diff --git a/nubus-to-ztex-gateware/goblin_accel.py b/nubus-to-ztex-gateware/goblin_accel.py index 6a0d569..5d7fbe6 100644 --- a/nubus-to-ztex-gateware/goblin_accel.py +++ b/nubus-to-ztex-gateware/goblin_accel.py @@ -114,8 +114,8 @@ class GoblinAccel(Module): # AutoCSR ? ) ] - led0 = platform.request("user_led", 0) - self.comb += led0.eq(~local_reset) + #led0 = platform.request("user_led", 0) + #self.comb += led0.eq(~local_reset) self.ibus = ibus = wishbone.Interface() self.dbus = dbus = wishbone.Interface() diff --git a/nubus-to-ztex-gateware/nubus_mem_wb.py b/nubus-to-ztex-gateware/nubus_mem_wb.py index 78ca88e..4f637f7 100644 --- a/nubus-to-ztex-gateware/nubus_mem_wb.py +++ b/nubus-to-ztex-gateware/nubus_mem_wb.py @@ -19,11 +19,28 @@ class NuBus2Wishbone(Module): #nubus.mem_error #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.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 += [ @@ -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 ] + self.comb += If(nubus.mem_write == 0, + wb.sel.eq(0xF)).Else( + wb.sel.eq(nubus.mem_write)) self.comb += [ wb.dat_w.eq(nubus.mem_wdata), 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_error.eq(0) # FIXME: TODO: ??? diff --git a/nubus-to-ztex-gateware/nubus_memfifo_wb.py b/nubus-to-ztex-gateware/nubus_memfifo_wb.py new file mode 100644 index 0000000..7851a69 --- /dev/null +++ b/nubus-to-ztex-gateware/nubus_memfifo_wb.py @@ -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), + ] diff --git a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py index c30190e..9add9ea 100644 --- a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py +++ b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py @@ -35,6 +35,7 @@ import goblin_accel # Wishbone stuff from sbus_wb import WishboneDomainCrossingMaster from nubus_mem_wb import NuBus2Wishbone +from nubus_memfifo_wb import NuBus2WishboneFIFO from nubus_cpu_wb import Wishbone2NuBus # CRG ---------------------------------------------------------------------------------------------- @@ -350,8 +351,10 @@ class NuBusFPGA(SoCCore): self.bus.add_master(name="NuBusBridgeToWishbone", master=wishbone_master_sys) 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) 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")