From c5e9a025b4eaf1a5d7ee04f768e0fa06f042d41c Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Sun, 18 Jul 2021 05:08:37 -0400 Subject: [PATCH] switch sdram access from Wishbone to dedicated port, seems to be more reliable --- sbus-to-ztex-gateware-migen/netbsd_csr.h | 2 +- sbus-to-ztex-gateware-migen/prom_csr.fth | 2 +- .../sbus_to_fpga_blk_dma.py | 160 ++++++++++-------- .../sbus_to_fpga_soc.py | 39 +++-- 4 files changed, 116 insertions(+), 87 deletions(-) diff --git a/sbus-to-ztex-gateware-migen/netbsd_csr.h b/sbus-to-ztex-gateware-migen/netbsd_csr.h index f7a1606..96ba456 100644 --- a/sbus-to-ztex-gateware-migen/netbsd_csr.h +++ b/sbus-to-ztex-gateware-migen/netbsd_csr.h @@ -1,5 +1,5 @@ //-------------------------------------------------------------------------------- -// Auto-generated by Migen (3ffd64c) & LiteX (8a644c90) on 2021-07-17 11:01:08 +// Auto-generated by Migen (3ffd64c) & LiteX (8a644c90) on 2021-07-18 04:58:11 //-------------------------------------------------------------------------------- #ifndef __GENERATED_CSR_H #define __GENERATED_CSR_H diff --git a/sbus-to-ztex-gateware-migen/prom_csr.fth b/sbus-to-ztex-gateware-migen/prom_csr.fth index d9d0973..d0b8e76 100644 --- a/sbus-to-ztex-gateware-migen/prom_csr.fth +++ b/sbus-to-ztex-gateware-migen/prom_csr.fth @@ -5,6 +5,6 @@ h# 42000 constant sbusfpga_csraddr_exchange_with_mem h# 43000 constant sbusfpga_csraddr_sdram h# 80000 constant sbusfpga_regionaddr_usb_host_ctrl h# 0 constant sbusfpga_regionaddr_prom -h# fc000000 constant sbusfpga_regionaddr_usb_fake_dma h# 80000000 constant sbusfpga_regionaddr_main_ram +h# fc000000 constant sbusfpga_regionaddr_usb_fake_dma h# 40000 constant sbusfpga_regionaddr_csr diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py index 5695cf6..4b25926 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py @@ -9,22 +9,29 @@ from litex.soc.interconnect import wishbone # width of fromsbus_fifo is 'blk_addr_width' + 'burst_size * 32' (blk_addr + data) # the blk_addr does the round-trip to accompany the data class ExchangeWithMem(Module, AutoCSR): - def __init__(self, soc, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, burst_size = 8): - self.wishbone_r_slave = wishbone.Interface(data_width=soc.bus.data_width) - self.wishbone_w_slave = wishbone.Interface(data_width=soc.bus.data_width) + def __init__(self, soc, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, dram_dma_writer, dram_dma_reader, burst_size = 8): + #self.wishbone_r_slave = wishbone.Interface(data_width=soc.bus.data_width) + #self.wishbone_w_slave = wishbone.Interface(data_width=soc.bus.data_width) self.tosbus_fifo = tosbus_fifo self.fromsbus_fifo = fromsbus_fifo self.fromsbus_req_fifo = fromsbus_req_fifo + self.dram_dma_writer = dram_dma_writer + self.dram_dma_reader = dram_dma_reader data_width = burst_size * 4 data_width_bits = burst_size * 32 blk_addr_width = 32 - log2_int(data_width) # 27 for burst_size == 8 - - self.wishbone_r_master = wishbone.Interface(data_width=data_width_bits) - self.wishbone_w_master = wishbone.Interface(data_width=data_width_bits) - self.submodules += wishbone.Converter(self.wishbone_r_master, self.wishbone_r_slave) - self.submodules += wishbone.Converter(self.wishbone_w_master, self.wishbone_w_slave) + assert(len(self.dram_dma_writer.sink.data == data_width_bits)) + assert(len(self.dram_dma_reader.source.data == data_width_bits)) + assert(len(self.dram_dma_writer.sink.address == blk_addr_width)) + assert(len(self.dram_dma_reader.sink.address == blk_addr_width)) + + #self.wishbone_r_master = wishbone.Interface(data_width=data_width_bits) + #self.wishbone_w_master = wishbone.Interface(data_width=data_width_bits) + + #self.submodules += wishbone.Converter(self.wishbone_r_master, self.wishbone_r_slave) + #self.submodules += wishbone.Converter(self.wishbone_w_master, self.wishbone_w_slave) print("ExchangeWithMem: data_width = {}, data_width_bits = {}, blk_addr_width = {}\n".format(data_width, data_width_bits, blk_addr_width)) print("ExchangeWithMem: tosbus_fifo width = {}, fromsbus_fifo width = {}, fromsbus_req_fifo width = {}\n".format(len(tosbus_fifo.din), len(fromsbus_fifo.dout), len(fromsbus_req_fifo.din))) @@ -49,14 +56,14 @@ class ExchangeWithMem(Module, AutoCSR): self.comb += self.blk_size.status.eq(data_width) self.comb += self.blk_base.status.eq(soc.wb_mem_map["main_ram"] >> log2_int(data_width)) - self.blk_addr = CSRStorage(32, description = "SDRAM Block address to read/write from Wishbone memory (block of size {})".format(data_width)) - self.dma_addr = CSRStorage(32, description = "Host Base address where to write/read data (i.e. SPARC Virtual addr)") - self.blk_cnt = CSRStorage(32, write_from_dev=True, description = "How many blk to read/write (max 2^{}-1); bit 31 is RD".format(max_block_bits), reset = 0) - self.last_blk = CSRStatus(32, description = "Last Blk addr finished on WB side") - self.last_dma = CSRStatus(32, description = "Last DMA addr finished on WB side") - self.blk_rem = CSRStatus(32, description = "How many block remaining; bit 31 is RD", reset = 0) + self.blk_addr = CSRStorage(32, description = "SDRAM Block address to read/write from Wishbone memory (block of size {})".format(data_width)) + self.dma_addr = CSRStorage(32, description = "Host Base address where to write/read data (i.e. SPARC Virtual addr)") + self.blk_cnt = CSRStorage(32, write_from_dev=True, description = "How many blk to read/write (max 2^{}-1); bit 31 is RD".format(max_block_bits), reset = 0) + self.last_blk = CSRStatus(32, description = "Last Blk addr finished on WB side") + self.last_dma = CSRStatus(32, description = "Last DMA addr finished on WB side") + self.blk_rem = CSRStatus(32, description = "How many block remaining; bit 31 is RD", reset = 0) self.dma_status = CSRStatus(32, description = "Status register") - self.wr_tosdram = CSRStatus(32, description = "Last address written to SDRAM") + self.wr_tosdram = CSRStatus(32, description = "Last address written to SDRAM") self.submodules.req_r_fsm = req_r_fsm = FSM(reset_state="Reset") self.submodules.req_w_fsm = req_w_fsm = FSM(reset_state="Reset") @@ -68,17 +75,17 @@ class ExchangeWithMem(Module, AutoCSR): self.comb += self.dma_status.status[8:9].eq(req_w_fsm.ongoing("ReqToMemory")) self.comb += self.dma_status.status[9:10].eq(req_w_fsm.ongoing("WaitForAck")) - self.comb += self.dma_status.status[16:17].eq(self.wishbone_w_master.cyc) # show the WB iface status (W) - self.comb += self.dma_status.status[17:18].eq(self.wishbone_w_master.stb) - self.comb += self.dma_status.status[18:19].eq(self.wishbone_w_master.we) - self.comb += self.dma_status.status[19:20].eq(self.wishbone_w_master.ack) - self.comb += self.dma_status.status[20:21].eq(self.wishbone_w_master.err) + #self.comb += self.dma_status.status[16:17].eq(self.wishbone_w_master.cyc) # show the WB iface status (W) + #self.comb += self.dma_status.status[17:18].eq(self.wishbone_w_master.stb) + #self.comb += self.dma_status.status[18:19].eq(self.wishbone_w_master.we) + #self.comb += self.dma_status.status[19:20].eq(self.wishbone_w_master.ack) + #self.comb += self.dma_status.status[20:21].eq(self.wishbone_w_master.err) - self.comb += self.dma_status.status[24:25].eq(self.wishbone_r_master.cyc) # show the WB iface status (R) - self.comb += self.dma_status.status[25:26].eq(self.wishbone_r_master.stb) - self.comb += self.dma_status.status[26:27].eq(self.wishbone_r_master.we) - self.comb += self.dma_status.status[27:28].eq(self.wishbone_r_master.ack) - self.comb += self.dma_status.status[28:29].eq(self.wishbone_r_master.err) + #self.comb += self.dma_status.status[24:25].eq(self.wishbone_r_master.cyc) # show the WB iface status (R) + #self.comb += self.dma_status.status[25:26].eq(self.wishbone_r_master.stb) + #self.comb += self.dma_status.status[26:27].eq(self.wishbone_r_master.we) + #self.comb += self.dma_status.status[27:28].eq(self.wishbone_r_master.ack) + #self.comb += self.dma_status.status[28:29].eq(self.wishbone_r_master.err) req_r_fsm.act("Reset", NextState("Idle") @@ -99,35 +106,31 @@ class ExchangeWithMem(Module, AutoCSR): ) ) req_r_fsm.act("ReqFromMemory", - If(~self.wishbone_r_master.ack, - NextValue(self.wishbone_r_master.cyc, 1), - NextValue(self.wishbone_r_master.stb, 1), - NextValue(self.wishbone_r_master.sel, 2**len(self.wishbone_r_master.sel)-1), - NextValue(self.wishbone_r_master.we, 0), - NextValue(self.wishbone_r_master.adr, local_r_addr), - NextState("WaitForData") - ) + self.dram_dma_reader.sink.address.eq(local_r_addr), + self.dram_dma_reader.sink.valid.eq(1), + If(self.dram_dma_reader.sink.ready, + NextState("WaitForData") + ) ) req_r_fsm.act("WaitForData", - If(self.wishbone_r_master.ack & - self.tosbus_fifo.writable, - NextValue(self.wishbone_r_master.cyc, 0), - NextValue(self.wishbone_r_master.stb, 0), - tosbus_fifo.we.eq(1), - tosbus_fifo.din.eq(Cat(dma_r_addr, self.wishbone_r_master.dat_r)), - NextValue(self.last_blk.status, local_r_addr), - NextValue(self.last_dma.status, dma_r_addr), - NextValue(self.blk_rem.status, self.blk_rem.status - 1), - If(self.blk_rem.status[0:max_block_bits] <= 1, - self.blk_cnt.we.eq(1), ## auto-reset - self.blk_cnt.dat_w.eq(0), - NextState("Idle"), - ).Else( - NextValue(local_r_addr, local_r_addr + 1), - NextValue(dma_r_addr, dma_r_addr + data_width), - NextState("ReqFromMemory"), - ) - ) + If(self.dram_dma_reader.source.valid & + self.tosbus_fifo.writable, + self.tosbus_fifo.we.eq(1), + self.tosbus_fifo.din.eq(Cat(dma_r_addr, self.dram_dma_reader.source.data)), + self.dram_dma_reader.source.ready.eq(1), + NextValue(self.last_blk.status, local_r_addr), + NextValue(self.last_dma.status, dma_r_addr), + NextValue(self.blk_rem.status, self.blk_rem.status - 1), + If(self.blk_rem.status[0:max_block_bits] <= 1, + self.blk_cnt.we.eq(1), ## auto-reset + self.blk_cnt.dat_w.eq(0), + NextState("Idle"), + ).Else( + NextValue(local_r_addr, local_r_addr + 1), + NextValue(dma_r_addr, dma_r_addr + data_width), + NextState("ReqFromMemory"), + ) + ) ) req_r_fsm.act("QueueReqToMemory", If(self.fromsbus_req_fifo.writable, @@ -150,27 +153,42 @@ class ExchangeWithMem(Module, AutoCSR): ) +# req_w_fsm.act("Reset", +# NextState("Idle") +# ) +# req_w_fsm.act("Idle", +# If(self.fromsbus_fifo.readable & +# ~self.wishbone_w_master.ack, +# self.fromsbus_fifo.re.eq(1), +# NextValue(self.wishbone_w_master.cyc, 1), +# NextValue(self.wishbone_w_master.stb, 1), +# NextValue(self.wishbone_w_master.sel, 2**len(self.wishbone_w_master.sel)-1), +# NextValue(self.wishbone_w_master.we, 1), +# NextValue(self.wishbone_w_master.adr, self.fromsbus_fifo.dout[0:blk_addr_width]), +# NextValue(self.wishbone_w_master.dat_w, self.fromsbus_fifo.dout[blk_addr_width:(blk_addr_width + data_width_bits)]), +# NextValue(self.wr_tosdram.status, self.fromsbus_fifo.dout[0:blk_addr_width]), +# NextState("WaitForAck") +# ) +# ) +# req_w_fsm.act("WaitForAck", +# If(self.wishbone_w_master.ack, +# NextValue(self.wishbone_w_master.cyc, 0), +# NextValue(self.wishbone_w_master.stb, 0), +# NextState("Idle"), +# ) +# ) + req_w_fsm.act("Reset", NextState("Idle") ) req_w_fsm.act("Idle", - If(self.fromsbus_fifo.readable & - ~self.wishbone_w_master.ack, - self.fromsbus_fifo.re.eq(1), - NextValue(self.wishbone_w_master.cyc, 1), - NextValue(self.wishbone_w_master.stb, 1), - NextValue(self.wishbone_w_master.sel, 2**len(self.wishbone_w_master.sel)-1), - NextValue(self.wishbone_w_master.we, 1), - NextValue(self.wishbone_w_master.adr, self.fromsbus_fifo.dout[0:blk_addr_width]), - NextValue(self.wishbone_w_master.dat_w, self.fromsbus_fifo.dout[blk_addr_width:(blk_addr_width + data_width_bits)]), - NextValue(self.wr_tosdram.status, self.fromsbus_fifo.dout[0:blk_addr_width]), - NextState("WaitForAck") - ) - ) - req_w_fsm.act("WaitForAck", - If(self.wishbone_w_master.ack, - NextValue(self.wishbone_w_master.cyc, 0), - NextValue(self.wishbone_w_master.stb, 0), - NextState("Idle"), - ) + If(self.fromsbus_fifo.readable, + self.dram_dma_writer.sink.address.eq(self.fromsbus_fifo.dout[0:blk_addr_width]), + self.dram_dma_writer.sink.data.eq(self.fromsbus_fifo.dout[blk_addr_width:(blk_addr_width + data_width_bits)]), + self.dram_dma_writer.sink.valid.eq(1), + NextValue(self.wr_tosdram.status, self.fromsbus_fifo.dout[0:blk_addr_width]), + If(self.dram_dma_writer.sink.ready, + self.fromsbus_fifo.re.eq(1) + ) + ) ) diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py index d447122..9b243ba 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py @@ -16,8 +16,10 @@ from migen.genlib.fifo import * from litedram.modules import MT41J128M16 from litedram.phy import s7ddrphy -from sbus_to_fpga_fsm import *; -from sbus_to_fpga_blk_dma import *; +from sbus_to_fpga_fsm import * +from sbus_to_fpga_blk_dma import * + +from litedram.frontend.dma import * import sbus_to_fpga_export; @@ -156,6 +158,15 @@ class SBusFPGA(SoCCore): #getattr(self,"prom").mem.init = prom_data #getattr(self,"prom").mem.depth = 2**14 + self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"), + memtype = "DDR3", + nphases = 4, + sys_clk_freq = sys_clk_freq) + self.add_sdram("sdram", + phy = self.ddrphy, + module = MT41J128M16(sys_clk_freq, "1:4"), + l2_cache_size = 0, + ) # don't enable anything on the SBus side for 20 seconds after power up # this avoids FPGA initialization messing with the cold boot process # requires us to reset the SPARCstation afterward so the FPGA board @@ -178,10 +189,20 @@ class SBusFPGA(SoCCore): self.submodules.fromsbus_fifo = ClockDomainsRenamer({"write": "sbus", "read": "sys"})(AsyncFIFOBuffered(width=((30-log2_int(burst_size))+burst_size*32), depth=4)) self.submodules.fromsbus_req_fifo = ClockDomainsRenamer({"read": "sbus", "write": "sys"})(AsyncFIFOBuffered(width=((30-log2_int(burst_size))+32), depth=16)) + self.submodules.dram_dma_writer = LiteDRAMDMAWriter(port=self.sdram.crossbar.get_port(mode="write", data_width=burst_size*32), + fifo_depth=4, + fifo_buffered=True) + + self.submodules.dram_dma_reader = LiteDRAMDMAReader(port=self.sdram.crossbar.get_port(mode="read", data_width=burst_size*32), + fifo_depth=4, + fifo_buffered=True) + self.submodules.exchange_with_mem = ExchangeWithMem(soc=self, tosbus_fifo=self.tosbus_fifo, fromsbus_fifo=self.fromsbus_fifo, fromsbus_req_fifo=self.fromsbus_req_fifo, + dram_dma_writer=self.dram_dma_writer, + dram_dma_reader=self.dram_dma_reader, burst_size=burst_size) _sbus_bus = SBusFPGABus(platform=self.platform, @@ -197,18 +218,8 @@ class SBusFPGA(SoCCore): self.bus.add_master(name="SBusBridgeToWishbone", master=wishbone_master_sys) self.bus.add_slave(name="usb_fake_dma", slave=self.wishbone_slave_sys, region=SoCRegion(origin=self.mem_map.get("usb_fake_dma", None), size=0x03ffffff, cached=False)) - self.bus.add_master(name="mem_read_master", master=self.exchange_with_mem.wishbone_r_slave) - self.bus.add_master(name="mem_write_master", master=self.exchange_with_mem.wishbone_w_slave) - - self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"), - memtype = "DDR3", - nphases = 4, - sys_clk_freq = sys_clk_freq) - self.add_sdram("sdram", - phy = self.ddrphy, - module = MT41J128M16(sys_clk_freq, "1:4"), - l2_cache_size = 0, - ) + #self.bus.add_master(name="mem_read_master", master=self.exchange_with_mem.wishbone_r_slave) + #self.bus.add_master(name="mem_write_master", master=self.exchange_with_mem.wishbone_w_slave) #self.add_sdcard()