|  | 
|  | 1 | +import os | 
|  | 2 | +import subprocess | 
|  | 3 | +import shutil | 
|  | 4 | + | 
|  | 5 | +from nmigen.build import * | 
|  | 6 | +from nmigen.vendor.lattice_ecp5 import * | 
|  | 7 | +from .resources import * | 
|  | 8 | + | 
|  | 9 | + | 
|  | 10 | +__all__ = ["ButterStickR1_0Platform"] | 
|  | 11 | + | 
|  | 12 | + | 
|  | 13 | +class ButterStickR1_0Platform(LatticeECP5Platform): | 
|  | 14 | +    device      = "LFE5U-25F" | 
|  | 15 | +    package     = "BG381" | 
|  | 16 | +    speed       = "8" | 
|  | 17 | +    default_clk = "clk" | 
|  | 18 | +    resources   = [ | 
|  | 19 | +        Resource("clk", 0, Pins("B12", dir="i"), | 
|  | 20 | +                 Clock(30e6), Attrs(IO_TYPE="LVCMOS33")), | 
|  | 21 | + | 
|  | 22 | +        # Used to reload FPGA configuration. | 
|  | 23 | +        Resource("program", 0, PinsN("R3", dir="o"), Attrs(IO_TYPE="LVCMOS33")), | 
|  | 24 | + | 
|  | 25 | +        # LED Anodes | 
|  | 26 | +        *LEDResources(pins="C13 D12 U2 T3 D13 E13", attrs=Attrs(IO_STANDARD="LVCMOS33")), | 
|  | 27 | +        # LED Cathodes. Use invert to default as on to allow LEDs to be used in white with single bit IO | 
|  | 28 | +        RGBLEDResource(0, r="T1", g="R1", b="U1", invert=True, attrs=Attrs(IO_TYPE="LVCMOS33")), | 
|  | 29 | + | 
|  | 30 | +        *ButtonResources( | 
|  | 31 | +            pins={0: "U16", 1: "T17" }, invert=True, | 
|  | 32 | +            attrs=Attrs(IO_TYPE="SSTL135_I")), | 
|  | 33 | + | 
|  | 34 | +        *SPIFlashResources(0, | 
|  | 35 | +            cs_n="R2", clk="U3", cipo="W2", copi="V2", wp_n="Y2", hold_n="W1", | 
|  | 36 | +            attrs=Attrs(IO_TYPE="LVCMOS33"), | 
|  | 37 | +        ), | 
|  | 38 | + | 
|  | 39 | +        Resource("ddr3", 0, | 
|  | 40 | +            Subsignal("rst",     PinsN("E17", dir="o")), | 
|  | 41 | +            Subsignal("clk",     DiffPairs("C20 J19", "D19 K19", dir="o"), Attrs(IO_TYPE="SSTL135D_I")), | 
|  | 42 | +            Subsignal("clk_en",  Pins("F18 J18", dir="o")), | 
|  | 43 | +            Subsignal("cs",      PinsN("J20 J16", dir="o")), | 
|  | 44 | +            Subsignal("we",      PinsN("G19", dir="o")), | 
|  | 45 | +            Subsignal("ras",     PinsN("K18", dir="o")), | 
|  | 46 | +            Subsignal("cas",     PinsN("J17", dir="o")), | 
|  | 47 | +            Subsignal("a",       Pins("G16 E19 E20 F16 F19 E16 F17 L20 M20 E18 G18 D18 H18 C18 D17 G20 ", dir="o")), | 
|  | 48 | +            Subsignal("ba",      Pins("H16 F20 H20", dir="o")), | 
|  | 49 | +            Subsignal("dqs",     DiffPairs("T19 N16", "R18 M18", dir="io"), | 
|  | 50 | +                      Attrs(IO_TYPE="SSTL135D_I", TERMINATION="OFF", | 
|  | 51 | +                            DIFFRESISTOR="100")), | 
|  | 52 | +            Subsignal("dq",      Pins("U19 T18 U18 R20 P18 P19 P20 N20 L19 L17 L16 R16 N18 R17 N17 P17", | 
|  | 53 | +                                      dir="io"), Attrs(TERMINATION="75")), | 
|  | 54 | +            Subsignal("dm",      Pins("U20 L18", dir="o")), | 
|  | 55 | +            Subsignal("odt",     Pins("K20 H17", dir="o")), | 
|  | 56 | +                 Attrs(IO_TYPE="SSTL135_I", SLEWRATE="FAST") | 
|  | 57 | +        ), | 
|  | 58 | + | 
|  | 59 | +        Resource("eth_rgmii", 0, | 
|  | 60 | +            Subsignal("rst",     PinsN("B20", dir="o")), | 
|  | 61 | +            Subsignal("mdc",     Pins("A19", dir="o")), | 
|  | 62 | +            Subsignal("mdio",    Pins("D16", dir="io")), | 
|  | 63 | +            Subsignal("tx_clk",  Pins("E15", dir="o")), | 
|  | 64 | +            Subsignal("tx_ctl",  Pins("D15", dir="o")), | 
|  | 65 | +            Subsignal("tx_data", Pins("C15 B16 A18 B19", dir="o")), | 
|  | 66 | +            Subsignal("rx_clk",  Pins("D11", dir="i")), | 
|  | 67 | +            Subsignal("rx_ctl",  Pins("B18", dir="i")), | 
|  | 68 | +            Subsignal("rx_data", Pins("A16 C17 B17 A17", dir="i")), | 
|  | 69 | +            Attrs(IO_TYPE="LVCMOS25") | 
|  | 70 | +        ), | 
|  | 71 | +        ULPIResource(0, data="B9 C6 A7 E9 A8 D9 C10 C7", | 
|  | 72 | +                     rst="C9", clk="B6", dir="A6", stp="C8", nxt="B8", | 
|  | 73 | +                     clk_dir="i", rst_invert=True, attrs=Attrs(IOSTANDARD="LVCMOS18")), | 
|  | 74 | +    ] | 
|  | 75 | +    connectors = [ | 
|  | 76 | +        Connector("syzygy", 0, { | 
|  | 77 | +            "S0_D0_P":   "G2", | 
|  | 78 | +            "S1_D1_P":   "J3", | 
|  | 79 | +            "S2_D0_N":   "F1", | 
|  | 80 | +            "S3_D1_N":   "K3", | 
|  | 81 | +            "S4_D2_P":   "J4", | 
|  | 82 | +            "S5_D3_P":   "K2", | 
|  | 83 | +            "S6_D2_N":   "J5", | 
|  | 84 | +            "S7_D3_N":   "J1", | 
|  | 85 | +            "S8_D4_P":   "N2", | 
|  | 86 | +            "S9_D5_P":   "L3", | 
|  | 87 | +            "S10_D4_N":  "M1", | 
|  | 88 | +            "S11_D5_N":  "L2", | 
|  | 89 | +            "S12_D6_P":  "N3", | 
|  | 90 | +            "S13_D7_P":  "N4", | 
|  | 91 | +            "S14_D6_N":  "M3", | 
|  | 92 | +            "S15_D7_N":  "P5", | 
|  | 93 | +            "S16":       "H1", | 
|  | 94 | +            "S17":       "K5", | 
|  | 95 | +            "S18":       "K4", | 
|  | 96 | +            "S19":       "K1", | 
|  | 97 | +            "S20":       "L4", | 
|  | 98 | +            "S21":       "L1", | 
|  | 99 | +            "S22":       "L5", | 
|  | 100 | +            "S23":       "M4", | 
|  | 101 | +            "S24":       "N1", | 
|  | 102 | +            "S25":       "N5", | 
|  | 103 | +            "S26":       "P3", | 
|  | 104 | +            "S28":       "P4", | 
|  | 105 | +            "C2P_CLK_N": "P2", | 
|  | 106 | +            "C2P_CLK_P": "P1", | 
|  | 107 | +            "P2C_CLK_N": "G1", | 
|  | 108 | +            "P2C_CLK_P": "H2", | 
|  | 109 | +        }), | 
|  | 110 | +        Connector("syzygy", 1, { | 
|  | 111 | +            "S0_D0_P":   "E4", | 
|  | 112 | +            "S1_D1_P":   "A4", | 
|  | 113 | +            "S2_D0_N":   "D5", | 
|  | 114 | +            "S3_D1_N":   "A5", | 
|  | 115 | +            "S4_D2_P":   "C4", | 
|  | 116 | +            "S5_D3_P":   "B2", | 
|  | 117 | +            "S6_D2_N":   "B4", | 
|  | 118 | +            "S7_D3_N":   "C2", | 
|  | 119 | +            "S8_D4_P":   "A2", | 
|  | 120 | +            "S9_D5_P":   "C1", | 
|  | 121 | +            "S10_D5_N":  "D1", | 
|  | 122 | +            "S11_D4_N":  "B1", | 
|  | 123 | +            "S12_D6_P":  "F4", | 
|  | 124 | +            "S13_D7_P":  "D2", | 
|  | 125 | +            "S14_D6_N":  "E3", | 
|  | 126 | +            "S15_D7_N":  "E1", | 
|  | 127 | +            "S16":       "B5", | 
|  | 128 | +            "S17":       "E5", | 
|  | 129 | +            "S18":       "F5", | 
|  | 130 | +            "S19":       "C5", | 
|  | 131 | +            "S20":       "B3", | 
|  | 132 | +            "S21":       "A3", | 
|  | 133 | +            "S22":       "D3", | 
|  | 134 | +            "S23":       "C3", | 
|  | 135 | +            "S24":       "H5", | 
|  | 136 | +            "S25":       "G5", | 
|  | 137 | +            "S26":       "H3", | 
|  | 138 | +            "S27":       "H4", | 
|  | 139 | +            "C2P_CLK_N": "F3", | 
|  | 140 | +            "C2P_CLK_P": "G3", | 
|  | 141 | +            "P2C_CLK_N": "E2", | 
|  | 142 | +            "P2C_CLK_P": "F2", | 
|  | 143 | +        }), | 
|  | 144 | +        Connector("syzygy", 2, { | 
|  | 145 | +            "S0":        "C11", | 
|  | 146 | +            "S1":        "B11", | 
|  | 147 | +            "S2":        "D6", | 
|  | 148 | +            "S3":        "D7", | 
|  | 149 | +            "S4":        "E6", | 
|  | 150 | +            "S5":        "E7", | 
|  | 151 | +            "S6":        "D8", | 
|  | 152 | +            "S7":        "E8", | 
|  | 153 | +            "S8":        "E10", | 
|  | 154 | +            "S9":        "D10", | 
|  | 155 | +            "RX0_N":     "Y6", | 
|  | 156 | +            "RX0_P":     "Y5", | 
|  | 157 | +            "RX1_N":     "Y8", | 
|  | 158 | +            "RX1_P":     "Y7", | 
|  | 159 | +            "RX2_N":     "Y15", | 
|  | 160 | +            "RX2_P":     "Y14", | 
|  | 161 | +            "RX3_N":     "Y17", | 
|  | 162 | +            "RX3_P":     "Y16", | 
|  | 163 | +            "TX0_N":     "W5", | 
|  | 164 | +            "TX0_P":     "W4", | 
|  | 165 | +            "TX1_N":     "W9", | 
|  | 166 | +            "TX1_P":     "W8", | 
|  | 167 | +            "TX2_N":     "W14", | 
|  | 168 | +            "TX2_P":     "W13", | 
|  | 169 | +            "TX3_N":     "W18", | 
|  | 170 | +            "TX3_P":     "W17", | 
|  | 171 | +            "C2P_CLK_N": "B10", | 
|  | 172 | +            "C2P_CLK_P": "A9", | 
|  | 173 | +            "P2C_CLK_N": "A11", | 
|  | 174 | +            "P2C_CLK_P": "A10", | 
|  | 175 | +            "REFCLK_N":  "Y12", | 
|  | 176 | +            "REFCLK_P":  "Y11", | 
|  | 177 | +        }), | 
|  | 178 | +    ] | 
|  | 179 | + | 
|  | 180 | +    @property | 
|  | 181 | +    def required_tools(self): | 
|  | 182 | +        return super().required_tools + [ | 
|  | 183 | +            "dfu-suffix" | 
|  | 184 | +        ] | 
|  | 185 | + | 
|  | 186 | +    @property | 
|  | 187 | +    def command_templates(self): | 
|  | 188 | +        return super().command_templates + [ | 
|  | 189 | +            r""" | 
|  | 190 | +            {{invoke_tool("dfu-suffix")}} | 
|  | 191 | +                -v 1209 -p 5af0 -a {{name}}.bit | 
|  | 192 | +            """ | 
|  | 193 | +        ] | 
|  | 194 | + | 
|  | 195 | +    def toolchain_prepare(self, fragment, name, **kwargs): | 
|  | 196 | +        overrides = dict(ecppack_opts="--compress --freq 38.8") | 
|  | 197 | +        overrides.update(kwargs) | 
|  | 198 | +        return super().toolchain_prepare(fragment, name, **overrides) | 
|  | 199 | + | 
|  | 200 | +    def toolchain_program(self, products, name): | 
|  | 201 | +        dfu_util = os.environ.get("DFU_UTIL", "dfu-util") | 
|  | 202 | +        with products.extract("{}.bit".format(name)) as bitstream_filename: | 
|  | 203 | +            subprocess.check_call([dfu_util, "-D", bitstream_filename]) | 
|  | 204 | + | 
|  | 205 | + | 
|  | 206 | +if __name__ == "__main__": | 
|  | 207 | +    from .test.blinky import * | 
|  | 208 | +    ButterStickR1_0Platform().build(Blinky(), do_program=True) | 
0 commit comments