|  | 
|  | 1 | +import os | 
|  | 2 | +import subprocess | 
|  | 3 | +import shutil | 
|  | 4 | + | 
|  | 5 | +from amaranth.build import * | 
|  | 6 | +from amaranth.vendor.lattice_ecp5 import * | 
|  | 7 | +from .resources import * | 
|  | 8 | + | 
|  | 9 | + | 
|  | 10 | +__all__ = ["ButterStickPlatform"] | 
|  | 11 | + | 
|  | 12 | + | 
|  | 13 | +class ButterStickPlatform(LatticeECP5Platform): | 
|  | 14 | +    device      = "LFE5UM5G-85F" | 
|  | 15 | +    package     = "BG381" | 
|  | 16 | +    speed       = "8" | 
|  | 17 | +    default_clk = "clk30" | 
|  | 18 | + | 
|  | 19 | +    def ulpi_io_type(self): | 
|  | 20 | +        return _vccio_iotype(2) | 
|  | 21 | + | 
|  | 22 | +    resources   = [ | 
|  | 23 | +        Resource("clk30", 0, Pins("B12", dir="i"), | 
|  | 24 | +                 Clock(30e6), Attrs(IO_TYPE="LVCMOS33")), | 
|  | 25 | + | 
|  | 26 | +        # LED Anodes | 
|  | 27 | +        *LEDResources(pins="C13 D12 U2 T3 D13 E13 C16", attrs=Attrs(IO_TYPE="LVCMOS33")), | 
|  | 28 | + | 
|  | 29 | +        # LED Cathodes. Use invert to default as on to allow LEDs to be used in white with single bit IO | 
|  | 30 | +        # note that G and B are swapped to match the LEDs and not the schematic labels | 
|  | 31 | +        RGBLEDResource(0, r="T1", g="U1", b="R1", invert=True, attrs=Attrs(IO_TYPE="LVCMOS33")), | 
|  | 32 | + | 
|  | 33 | +        *ButtonResources( | 
|  | 34 | +            pins={0: "U16", 1: "T17" }, invert=True, | 
|  | 35 | +            attrs=Attrs(IO_TYPE="SSTL135_I")), | 
|  | 36 | + | 
|  | 37 | +        *SPIFlashResources(0, | 
|  | 38 | +            cs_n="R2", clk="U3", cipo="V2", copi="W2", wp_n="Y2", hold_n="W1", | 
|  | 39 | +            attrs=Attrs(IO_TYPE="LVCMOS33", SLEWRATE="FAST"), | 
|  | 40 | +        ), | 
|  | 41 | + | 
|  | 42 | +        *SDCardResources("sdcard", 0, | 
|  | 43 | +            clk="B13", cmd="A13", dat0="C12", dat1="A12", dat2="D14", dat3="A14", | 
|  | 44 | +            attrs=Attrs(IO_TYPE="LVCMOS33", SLEWRATE="FAST"), | 
|  | 45 | +        ), | 
|  | 46 | + | 
|  | 47 | +        Resource("ddr3", 0, | 
|  | 48 | +            Subsignal("rst",     PinsN("E17", dir="o")), | 
|  | 49 | +            Subsignal("clk",     DiffPairs("C20", "J19", dir="o"), Attrs(IO_TYPE="SSTL135D_I")), | 
|  | 50 | +            Subsignal("clk_en",  Pins("F18 J18", dir="o")), | 
|  | 51 | +            Subsignal("cs",      PinsN("J20 J16", dir="o")), | 
|  | 52 | +            Subsignal("we",      PinsN("G19", dir="o")), | 
|  | 53 | +            Subsignal("ras",     PinsN("K18", dir="o")), | 
|  | 54 | +            Subsignal("cas",     PinsN("J17", dir="o")), | 
|  | 55 | +            Subsignal("a",       Pins("G16 E19 E20 F16 F19 E16 F17 L20 M20 E18 G18 D18 H18 C18 D17 G20", dir="o")), | 
|  | 56 | +            Subsignal("ba",      Pins("H16 F20 H20", dir="o")), | 
|  | 57 | +            Subsignal("dqs",     DiffPairs("T19 N16", "R18 M17", dir="io"), | 
|  | 58 | +                      Attrs(IO_TYPE="SSTL135D_I", TERMINATION="OFF", | 
|  | 59 | +                      DIFFRESISTOR="100")), | 
|  | 60 | +            Subsignal("dq",      Pins("U19 T18 U18 R20 P18 P19 P20 N20 L19 L17 L16 R16 N18 R17 N17 P17", | 
|  | 61 | +                                      dir="io"), Attrs(TERMINATION="75")), | 
|  | 62 | +            Subsignal("dm",      Pins("U20 L18", dir="o")), | 
|  | 63 | +            Subsignal("odt",     Pins("K20 H17", dir="o")), | 
|  | 64 | +            Attrs(IO_TYPE="SSTL135_I", SLEWRATE="FAST") | 
|  | 65 | +        ), | 
|  | 66 | + | 
|  | 67 | +        Resource("eth_rgmii", 0, | 
|  | 68 | +            Subsignal("rst",     PinsN("B20", dir="o")), | 
|  | 69 | +            Subsignal("mdc",     Pins("A19", dir="o")), | 
|  | 70 | +            Subsignal("mdio",    Pins("D16", dir="io")), | 
|  | 71 | +            Subsignal("tx_clk",  Pins("E15", dir="o")), | 
|  | 72 | +            Subsignal("tx_ctl",  Pins("D15", dir="o")), | 
|  | 73 | +            Subsignal("tx_data", Pins("C15 B16 A18 B19", dir="o")), | 
|  | 74 | +            Subsignal("rx_clk",  Pins("D11", dir="i")), | 
|  | 75 | +            Subsignal("rx_ctl",  Pins("B18", dir="i")), | 
|  | 76 | +            Subsignal("rx_data", Pins("A16 C17 B17 A17", dir="i")), | 
|  | 77 | +            Attrs(IO_TYPE="LVCMOS33", SLEWRATE="FAST") | 
|  | 78 | +        ), | 
|  | 79 | + | 
|  | 80 | +        ULPIResource(0, data="B9 C6 A7 E9 A8 D9 C10 C7", | 
|  | 81 | +                     rst="C9", clk="B6", dir="A6", stp="C8", nxt="B8", | 
|  | 82 | +                     clk_dir="o", rst_invert=True, attrs=Attrs(IO_TYPE="LVCMOS18")), | 
|  | 83 | + | 
|  | 84 | +        I2CResource(0, scl="E14", sda="C14", | 
|  | 85 | +                    attrs=Attrs(IO_TYPE="LVCMOS33")), | 
|  | 86 | + | 
|  | 87 | +        # SYGYZY VIO level control pwm pins (use with care) | 
|  | 88 | +        Resource("vccio_ctrl", 0, | 
|  | 89 | +                 Subsignal("pdm", Pins("V1 E11 T2", dir="o")), | 
|  | 90 | +                 Subsignal("en", Pins("E12", dir="o")), | 
|  | 91 | +                 Attrs(IO_TYPE="LVCMOS33") | 
|  | 92 | +        ), | 
|  | 93 | +        # Used to reload FPGA configuration (drives program_n) | 
|  | 94 | +        Resource("program", 0, PinsN("R3", dir="o"), Attrs(IO_TYPE="LVCMOS33")), | 
|  | 95 | +    ] | 
|  | 96 | +    connectors = [ | 
|  | 97 | +        Connector("syzygy", 0, { | 
|  | 98 | +            # single ended | 
|  | 99 | +            "S0":"G2",  "S1":"J3", | 
|  | 100 | +            "S2":"F1",  "S3":"K3", | 
|  | 101 | +            "S4":"J4",  "S5":"K2", | 
|  | 102 | +            "S6":"J5",  "S7":"J1", | 
|  | 103 | +            "S8":"N2",  "S9":"L3", | 
|  | 104 | +            "S10":"M1", "S11":"L2", | 
|  | 105 | +            "S12":"N3", "S13":"N4", | 
|  | 106 | +            "S14":"M3", "S15":"P5", | 
|  | 107 | +            "S16":"H1", "S17":"K5", | 
|  | 108 | +            "S18":"K4", "S19":"K1", | 
|  | 109 | +            "S20":"L4", "S21":"L1", | 
|  | 110 | +            "S22":"L5", "S23":"M4", | 
|  | 111 | +            "S24":"N1", "S25":"N5", | 
|  | 112 | +            "S26":"P3", "S27":"P4", | 
|  | 113 | +            "S28":"H2", "S29":"P1", | 
|  | 114 | +            "S30":"G1", "S31":"P2", | 
|  | 115 | +            # diff pairs | 
|  | 116 | + | 
|  | 117 | +        }), | 
|  | 118 | +        Connector("syzygy", 1, { | 
|  | 119 | +            # single ended | 
|  | 120 | +            "S0": "E4", "S1": "A4", | 
|  | 121 | +            "S2": "D5", "S3": "A5", | 
|  | 122 | +            "S4": "C4", "S5": "B2", | 
|  | 123 | +            "S6": "B4", "S7": "C2", | 
|  | 124 | +            "S8": "A2", "S9": "C1", | 
|  | 125 | +            "S10":"B1", "S11":"D1", | 
|  | 126 | +            "S12":"F4", "S13":"D2", | 
|  | 127 | +            "S14":"E3", "S15":"E1", | 
|  | 128 | + | 
|  | 129 | +            "S16":"B5", "S17":"E5", | 
|  | 130 | +            "S18":"F5", "S19":"C5", | 
|  | 131 | +            "S20":"B3", "S21":"A3", | 
|  | 132 | +            "S22":"D3", "S23":"C3", | 
|  | 133 | +            "S24":"H5", "S25":"G5", | 
|  | 134 | +            "S26":"H3", "S27":"H4", | 
|  | 135 | +            "S28":"F2", "S29":"G3", | 
|  | 136 | +            "S30":"E2", "S31":"F3", | 
|  | 137 | +             | 
|  | 138 | +            # diff pairs | 
|  | 139 | +            "D0P":"E4", "D0N":"D5", | 
|  | 140 | +            "D1P":"A4", "D1N":"A5", | 
|  | 141 | +            "D2P":"C4", "D2N":"B4", | 
|  | 142 | +            "D3P":"B2", "D3N":"C2", | 
|  | 143 | +            "D4P":"A2", "D4N":"B1", | 
|  | 144 | +            "D5P":"C1", "D5N":"D1", | 
|  | 145 | +            "D6P":"F4", "D6N":"E3", | 
|  | 146 | +            "D7P":"D2", "D7N":"E1", | 
|  | 147 | +        }), | 
|  | 148 | +    ] | 
|  | 149 | + | 
|  | 150 | +    def __init__(self, *, vccio_enable=True, vccio_voltages = [ 3.3, 3.3, 1.8 ], **kwargs): | 
|  | 151 | +        super().__init__(**kwargs) | 
|  | 152 | +        self._vccio_enable   = vccio_enable | 
|  | 153 | +        self._vccio_voltages = vccio_voltages | 
|  | 154 | + | 
|  | 155 | +    def vccio_voltage(self, vccio_index): | 
|  | 156 | +        if not self._vccio_enable: | 
|  | 157 | +            return None | 
|  | 158 | +        else: | 
|  | 159 | +            return self._vccio_voltages[vccio_index] | 
|  | 160 | + | 
|  | 161 | +    def _vccio_iotype(self, vccio_index): | 
|  | 162 | +        if not self._vccio_enable or self._vccio_voltages[vccio_index] == 3.3: | 
|  | 163 | +            return "LVCMOS33" | 
|  | 164 | +        if self._vccio_voltages[vccio_index] == 2.5: | 
|  | 165 | +            return "LVCMOS25" | 
|  | 166 | +        if self._vccio_voltages[vccio_index] == 1.8: | 
|  | 167 | +            return "LVCMOS18" | 
|  | 168 | +        assert False | 
|  | 169 | + | 
|  | 170 | +    @property | 
|  | 171 | +    def required_tools(self): | 
|  | 172 | +        return super().required_tools + [ | 
|  | 173 | +            "dfu-suffix" | 
|  | 174 | +        ] | 
|  | 175 | + | 
|  | 176 | +    @property | 
|  | 177 | +    def command_templates(self): | 
|  | 178 | +        return super().command_templates + [ | 
|  | 179 | +            r""" | 
|  | 180 | +            {{invoke_tool("dfu-suffix")}} | 
|  | 181 | +                -v 1209 -p 5af1 -a {{name}}.bit | 
|  | 182 | +            """ | 
|  | 183 | +        ] | 
|  | 184 | + | 
|  | 185 | +    def toolchain_prepare(self, fragment, name, **kwargs): | 
|  | 186 | +        overrides = dict(ecppack_opts="--compress --freq 38.8") | 
|  | 187 | +        overrides.update(kwargs) | 
|  | 188 | +        return super().toolchain_prepare(fragment, name, **overrides) | 
|  | 189 | + | 
|  | 190 | +    def toolchain_program(self, products, name): | 
|  | 191 | +        dfu_util = os.environ.get("DFU_UTIL", "dfu-util") | 
|  | 192 | +        with products.extract("{}.bit".format(name)) as bitstream_filename: | 
|  | 193 | +            subprocess.check_call([dfu_util, "-a", "0", "-D", bitstream_filename, "-R"]) | 
|  | 194 | + | 
|  | 195 | + | 
|  | 196 | +if __name__ == "__main__": | 
|  | 197 | +    from .test.blinky import * | 
|  | 198 | +    ButterStickPlatform().build(Blinky(), do_program=True) | 
0 commit comments