buffers (fifo) write from NuBus to Wishbone, to improve write BW

This commit is contained in:
Romain Dolbeau 2022-05-30 13:15:20 +02:00
parent c8e8113c81
commit 3a52ab666f
4 changed files with 151 additions and 7 deletions

View File

@ -114,8 +114,8 @@ class GoblinAccel(Module): # AutoCSR ?
) )
] ]
led0 = platform.request("user_led", 0) #led0 = platform.request("user_led", 0)
self.comb += led0.eq(~local_reset) #self.comb += led0.eq(~local_reset)
self.ibus = ibus = wishbone.Interface() self.ibus = ibus = wishbone.Interface()
self.dbus = dbus = wishbone.Interface() self.dbus = dbus = wishbone.Interface()

View File

@ -19,11 +19,28 @@ class NuBus2Wishbone(Module):
#nubus.mem_error #nubus.mem_error
#nubus.mem_tryagain #nubus.mem_tryagain
assert(len(wb.dat_r) == 32)
assert(len(nubus.mem_wdata) == 32)
assert(len(nubus.mem_write) == 4)
#wb_dat_r_rev = Signal(32)
#self.comb += [ wb_dat_r_rev[ 0: 8].eq(wb.dat_r[24:32]),
# wb_dat_r_rev[ 8:16].eq(wb.dat_r[16:24]),
# wb_dat_r_rev[16:24].eq(wb.dat_r[ 8:16]),
# wb_dat_r_rev[24:32].eq(wb.dat_r[ 0: 8]), ]
#nubus_mem_wdata_rev = Signal(32)
#self.comb += [ nubus_mem_wdata_rev[ 0: 8].eq(nubus.mem_wdata[24:32]),
# nubus_mem_wdata_rev[ 8:16].eq(nubus.mem_wdata[16:24]),
# nubus_mem_wdata_rev[16:24].eq(nubus.mem_wdata[ 8:16]),
# nubus_mem_wdata_rev[24:32].eq(nubus.mem_wdata[ 0: 8]), ]
#nubus_mem_write_rev = Signal(4)
#self.comb += [ nubus_mem_write_rev[0].eq(nubus.mem_write[3]),
# nubus_mem_write_rev[1].eq(nubus.mem_write[2]),
# nubus_mem_write_rev[2].eq(nubus.mem_write[1]),
# nubus_mem_write_rev[3].eq(nubus.mem_write[0]), ]
self.comb += wb.cyc.eq(nubus.mem_valid) self.comb += wb.cyc.eq(nubus.mem_valid)
self.comb += wb.stb.eq(nubus.mem_valid) self.comb += wb.stb.eq(nubus.mem_valid)
self.comb += If(nubus.mem_write == 0,
wb.sel.eq(0xF)).Else(
wb.sel.eq(nubus.mem_write))
self.comb += wb.we.eq(nubus.mem_write != 0) self.comb += wb.we.eq(nubus.mem_write != 0)
self.comb += [ self.comb += [
@ -33,10 +50,20 @@ class NuBus2Wishbone(Module):
wb.adr.eq(Cat(nubus.mem_addr[2:24], Signal(8, reset = 0xf0)))), # 24 bits, a.k.a 22 bits of words wb.adr.eq(Cat(nubus.mem_addr[2:24], Signal(8, reset = 0xf0)))), # 24 bits, a.k.a 22 bits of words
] ]
self.comb += If(nubus.mem_write == 0,
wb.sel.eq(0xF)).Else(
wb.sel.eq(nubus.mem_write))
self.comb += [ self.comb += [
wb.dat_w.eq(nubus.mem_wdata), wb.dat_w.eq(nubus.mem_wdata),
nubus.mem_rdata.eq(wb.dat_r), nubus.mem_rdata.eq(wb.dat_r),
] ]
#self.comb += If(nubus.mem_write == 0,
# wb.sel.eq(0xF)).Else(
# wb.sel.eq(nubus_mem_write_rev))
#self.comb += [
# wb.dat_w.eq(nubus_mem_wdata_rev),
# nubus.mem_rdata.eq(wb_dat_r_rev),
#]
self.comb += nubus.mem_ready.eq(wb.ack) self.comb += nubus.mem_ready.eq(wb.ack)
self.comb += nubus.mem_error.eq(0) # FIXME: TODO: ??? self.comb += nubus.mem_error.eq(0) # FIXME: TODO: ???

View File

@ -0,0 +1,114 @@
from migen import *
from migen.genlib.fifo import *
import litex
from litex.soc.interconnect import wishbone
from migen.genlib.cdc import BusSynchronizer
class NuBus2WishboneFIFO(Module):
def __init__(self, platform, nubus, wb_read, wb_write):
# memory
# nubus.mem_valid
# nubus.mem_addr
# nubus.mem_wdata
# nubus.mem_write
# nubus.mem_ready
# nubus.mem_rdata
#nubus.mem_error
#nubus.mem_tryagain
assert(len(wb_read.dat_r) == 32)
assert(len(nubus.mem_wdata) == 32)
assert(len(nubus.mem_write) == 4)
write_fifo_layout = [
("adr", 32),
("data", 32),
("sel", 4),
]
self.submodules.write_fifo = write_fifo = ClockDomainsRenamer({"read": "sys", "write": "nubus"})(AsyncFIFOBuffered(width=layout_len(write_fifo_layout), depth=8))
write_fifo_dout = Record(write_fifo_layout)
self.comb += write_fifo_dout.raw_bits().eq(write_fifo.dout)
write_fifo_din = Record(write_fifo_layout)
self.comb += write_fifo.din.eq(write_fifo_din.raw_bits())
self.comb += wb_read.cyc.eq(nubus.mem_valid & (nubus.mem_write == 0)) # only handle reads
self.comb += wb_read.stb.eq(nubus.mem_valid & (nubus.mem_write == 0)) # only handle reads
self.comb += wb_read.we.eq(0) #(nubus.mem_write != 0)
self.comb += [
If(~nubus.mem_addr[23], # first 8 MiB of slot space: remap to last 8 Mib of SDRAM
wb_read.adr.eq(Cat(nubus.mem_addr[2:23], Signal(1, reset=1), Signal(8, reset = 0x8f))), # 0x8f8...
).Else( # second 8 MiB: direct access
wb_read.adr.eq(Cat(nubus.mem_addr[2:24], Signal(8, reset = 0xf0)))), # 24 bits, a.k.a 22 bits of words
]
#self.comb += If(nubus.mem_write == 0,
# wb_read.sel.eq(0xF)).Else(
# wb_read.sel.eq(nubus.mem_write))
self.comb += [
#wb_read.dat_w.eq(nubus.mem_wdata),
wb_read.sel.eq(0xF),
nubus.mem_rdata.eq(wb_read.dat_r),
]
write_ack = Signal()
self.comb += nubus.mem_ready.eq(wb_read.ack | write_ack)
self.comb += nubus.mem_error.eq(0) # FIXME: TODO: ???
self.comb += nubus.mem_tryagain.eq(0) # FIXME: TODO: ???
led0 = platform.request("user_led", 0)
led1 = platform.request("user_led", 1)
self.comb += [ led0.eq(wb_read.ack),
led1.eq(write_ack), ]
#self.submodules.write_fsm = write_fsm = FSM(reset_state = "Reset")
#write_fsm.act("Reset",
# NextState("Idle"))
#write_fsm.act("Idle",)
# in NuBus
#self.comb += [ write_fifo.we.eq(write_fifo.writable & nubus.mem_valid & (nubus.mem_write != 0)),
# write_ack.eq(write_fifo.writable & nubus.mem_valid & (nubus.mem_write != 0))
#]
#self.comb += [ write_fifo_din.adr.eq(nubus.mem_addr),
# write_fifo_din.data.eq(nubus.mem_wdata),
# write_fifo_din.sel.eq(nubus.mem_write),
#]
self.submodules.write_fsm = write_fsm = ClockDomainsRenamer("nubus")(FSM(reset_state = "Reset"))
write_fsm.act("Reset",
NextState("Idle"))
write_fsm.act("Idle",
If(nubus.mem_valid & (nubus.mem_write != 0), # & write_fifo.writable),
NextState("WriteFifo"),
)
)
write_fsm.act("WriteFifo",
write_fifo.we.eq(1),
write_ack.eq(1), # the one cycle delay is needed for the tmO -> nubus.mem_write -> ack dependency chain
NextState("WaitForNuBus"),
)
write_fsm.act("WaitForNuBus",
If(~nubus.mem_valid,
NextState("Idle"),
)
)
self.comb += [ write_fifo_din.adr.eq(nubus.mem_addr),
write_fifo_din.data.eq(nubus.mem_wdata),
write_fifo_din.sel.eq(nubus.mem_write),
]
self.comb += [ wb_write.cyc.eq(write_fifo.readable),
wb_write.stb.eq(write_fifo.readable),
wb_write.we.eq(1),
If(~write_fifo_dout.adr[23], # first 8 MiB of slot space: remap to last 8 Mib of SDRAM
wb_write.adr.eq(Cat(write_fifo_dout.adr[2:23], Signal(1, reset=1), Signal(8, reset = 0x8f))), # 0x8f8...
).Else( # second 8 MiB: direct access
wb_write.adr.eq(Cat(write_fifo_dout.adr[2:24], Signal(8, reset = 0xf0)))), # 24 bits, a.k.a 22 bits of words
wb_write.dat_w.eq(write_fifo_dout.data),
wb_write.sel.eq(write_fifo_dout.sel),
write_fifo.re.eq(wb_write.ack),
]

View File

@ -35,6 +35,7 @@ import goblin_accel
# Wishbone stuff # Wishbone stuff
from sbus_wb import WishboneDomainCrossingMaster from sbus_wb import WishboneDomainCrossingMaster
from nubus_mem_wb import NuBus2Wishbone from nubus_mem_wb import NuBus2Wishbone
from nubus_memfifo_wb import NuBus2WishboneFIFO
from nubus_cpu_wb import Wishbone2NuBus from nubus_cpu_wb import Wishbone2NuBus
# CRG ---------------------------------------------------------------------------------------------- # CRG ----------------------------------------------------------------------------------------------
@ -350,8 +351,10 @@ class NuBusFPGA(SoCCore):
self.bus.add_master(name="NuBusBridgeToWishbone", master=wishbone_master_sys) self.bus.add_master(name="NuBusBridgeToWishbone", master=wishbone_master_sys)
self.submodules.nubus = nubus.NuBus(platform=platform, cd_nubus="nubus") self.submodules.nubus = nubus.NuBus(platform=platform, cd_nubus="nubus")
self.submodules.nubus2wishbone = ClockDomainsRenamer("nubus")(NuBus2Wishbone(nubus=self.nubus,wb=self.wishbone_master_nubus)) #self.submodules.nubus2wishbone = ClockDomainsRenamer("nubus")(NuBus2Wishbone(nubus=self.nubus,wb=self.wishbone_master_nubus))
nubus_writemaster_sys = wishbone.Interface(data_width=self.bus.data_width)
self.submodules.nubus2wishbone = NuBus2WishboneFIFO(platform=self.platform,nubus=self.nubus,wb_read=self.wishbone_master_nubus,wb_write=nubus_writemaster_sys)
self.bus.add_master(name="NuBusBridgeToWishboneWrite", master=nubus_writemaster_sys)
wishbone_slave_nubus = wishbone.Interface(data_width=self.bus.data_width) wishbone_slave_nubus = wishbone.Interface(data_width=self.bus.data_width)
self.submodules.wishbone2nubus = ClockDomainsRenamer("nubus")(Wishbone2NuBus(nubus=self.nubus,wb=wishbone_slave_nubus)) self.submodules.wishbone2nubus = ClockDomainsRenamer("nubus")(Wishbone2NuBus(nubus=self.nubus,wb=wishbone_slave_nubus))
self.submodules.wishbone_slave_sys = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_slave_nubus, cd_master="sys", cd_slave="nubus") self.submodules.wishbone_slave_sys = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_slave_nubus, cd_master="sys", cd_slave="nubus")