1
0
mirror of synced 2026-01-19 09:08:35 +00:00

switch sdram access from Wishbone to dedicated port, seems to be more reliable

This commit is contained in:
Romain Dolbeau 2021-07-18 05:08:37 -04:00
parent 2f5b4eecfb
commit c5e9a025b4
4 changed files with 116 additions and 87 deletions

View File

@ -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

View File

@ -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

View File

@ -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)
)
)
)

View File

@ -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()