示例#1
0
    def __init__(self, pads):
        self.intro = ModuleDoc("""BtPower - power control pins (EC)""")

        self.power = CSRStorage(
            8,
            fields=[
                CSRField(
                    "self",
                    description="Writing `1` to this keeps the EC powered on",
                    reset=1),
                CSRField("soc_on",
                         description="Writing `1` to this powers on the SoC",
                         reset=1),
                CSRField(
                    "discharge",
                    description=
                    "Writing `1` to this connects a low-value resistor across FPGA domain supplies to force a full discharge"
                ),
                CSRField(
                    "kbdscan",
                    size=2,
                    description=
                    "Writing `1` to this forces the power-down keyboard scan event on the respective mon bit"
                ),
                CSRField(
                    "kbddrive",
                    description=
                    "Writing `1` to this drives the input scan row to 0. Do this prior to reading to mitigate noise"
                )
            ])

        self.stats = CSRStatus(
            8,
            fields=[
                CSRField("state",
                         size=2,
                         description="Current power state of the SOC"),
                CSRField("monkey",
                         size=2,
                         description="Power-on key monitor input"),
            ])
        self.mon0 = Signal()
        self.mon1 = Signal()
        self.soc_on = Signal()
        self.comb += [
            pads.sys_on.eq(self.power.fields.self),
            pads.u_to_t_on.eq(self.power.fields.soc_on),
            pads.fpga_dis.eq(self.power.fields.discharge),
            self.stats.fields.state.eq(Cat(pads.s0, pads.s1)),
            self.stats.fields.monkey.eq(Cat(self.mon0, self.mon1)),
            self.soc_on.eq(self.power.fields.soc_on),
        ]
示例#2
0
    def __init__(self, pads):
        touch1 = TSTriple()
        touch2 = TSTriple()
        touch3 = TSTriple()
        touch4 = TSTriple()
        self.specials += touch1.get_tristate(pads.t1)
        self.specials += touch2.get_tristate(pads.t2)
        self.specials += touch3.get_tristate(pads.t3)
        self.specials += touch4.get_tristate(pads.t4)

        self.o = CSRStorage(size=4)
        self.oe = CSRStorage(size=4)
        self.i = CSRStatus(size=4)

        self.comb += [
            touch1.o.eq(self.o.storage[0]),
            touch2.o.eq(self.o.storage[1]),
            touch3.o.eq(self.o.storage[2]),
            touch4.o.eq(self.o.storage[3]),
            touch1.oe.eq(self.oe.storage[0]),
            touch2.oe.eq(self.oe.storage[1]),
            touch3.oe.eq(self.oe.storage[2]),
            touch4.oe.eq(self.oe.storage[3]),
            self.i.status.eq(Cat(touch1.i, touch2.i, touch3.i, touch4.i))
        ]
示例#3
0
 def request_all(self, name):
     r = []
     while True:
         try:
             r.append(self.request(name, len(r)))
         except ConstraintError:
             break
     if not len(r):
         raise ValueError
     return Cat(r)
示例#4
0
 def request_remaining(self, name):
     r = []
     while True:
         try:
             r.append(self.request(name))
         except ConstraintError:
             break
     if not len(r):
         raise ValueError(f"Could not request any pins named '{name}'")
     return Cat(r)
示例#5
0
 def request_all(self, name):
     r = []
     while True:
         try:
             r.append(self.request(name, len(r)))
         except ConstraintError:
             break
     if not len(r):
         raise ValueError(f"Could not request some pin(s) named '{name}'")
     return Cat(r)
示例#6
0
    def __init__(self, pads):
        self.intro = ModuleDoc("""BtPower - power control pins (EC)""")

        self.power = CSRStorage(
            8,
            fields=[
                CSRField(
                    "self",
                    description="Writing `1` to this keeps the EC powered on",
                    reset=1),
                CSRField("soc_on",
                         description="Writing `1` to this powers on the SoC",
                         reset=1),
                #CSRField("discharge", description="Writing `1` to this connects a low-value resistor across FPGA domain supplies to force a full discharge"),
                CSRField(
                    "kbddrive",
                    description=
                    "Writing `1` to this drives the scan column to 1. Do this prior to reading to mitigate noise"
                )
            ])

        self.stats = CSRStatus(
            8,
            fields=[
                CSRField("state",
                         size=1,
                         description="Current power state of the SOC"),
                CSRField("monkey",
                         size=2,
                         description="Power-on key monitor input"),
            ])
        self.mon0 = Signal()
        self.mon1 = Signal()
        self.soc_on = Signal()
        self.comb += [
            pads.sys_on.eq(self.power.fields.self),
            pads.u_to_t_on.eq(self.power.fields.soc_on),
            pads.fpga_dis.eq(
                ~pads.s0
            ),  # make this automatic: if the FPGA is reporting itself as off, discharge the rails
            self.stats.fields.state.eq(pads.s0),
            self.stats.fields.monkey.eq(Cat(self.mon0, self.mon1)),
            self.soc_on.eq(self.power.fields.soc_on),
        ]
示例#7
0
    def __init__(self, platform, pads):
        self.reset = Signal()

        mosi_pad = TSTriple()
        miso_pad = TSTriple()
        cs_n_pad = TSTriple()
        clk_pad = TSTriple()
        wp_pad = TSTriple()
        hold_pad = TSTriple()

        self.do = CSRStorage(size=6)
        self.oe = CSRStorage(size=6)
        self.di = CSRStatus(size=6)

        self.specials += mosi_pad.get_tristate(pads.mosi)
        self.specials += miso_pad.get_tristate(pads.miso)
        self.specials += cs_n_pad.get_tristate(pads.cs_n)
        self.specials += clk_pad.get_tristate(pads.clk)
        self.specials += wp_pad.get_tristate(pads.wp)
        self.specials += hold_pad.get_tristate(pads.hold)

        self.comb += [
            mosi_pad.oe.eq(self.oe.storage[0]),
            miso_pad.oe.eq(self.oe.storage[1]),
            wp_pad.oe.eq(self.oe.storage[2]),
            hold_pad.oe.eq(self.oe.storage[3]),
            clk_pad.oe.eq(self.oe.storage[4]),
            cs_n_pad.oe.eq(self.oe.storage[5]),
            mosi_pad.o.eq(self.do.storage[0]),
            miso_pad.o.eq(self.do.storage[1]),
            wp_pad.o.eq(self.do.storage[2]),
            hold_pad.o.eq(self.do.storage[3]),
            clk_pad.o.eq(self.do.storage[4]),
            cs_n_pad.o.eq(self.do.storage[5]),
            self.di.status.eq(
                Cat(mosi_pad.i, miso_pad.i, wp_pad.i, hold_pad.i, clk_pad.i,
                    cs_n_pad.i)),
        ]
示例#8
0
    def __init__(self, platform, pads, size=2*1024*1024):
        self.intro = ModuleDoc("See https://github.com/cliffordwolf/picorv32/tree/master/picosoc#spi-flash-controller-config-register; used with modifications")
        self.size = size

        self.bus = bus = wishbone.Interface()

        self.reset = Signal()

        cfg = Signal(32)
        cfg_we = Signal(4)
        cfg_out = Signal(32)

        # Add pulse the cfg_we line after reset
        reset_counter = Signal(2, reset=3)
        ic_reset = Signal(reset=1)
        self.sync += \
            If(reset_counter != 0,
                reset_counter.eq(reset_counter - 1)
            ).Else(
                ic_reset.eq(0)
            )

        self.rdata = CSRStatus(fields=[
            CSRField("data", size=4, description="Data bits from SPI [3:hold, 2:wp, 1:cipo, 0:copi]"),
        ])
        self.mode = CSRStorage(fields=[
            CSRField("bitbang", size=1, description="Turn on bitbang mode", reset = 0),
            CSRField("csn", size=1, description="Chip select (set to `0` to select the chip)"),
        ])
        self.wdata = CSRStorage(description="Writes to this field automatically pulse CLK", fields=[
            CSRField("data", size=4, description="Data bits to SPI [3:hold, 2:wp, 1:cipo, 0:copi]"),
            CSRField("oe", size=4, description="Output enable for data pins"),
        ])
        bb_clk = Signal()
        self.sync += [
            bb_clk.eq(self.wdata.re), # auto-clock the SPI chip whenever wdata is written. Delay a cycle for setup/hold.
        ]

        copi_pad = TSTriple()
        cipo_pad = TSTriple()
        cs_n_pad = TSTriple()
        clk_pad  = TSTriple()
        wp_pad   = TSTriple()
        hold_pad = TSTriple()
        self.specials += copi_pad.get_tristate(pads.copi)
        self.specials += cipo_pad.get_tristate(pads.cipo)
        self.specials += cs_n_pad.get_tristate(pads.cs_n)
        self.specials += clk_pad.get_tristate(pads.clk)
        self.specials += wp_pad.get_tristate(pads.wp)
        self.specials += hold_pad.get_tristate(pads.hold)

        reset = Signal()
        self.comb += [
            reset.eq(ResetSignal() | self.reset),
            cs_n_pad.oe.eq(~reset),
            clk_pad.oe.eq(~reset),
        ]

        flash_addr = Signal(24)
        # size/4 because data bus is 32 bits wide, -1 for base 0
        mem_bits = bits_for(int(size/4)-1)
        pad = Signal(2)
        self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits-1]))

        read_active = Signal()
        spi_ready = Signal()
        self.sync += [
            If(bus.stb & bus.cyc & ~read_active,
                read_active.eq(1),
                bus.ack.eq(0),
            )
            .Elif(read_active & spi_ready,
                read_active.eq(0),
                bus.ack.eq(1),
            )
            .Else(
                bus.ack.eq(0),
                read_active.eq(0),
            )
        ]

        o_rdata = Signal(32)
        self.comb += bus.dat_r.eq(o_rdata)

        self.specials += Instance("spimemio",
            o_flash_io0_oe = copi_pad.oe,
            o_flash_io1_oe = cipo_pad.oe,
            o_flash_io2_oe = wp_pad.oe,
            o_flash_io3_oe = hold_pad.oe,

            o_flash_io0_do = copi_pad.o,
            o_flash_io1_do = cipo_pad.o,
            o_flash_io2_do = wp_pad.o,
            o_flash_io3_do = hold_pad.o,
            o_flash_csb    = cs_n_pad.o,
            o_flash_clk    = clk_pad.o,

            i_flash_io0_di = copi_pad.i,
            i_flash_io1_di = cipo_pad.i,
            i_flash_io2_di = wp_pad.i,
            i_flash_io3_di = hold_pad.i,

            i_resetn = ~reset,
            i_clk = ClockSignal(),

            i_valid = bus.stb & bus.cyc,
            o_ready = spi_ready,
            i_addr  = flash_addr,
            o_rdata = o_rdata,

            i_bb_oe = self.wdata.fields.oe,
            i_bb_wd = self.wdata.fields.data,
            i_bb_clk = bb_clk,
            i_bb_csb = self.mode.fields.csn,
            o_bb_rd = self.rdata.fields.data,
            i_config_update = self.mode.re | ic_reset,
            i_memio_enable = ~self.mode.fields.bitbang,
        )
        platform.add_source("rtl/spimemio.v")
示例#9
0
    def __init__(self, platform, pads, size=2 * 1024 * 1024):
        self.size = size

        self.bus = bus = wishbone.Interface()

        self.reset = Signal()

        self.cfg1 = CSRStorage(size=8)
        self.cfg2 = CSRStorage(size=8)
        self.cfg3 = CSRStorage(size=8)
        self.cfg4 = CSRStorage(size=8)

        self.stat1 = CSRStatus(size=8)
        self.stat2 = CSRStatus(size=8)
        self.stat3 = CSRStatus(size=8)
        self.stat4 = CSRStatus(size=8)

        cfg = Signal(32)
        cfg_we = Signal(4)
        cfg_out = Signal(32)
        self.comb += [
            cfg.eq(
                Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage,
                    self.cfg4.storage)),
            cfg_we.eq(
                Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re, self.cfg4.re)),
            self.stat1.status.eq(cfg_out[0:8]),
            self.stat2.status.eq(cfg_out[8:16]),
            self.stat3.status.eq(cfg_out[16:24]),
            self.stat4.status.eq(cfg_out[24:32]),
        ]

        mosi_pad = TSTriple()
        miso_pad = TSTriple()
        cs_n_pad = TSTriple()
        clk_pad = TSTriple()
        wp_pad = TSTriple()
        hold_pad = TSTriple()
        self.specials += mosi_pad.get_tristate(pads.mosi)
        self.specials += miso_pad.get_tristate(pads.miso)
        self.specials += cs_n_pad.get_tristate(pads.cs_n)
        self.specials += clk_pad.get_tristate(pads.clk)
        self.specials += wp_pad.get_tristate(pads.wp)
        self.specials += hold_pad.get_tristate(pads.hold)

        reset = Signal()
        self.comb += [
            reset.eq(ResetSignal() | self.reset),
            cs_n_pad.oe.eq(~reset),
            clk_pad.oe.eq(~reset),
        ]

        flash_addr = Signal(24)
        # size/4 because data bus is 32 bits wide, -1 for base 0
        mem_bits = bits_for(int(size / 4) - 1)
        pad = Signal(2)
        self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits - 1]))

        read_active = Signal()
        spi_ready = Signal()
        self.sync += [
            If(
                bus.stb & bus.cyc & ~read_active,
                read_active.eq(1),
                bus.ack.eq(0),
            ).Elif(
                read_active & spi_ready,
                read_active.eq(0),
                bus.ack.eq(1),
            ).Else(
                bus.ack.eq(0),
                read_active.eq(0),
            )
        ]

        o_rdata = Signal(32)
        self.comb += bus.dat_r.eq(o_rdata)

        self.specials += Instance(
            "spimemio",
            o_flash_io0_oe=mosi_pad.oe,
            o_flash_io1_oe=miso_pad.oe,
            o_flash_io2_oe=wp_pad.oe,
            o_flash_io3_oe=hold_pad.oe,
            o_flash_io0_do=mosi_pad.o,
            o_flash_io1_do=miso_pad.o,
            o_flash_io2_do=wp_pad.o,
            o_flash_io3_do=hold_pad.o,
            o_flash_csb=cs_n_pad.o,
            o_flash_clk=clk_pad.o,
            i_flash_io0_di=mosi_pad.i,
            i_flash_io1_di=miso_pad.i,
            i_flash_io2_di=wp_pad.i,
            i_flash_io3_di=hold_pad.i,
            i_resetn=~reset,
            i_clk=ClockSignal(),
            i_valid=bus.stb & bus.cyc,
            o_ready=spi_ready,
            i_addr=flash_addr,
            o_rdata=o_rdata,
            i_cfgreg_we=cfg_we,
            i_cfgreg_di=cfg,
            o_cfgreg_do=cfg_out,
        )
        platform.add_source("rtl/spimemio.v")
示例#10
0
    def __init__(self, sys_clk_freq=int(200e6), disable_sdram=False, **kwargs):
        platform = ted_tfoil.Platform()

        SoCCore.__init__(self,
                         platform,
                         sys_clk_freq,
                         ident="LiteX SoC on tfoil",
                         ident_version=True,
                         **kwargs)

        self.submodules.crg = _CRG(platform, sys_clk_freq)

        if not disable_sdram:
            if not self.integrated_main_ram_size:
                self.submodules.ddrphy = usddrphy.USPDDRPHY(
                    platform.request("ddram"),
                    memtype="DDR4",
                    sys_clk_freq=sys_clk_freq,
                    iodelay_clk_freq=400e6)
                self.add_sdram("sdram",
                               phy=self.ddrphy,
                               module=MT40A1G8(sys_clk_freq, "1:4"),
                               size=0x40000000,
                               l2_cache_size=kwargs.get("l2_size", 8192))

        self.submodules.leds = LedChaser(pads=platform.request_all("user_led"),
                                         sys_clk_freq=sys_clk_freq)

        i2c_master_pads = [
            platform.request("i2c_tca9555", 0),
            platform.request("i2c_tca9555", 1),
            platform.request("i2c_tca9555", 2),
            platform.request("i2c_tca9555", 3),
            platform.request("i2c_tca9555", 4),
            platform.request("i2c_tca9555", 5),
            platform.request("i2c_tca9555", 6),
            platform.request("i2c_tca9548", 0),
            platform.request("i2c_tca9548", 1),
            platform.request("i2c_tca9548", 2),
            platform.request("i2c_tca9548", 3),
            platform.request("i2c_si5341", 0),
            platform.request("i2c_si5341", 1),
        ]

        self.submodules.i2c = I2CMasterMP(platform, i2c_master_pads)

        self.submodules.sb_tca9548 = GPIOOut(
            pads=platform.request_all("tca9548_reset_n"))

        sb_si5341_o_pads = Cat([
            platform.request("si5341_in_sel_0", 0),
            platform.request("si5341_in_sel_0", 1),
            platform.request("si5341_syncb", 0),
            platform.request("si5341_syncb", 1),
            platform.request("si5341_rstb", 0),
            platform.request("si5341_rstb", 1),
        ])
        sb_si5341_i_pads = Cat([
            platform.request("si5341_lolb", 0),
            platform.request("si5341_lolb", 1),
        ])
        self.submodules.sb_si5341_o = GPIOOut(pads=sb_si5341_o_pads)
        self.submodules.sb_si5341_i = GPIOIn(pads=sb_si5341_i_pads)

        self._add_aurora(platform)
示例#11
0
    def __init__(self):

        self.specials.rom = Memory(16, 4096, rom_image)
        rom_port = self.rom.get_port(write_capable=False)
        self.specials += rom_port

        self.specials.ram = Memory(8, 8192, rom_image)
        ram_port = self.ram.get_port(write_capable=True)
        self.specials += ram_port

        program_counter = Signal(16)
        self.sync += program_counter.eq(program_counter + 1)
        self.comb += rom_port.adr.eq(program_counter)

        accumulator = Signal(8)

        op_code = Signal(3)
        op_mode = Signal(3)
        op_bus = Signal(2)
        op_data = Signal(8)
        Cat(op_bus, op_mode, op_code, op_data).eq(rom_port.dat_r)
     
        sig_ar0 = Signal()
        sig_ar0.eq((op_code == OP_SUB) | (op_code == OP_BCC))
        sig_ar1 = Signal()
        sig_ar1.eq((op_code == OP_OR) | (op_code == OP_XOR) | (op_code == OP_SUB))
        sig_ar2 = Signal()
        sig_ar2.eq((op_code == OP_LD) | (op_code == OP_OR) | (op_code == OP_XOR) | (op_code == OP_ADD) | (op_code == OP_BCC))
        sig_ar3 = Signal()
        sig_ar3.eq((op_code == OP_LD) | (op_code == OP_AND) | (op_code == OP_OR) | (op_code == OP_ADD))
        sig_al = Signal()
        sig_al.eq((op_code == OP_BCC) | (~op_code[2]))

        sig_xl = Signal()
        sig_xl.eq(op_mode != MOD_DX)
        sig_yl = Signal()
        sig_yl.eq(op_mode != MOD_DY)
        sig_ix = Signal()
        sig_ix.eq(op_mode == MOD_YXOUT) 
        sig_eh = Signal()
        sig_eh.eq((op_mode != MOD_YDAC) & (op_mode != MOD_YXAC) & (op_mode != MOD_YXOUT))
        sig_el = Signal()
        sig_el.eq((op_mode != MOD_XAC) & (op_mode != MOD_YXAC) & (op_mode != MOD_YXOUT))
        
        sig_ol = Signal()
        sig_ol.eq(((op_mode != MOD_DOUT) & (op_mode != MOD_YXOUT)) | (op_code == OP_ST))
        sig_ld = Signal()
        sig_ld.eq(((op_mode != MOD_DAC) & (op_mode != MOD_XAC) & (op_mode != MOD_YDAC) & (op_mode != MOD_YXAC)) | (op_code == OP_ST))

        # this isn't quite right, in the schematic it's all about AC7 and the
        # carry-out of the ALU adder, hmmm.

        sig_cond = Signal()
        sig_cond.eq(
                (op_mode == MOD_JMP) | (op_mode == MOD_BRA) |
                ((op_mode == MOD_BNE) & (accumulator != 0)) |
                ((op_mode == MOD_BEQ) & (accumulator == 0)) |
                ((op_mode == MOD_BLT) & (accumulator < 0)) |
                ((op_mode == MOD_BGT) & (accumulator > 0)) |
                ((op_mode == MOD_BLE) & (accumulator <= 0)) |
                ((op_mode == MOD_BGE) & (accumulator >= 0))
        )

        sig_ph = Signal()
        sig_ph.eq((op_code == OP_BCC) & (op_mode == MOD_JMP))
        sig_pl = Signal()
        sig_pl.eq((op_code == OP_BCC) & sig_cond)
        
        data_bus = Signal(8)

        Case(op_bus, {
            0: data_bus.eq(op_data),
            1: data_bus.eq(ram_port.dat_r),
            2: data_bus.eq(accumulator),
            3: data_bus.eq(dinput),
        })

        register_x = Signal(8)
        register_y = Signal(8)
        ram_addr_l = Signal(8)
        ram_addr_h = Signal(8)
        ram_addr_l.eq(Mux(sig_el, register_x, data_bus))
        ram_addr_h.eq(Mux(sig_eh, register_y, 0))
        self.comb += ram_port.adr.eq(Cat(ram_addr_l, ram_addr_h))

        self.comb += ram_port.we.eq(rom_port.dat_r[0])
        self.comb += ram_port.dat_w.eq(rom_port.dat_r[0:8])
        self.comb += output.eq(ram_port.dat_r[0:8])
示例#12
0
    def __init__(self, platform, pads, size=2 * 1024 * 1024):
        self.intro = ModuleDoc(
            "See https://github.com/cliffordwolf/picorv32/tree/master/picosoc#spi-flash-controller-config-register"
        )
        self.size = size

        self.bus = bus = wishbone.Interface()

        self.reset = Signal()

        self.cfg1 = CSRStorage(size=8)
        self.cfg2 = CSRStorage(size=8)
        self.cfg3 = CSRStorage(
            size=8, reset=0x24
        )  # set 1 for qspi (bit 21); lower 4 bits is "dummy" cycles
        self.cfg4 = CSRStorage(size=8)

        self.stat = CSRStatus(size=32)

        cfg = Signal(32)
        cfg_we = Signal(4)
        cfg_out = Signal(32)

        # Add pulse the cfg_we line after reset
        reset_counter = Signal(2, reset=3)
        ic_reset = Signal(reset=1)
        self.sync += \
            If(reset_counter != 0,
                reset_counter.eq(reset_counter - 1)
            ).Else(
                ic_reset.eq(0)
            )

        self.comb += [
            cfg.eq(
                Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage,
                    self.cfg4.storage)),
            cfg_we.eq(
                Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re | ic_reset,
                    self.cfg4.re)),
            self.stat.status.eq(cfg_out),
        ]

        copi_pad = TSTriple()
        cipo_pad = TSTriple()
        cs_n_pad = TSTriple()
        clk_pad = TSTriple()
        wp_pad = TSTriple()
        hold_pad = TSTriple()
        self.specials += copi_pad.get_tristate(pads.copi)
        self.specials += cipo_pad.get_tristate(pads.cipo)
        self.specials += cs_n_pad.get_tristate(pads.cs_n)
        self.specials += clk_pad.get_tristate(pads.clk)
        self.specials += wp_pad.get_tristate(pads.wp)
        self.specials += hold_pad.get_tristate(pads.hold)

        reset = Signal()
        self.comb += [
            reset.eq(ResetSignal() | self.reset),
            cs_n_pad.oe.eq(~reset),
            clk_pad.oe.eq(~reset),
        ]

        flash_addr = Signal(24)
        # size/4 because data bus is 32 bits wide, -1 for base 0
        mem_bits = bits_for(int(size / 4) - 1)
        pad = Signal(2)
        self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits - 1]))

        read_active = Signal()
        spi_ready = Signal()
        self.sync += [
            If(
                bus.stb & bus.cyc & ~read_active,
                read_active.eq(1),
                bus.ack.eq(0),
            ).Elif(
                read_active & spi_ready,
                read_active.eq(0),
                bus.ack.eq(1),
            ).Else(
                bus.ack.eq(0),
                read_active.eq(0),
            )
        ]

        o_rdata = Signal(32)
        self.comb += bus.dat_r.eq(o_rdata)

        self.specials += Instance(
            "spimemio",
            o_flash_io0_oe=copi_pad.oe,
            o_flash_io1_oe=cipo_pad.oe,
            o_flash_io2_oe=wp_pad.oe,
            o_flash_io3_oe=hold_pad.oe,
            o_flash_io0_do=copi_pad.o,
            o_flash_io1_do=cipo_pad.o,
            o_flash_io2_do=wp_pad.o,
            o_flash_io3_do=hold_pad.o,
            o_flash_csb=cs_n_pad.o,
            o_flash_clk=clk_pad.o,
            i_flash_io0_di=copi_pad.i,
            i_flash_io1_di=cipo_pad.i,
            i_flash_io2_di=wp_pad.i,
            i_flash_io3_di=hold_pad.i,
            i_resetn=~reset,
            i_clk=ClockSignal(),
            i_valid=bus.stb & bus.cyc,
            o_ready=spi_ready,
            i_addr=flash_addr,
            o_rdata=o_rdata,
            i_cfgreg_we=cfg_we,
            i_cfgreg_di=cfg,
            o_cfgreg_do=cfg_out,
        )
        platform.add_source("rtl/spimemio.v")