switch sdram access from Wishbone to dedicated port, seems to be more reliable
This commit is contained in:
parent
2f5b4eecfb
commit
c5e9a025b4
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user