mirror of
https://github.com/im-tomu/foboot.git
synced 2024-09-20 02:40:09 +00:00
45e3b5b617
These are all independent modules, so break each one out into its own file. Signed-off-by: Sean Cross <sean@xobs.io>
127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
from migen import Module, Signal, Cat, TSTriple, bits_for, ResetSignal, If, ClockSignal, Instance
|
|
from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage, CSRField
|
|
from litex.soc.interconnect import wishbone
|
|
|
|
class PicoRVSpi(Module, AutoCSR):
|
|
def __init__(self, platform, pads, size=2*1024*1024):
|
|
self.size = size
|
|
|
|
self.bus = bus = wishbone.Interface()
|
|
|
|
self.reset = Signal()
|
|
|
|
self.cfg1 = CSRStorage(fields=[
|
|
CSRField("bb_out", size=4, description="Output bits in bit-bang mode"),
|
|
CSRField("bb_clk", description="Serial clock line in bit-bang mode"),
|
|
CSRField("bb_cs", description="Chip select line in bit-bang mode"),
|
|
])
|
|
self.cfg2 = CSRStorage(fields=[
|
|
CSRField("bb_oe", size=4, description="Output Enable bits in bit-bang mode"),
|
|
])
|
|
self.cfg3 = CSRStorage(fields=[
|
|
CSRField("rlat", size=4, description="Read latency/dummy cycle count"),
|
|
CSRField("crm", description="Continuous Read Mode enable bit"),
|
|
CSRField("qspi", description="Quad-SPI enable bit"),
|
|
CSRField("ddr", description="Double Data Rate enable bit"),
|
|
])
|
|
self.cfg4 = CSRStorage(fields=[
|
|
CSRField("memio", offset=7, reset=1, description="Enable memory-mapped mode (set to 0 to enable bit-bang mode)")
|
|
])
|
|
|
|
self.stat1 = CSRStatus(fields=[
|
|
CSRField("bb_in", size=4, description="Input bits in bit-bang mode"),
|
|
])
|
|
self.stat2 = CSRStatus(1, fields=[], description="Reserved")
|
|
self.stat3 = CSRStatus(1, fields=[], description="Reserved")
|
|
self.stat4 = CSRStatus(1, fields=[], description="Reserved")
|
|
|
|
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")
|