NuBusFPGA/nubus-to-ztex-gateware/nubus_memfifo_wb.py

115 lines
4.9 KiB
Python

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),
]