diff --git a/nubus-to-ztex-gateware/nubus_full.py b/nubus-to-ztex-gateware/nubus_full.py deleted file mode 100644 index 42acbe0..0000000 --- a/nubus-to-ztex-gateware/nubus_full.py +++ /dev/null @@ -1,599 +0,0 @@ -from migen import * -from migen.genlib.fifo import * -from migen.genlib.cdc import * -from migen.fhdl.specials import Tristate - -import litex -from litex.soc.interconnect import wishbone - -class NuBus(Module): - def __init__(self, soc, - burst_size, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, - wb_read, wb_write, wb_dma, - cd_nubus="nubus", cd_nubus90="nubus90"): - - platform = soc.platform - self.add_sources(platform) - - #led0 = platform.request("user_led", 0) - #led1 = platform.request("user_led", 1) - - # Signals for tri-stated nubus access - # slave - tmo_oe = Signal() # output enable - tm0_i_n = Signal() - tm0_o_n = Signal(reset = 1) - tm1_i_n = Signal() - tm1_o_n = Signal(reset = 1) - ack_i_n = Signal() - ack_o_n = Signal(reset = 1) - - ad_oe = Signal() - ad_i_n = Signal(32) - ad_o_n = Signal(32) - - id_i_n = Signal(4) - - start_i_n = Signal() - start_o_n = Signal(reset = 1) # master via master_oe - - # master - rqst_oe = Signal() - rqst_i_n = Signal() - rqst_o_n = Signal(reset = 1) - - # sampled signals, exposing the value of the register acquired on the falling edge - # they can change every cycle *on falling edge* - # slave - sampled_tm0 = Signal() # high is byte (which byte is in ad0/ad1); low is halfword/word/block depending on ad0/ad1 - sampled_tm1 = Signal() # high is write - sampled_start = Signal() - sampled_ack = Signal() - sampled_ad = Signal(32) - sampled_ad_byterev = Signal(32) - - # master - sampled_rqst = Signal() - - # address rewriting - # can change every cycle *on falling edge* - processed_ad = Signal(32) - processed_super_ad = Signal(32) - self.comb += [ - processed_ad[0:23].eq(sampled_ad[0:23]), - If(~sampled_ad[23], # first 8 MiB of slot space: remap to last 8 Mib of SDRAM - processed_ad[23:32].eq(Cat(Signal(1, reset=1), Signal(8, reset = 0x8f))), # 0x8f8... - ).Else( # second 8 MiB: direct access - processed_ad[23:32].eq(Cat(sampled_ad[23], Signal(8, reset = 0xf0)))), # 24 bits, a.k.a 22 bits of words - processed_super_ad[0:28].eq(sampled_ad[0:28]), - processed_super_ad[28:32].eq(Signal(4, reset = 0x8)), - sampled_ad_byterev[ 0: 8].eq(sampled_ad[24:32]), - sampled_ad_byterev[ 8:16].eq(sampled_ad[16:24]), - sampled_ad_byterev[16:24].eq(sampled_ad[ 8:16]), - sampled_ad_byterev[24:32].eq(sampled_ad[ 0: 8]), - ] - - # decoded signals, exposing decoded results from the sampled signals - # they can change every cycle *on falling edge* - # from sampling (fixme?) - decoded_sel = Signal(4) - decoded_block = Signal() - decoded_busy = Signal() - # locally evaluated - decoded_myslot = Signal() - decoded_mysuperslot = Signal() - self.comb += [ - decoded_myslot.eq( - (sampled_ad[28:32] == 0xF) & - (sampled_ad[27] == ~id_i_n[3]) & - (sampled_ad[26] == ~id_i_n[2]) & - (sampled_ad[25] == ~id_i_n[1]) & - (sampled_ad[24] == ~id_i_n[0])), - decoded_mysuperslot.eq( - (sampled_ad[31] == ~id_i_n[3]) & - (sampled_ad[30] == ~id_i_n[2]) & - (sampled_ad[29] == ~id_i_n[1]) & - (sampled_ad[28] == ~id_i_n[0])), - #led0.eq(decoded_block), - ] - - # current value, registered from the sampled/processed/decoded signals - # change is controlled by the FSM - current_adr = Signal(32) - current_tm0 = Signal() - current_tm1 = Signal() - current_sel = Signal(4) - current_block = Signal() - current_data = Signal(32) - - # write FIFO to speed up bus turnaround on NuBus side - 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=16)) - 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.specials += Instance("nubus_sampling", - i_nub_clkn = ClockSignal(cd_nubus), - i_nub_resetn = ~ResetSignal(cd_nubus), - i_nub_tm0n = tm0_i_n, - i_nub_tm1n = tm1_i_n, - i_nub_startn = start_i_n, - i_nub_rqstn = rqst_i_n, - i_nub_ackn = ack_i_n, - i_nub_adn = ad_i_n, - - o_tm0 = sampled_tm0, - o_tm1 = sampled_tm1, - o_start = sampled_start, - o_rqst = sampled_rqst, - o_ack = sampled_ack, - o_ad = sampled_ad, - - o_sel = decoded_sel, - o_block = decoded_block, - o_busy = decoded_busy, - ) - - self.read_ctr = read_ctr = Signal(32) - self.writ_ctr = writ_ctr = Signal(32) - - self.submodules.slave_fsm = slave_fsm = ClockDomainsRenamer(cd_nubus)(FSM(reset_state="Reset")) - slave_fsm.act("Reset", - NextState("Idle") - ) - slave_fsm.act("Idle", - If((decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & ~sampled_tm1,# & ~decoded_block, # regular read (we always send back 32 bits, so don't worry about byte/word) - If(decoded_myslot, - NextValue(current_adr, processed_ad), - ).Else( # decoded_mysuperslot, - NextValue(current_adr, processed_super_ad), - ), - #NextValue(current_tm0, sampled_tm0), - #NextValue(current_tm1, sampled_tm1), - #NextValue(current_sel, decoded_sel), - #NextValue(current_block, decoded_block), - #If(decoded_block, - # NextValue(decoded_block_memory, 1),), - NextValue(read_ctr, read_ctr + 1), - NextState("WaitWBRead"), - ).Elif((decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & sampled_tm1,# & ~decoded_block, # regular write - If(decoded_myslot, - NextValue(current_adr, processed_ad), - ).Else( # decoded_mysuperslot, - NextValue(current_adr, processed_super_ad), - ), - #NextValue(current_tm0, sampled_tm0), - #NextValue(current_tm1, sampled_tm1), - NextValue(current_sel, decoded_sel), - #NextValue(current_block, decoded_block), - #If(decoded_block, - # NextValue(decoded_block_memory, 1),), - #NextState("GetNubusWriteData"), - NextValue(writ_ctr, writ_ctr + 1), - NextState("NubusWriteDataToFIFO"), - ) - ) - slave_fsm.act("WaitWBRead", - wb_read.cyc.eq(1), - wb_read.stb.eq(1), - wb_read.we.eq(0), - wb_read.sel.eq(0xf), - wb_read.adr.eq(current_adr[2:32]), - tmo_oe.eq(1), - tm0_o_n.eq(1), - tm1_o_n.eq(1), - ack_o_n.eq(1), - If(wb_read.ack, - ad_oe.eq(1), - ad_o_n.eq(~wb_read.dat_r), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - NextState("Idle"), - ) - ) - slave_fsm.act("NubusWriteDataToFIFO", - tmo_oe.eq(1), - tm0_o_n.eq(1), - tm1_o_n.eq(1), - ack_o_n.eq(1), - If(write_fifo.writable, - write_fifo.we.eq(1), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - NextState("Idle"), - ) - ) - - # connect the write FIFO inputs - self.comb += [ write_fifo_din.adr.eq(current_adr), # recorded - write_fifo_din.data.eq(sampled_ad), # we do it live - write_fifo_din.sel.eq(current_sel), # recorded - ] - # deal with emptying the Write FIFO to the write WB - self.comb += [ wb_write.cyc.eq(write_fifo.readable), - wb_write.stb.eq(write_fifo.readable), - wb_write.we.eq(1), - wb_write.adr.eq(write_fifo_dout.adr[2:32]), - wb_write.dat_w.eq(write_fifo_dout.data), - wb_write.sel.eq(write_fifo_dout.sel), - write_fifo.re.eq(wb_write.ack), - ] - - owning_bus = Signal(reset = 0) # fixme ; theoretically one can bypass arbitration when owning the bus - - start_arbitration = Signal() - grant = Signal() - master_oe = Signal() - - nubus_sync = getattr(self.sync, cd_nubus) - nubus_sync += [ - If(sampled_rqst & ~start_arbitration, - owning_bus.eq(0), - ) - ] - - self.submodules.dma_fsm = dma_fsm = ClockDomainsRenamer(cd_nubus)(FSM(reset_state="Reset")) - ctr = Signal(log2_int(burst_size)) # burst counter - burst = Signal() - burst_we = Signal() - - data_width = burst_size * 4 - data_width_bits = burst_size * 32 - blk_addr_width = 32 - log2_int(data_width) # 27 for burst_size == 8, 28 for burst_size == 4 - fifo_addr = Signal(blk_addr_width) - fifo_blk_addr = Signal(blk_addr_width) - fifo_buffer = Signal(data_width_bits) - - tosbus_fifo_dout = Record(soc.tosbus_layout) - self.comb += tosbus_fifo_dout.raw_bits().eq(tosbus_fifo.dout) - tosbus_fifo_dout_data_byterev = Signal(data_width_bits) - tosbus_fifo_dout_bytereversal_stmts = [ tosbus_fifo_dout_data_byterev[k*32+j*8:k*32+j*8+8].eq(tosbus_fifo_dout.data[k*32+32-j*8-8:k*32+32-j*8]) for k in range(burst_size) for j in range(4) ] - self.comb += tosbus_fifo_dout_bytereversal_stmts - - fromsbus_req_fifo_dout = Record(soc.fromsbus_req_layout) - self.comb += fromsbus_req_fifo_dout.raw_bits().eq(fromsbus_req_fifo.dout) - - fromsbus_fifo_din = Record(soc.fromsbus_layout) - self.comb += fromsbus_fifo.din.eq(fromsbus_fifo_din.raw_bits()) - - #self.comb += led0.eq(~dma_fsm.ongoing("Idle")) - #self.comb += led1.eq(burst) - - dma_fsm.act("Reset", - NextState("Idle") - ) - dma_fsm.act("Idle", - If(wb_dma.cyc & wb_dma.stb & ~sampled_rqst, # we need the bus and it's not being requested - NextValue(burst, 0), - If(owning_bus, # we own the bus, skip arbitration - NextState("AdrCycle"), - ).Else( # go for arbitration - NextState("Arbitration"), - ), - ).Elif(tosbus_fifo.readable & ~sampled_rqst, - NextValue(burst, 1), - NextValue(burst_we, 1), - NextValue(fifo_addr, tosbus_fifo_dout.address[(32-blk_addr_width):32]), - If(owning_bus, # we own the bus, skip arbitration - NextState("Burst4AdrCycle"), - ).Else( # go for arbitration - NextState("Arbitration"), - ) - ).Elif(fromsbus_req_fifo.readable & fromsbus_fifo.writable & ~sampled_rqst, - NextValue(burst, 1), - NextValue(burst_we, 0), - NextValue(fifo_addr, fromsbus_req_fifo_dout.dmaaddress[(32-blk_addr_width):32]), - NextValue(fifo_blk_addr, fromsbus_req_fifo_dout.blkaddress), - If(owning_bus, # we own the bus, skip arbitration - NextState("Burst4AdrCycle"), - ).Else( # go for arbitration - NextState("Arbitration"), - ) - ) - ) - dma_fsm.act("Arbitration", - start_arbitration.eq(1), - rqst_oe.eq(1), - rqst_o_n.eq(0), - NextState("WaitForGrant"), - ) - dma_fsm.act("WaitForGrant", - start_arbitration.eq(1), - rqst_oe.eq(1), - rqst_o_n.eq(0), - If(grant & ~decoded_busy, # I'm now 'owner' - NextValue(owning_bus, 1), - If(burst, - NextState("Burst4AdrCycle"), - ).Else( - NextState("AdrCycle"), - ), - ) - ) - dma_fsm.act("AdrCycle", - start_arbitration.eq(0), - master_oe.eq(1), # for start - tmo_oe.eq(1), # for tm0, tm1, ack - ad_oe.eq(1), # for write address - start_o_n.eq(0), - tm0_o_n.eq(~((wb_dma.sel == 0x1) | (wb_dma.sel == 0x2) | (wb_dma.sel == 0x4) | (wb_dma.sel == 0x8))), # byte only - tm1_o_n.eq(~wb_dma.we), - ad_o_n[0].eq(~((wb_dma.sel == 0x2) | (wb_dma.sel == 0x3) | (wb_dma.sel == 0x8) | (wb_dma.sel == 0xc))), # odd bytes, both half-words - ad_o_n[1].eq(~((wb_dma.sel == 0x4) | (wb_dma.sel == 0x8) | (wb_dma.sel == 0xc))), # upper bytes and half-word - ad_o_n[2:32].eq(~wb_dma.adr), - ack_o_n.eq(1), - If(wb_dma.we, - NextState("DatCycle"), - ).Else( - NextState("ReadWaitForAck"), - ) - ) - dma_fsm.act("DatCycle", - master_oe.eq(1), # for start - ad_oe.eq(1), # for write data - start_o_n.eq(1), # start finished, but still need to be driven - ad_o_n.eq(~wb_dma.dat_w), - If(sampled_ack, - wb_dma.ack.eq(1), - # fixme: check status ??? (tm0 and tm1 should be active for no-error) - NextState("FinishCycle"), - ) - ) - dma_fsm.act("FinishCycle", - NextValue(burst, 0), - master_oe.eq(1), # for start - start_o_n.eq(1), # start finished, but still need to be driven - tmo_oe.eq(1), # for tm0, tm1, ack, need to be driven to inactive - tm0_o_n.eq(1), - tm1_o_n.eq(1), - ack_o_n.eq(1), - NextState("Idle"), - ) - dma_fsm.act("ReadWaitForAck", - master_oe.eq(1), # for start - start_o_n.eq(1), # start finished, but still need to be driven - wb_dma.dat_r.eq(sampled_ad), - If(sampled_ack, - wb_dma.ack.eq(1), - # fixme: check status ??? (tm0 and tm1 should be active for no-error) - NextState("FinishCycle"), - ) - ) - - if (burst_size == 4): - handle_ad_for_burst = [ - ad_o_n[0].eq(1), # burst - ad_o_n[1].eq(0), # burst - ad_o_n[2].eq(0), # burst == 4 - ad_o_n[3].eq(1), # burst == 4 - ad_o_n[4:32].eq(~fifo_addr), # adr - ] - elif (burst_size == 8): - handle_ad_for_burst = [ - ad_o_n[0].eq(1), # burst - ad_o_n[1].eq(0), # burst - ad_o_n[2].eq(0), # burst == 8 - ad_o_n[3].eq(0), # burst == 8 - ad_o_n[4].eq(1), # burst == 8 - ad_o_n[5:32].eq(~fifo_addr), # adr - ] - else: - raise ValueError(f"Unsupported burst_size {burst_size}") - - dma_fsm.act("Burst4AdrCycle", - start_arbitration.eq(0), - master_oe.eq(1), # for start - tmo_oe.eq(1), # for tm0, tm1, ack - ad_oe.eq(1), # for write address - start_o_n.eq(0), - tm0_o_n.eq(1), # burst - tm1_o_n.eq(~burst_we), - *handle_ad_for_burst, - ack_o_n.eq(1), - NextValue(ctr, 0), - If(burst_we, - NextState("Burst4DatCycleTM0"), - ).Else( - NextState("Burst4ReadWaitForTM0"), - ) - ) - - if (burst_size == 4): - handle_buffer_read_for_burst = [ - Case(ctr, { - 0x0: NextValue(fifo_buffer[ 0: 32], sampled_ad), - 0x1: NextValue(fifo_buffer[32: 64], sampled_ad), - 0x2: NextValue(fifo_buffer[64: 96], sampled_ad), - #0x3: NextValue(fifo_buffer[96:128], sampled_ad), - #0x0: NextValue(fifo_buffer[ 0: 32], sampled_ad_byterev), - #0x1: NextValue(fifo_buffer[32: 64], sampled_ad_byterev), - #0x2: NextValue(fifo_buffer[64: 96], sampled_ad_byterev), - ##0x3: NextValue(fifo_buffer[96:128], sampled_ad_byterev), - }), - ] - handle_final_buffer_read_for_burst = [ - fromsbus_fifo_din.data.eq(Cat(fifo_buffer[0:96], sampled_ad)), # we use sampled_ad directly for 96:128 - ] - elif (burst_size == 8): - handle_buffer_read_for_burst = [ - Case(ctr, { - 0x0: NextValue(fifo_buffer[ 0: 32], sampled_ad), - 0x1: NextValue(fifo_buffer[ 32: 64], sampled_ad), - 0x2: NextValue(fifo_buffer[ 64: 96], sampled_ad), - 0x3: NextValue(fifo_buffer[ 96:128], sampled_ad), - 0x4: NextValue(fifo_buffer[128:160], sampled_ad), - 0x5: NextValue(fifo_buffer[160:192], sampled_ad), - 0x6: NextValue(fifo_buffer[192:224], sampled_ad), - #0x7: NextValue(fifo_buffer[224:256], sampled_ad), - }), - ] - handle_final_buffer_read_for_burst = [ - fromsbus_fifo_din.data.eq(Cat(fifo_buffer[0:224], sampled_ad)), # we use sampled_ad directly for 224:256 - ] - else: - raise ValueError(f"Unsupported burst_size {burst_size}") - - dma_fsm.act("Burst4ReadWaitForTM0", - master_oe.eq(1), # for start - start_o_n.eq(1), # start finished, but still need to be driven - If(sampled_ack, # oups - fromsbus_req_fifo.re.eq(1), # remove request to avoid infinite repeat - #NextValue(led0, 1), - #NextValue(led1, 1), - NextState("FinishCycle"), - ).Elif(sampled_tm0, - *handle_buffer_read_for_burst, - NextValue(ctr, ctr + 1), - If(ctr == (burst_size - 2), # burst next-to-last - NextState("Burst4ReadWaitForAck"), - ).Else( - NextState("Burst4ReadWaitForTM0"), - ) - ) - ) - dma_fsm.act("Burst4ReadWaitForAck", - master_oe.eq(1), # for start - start_o_n.eq(1), # start finished, but still need to be driven - If(sampled_ack, - fromsbus_req_fifo.re.eq(1), # remove request - fromsbus_fifo.we.eq(1), - fromsbus_fifo_din.blkaddress.eq(fifo_blk_addr), - *handle_final_buffer_read_for_burst, - # fixme: check status ??? (tm0 and tm1 should be active for no-error) - #NextValue(led0, (~sampled_tm0 | ~sampled_tm1)), - NextState("FinishCycle"), - ) - ) - - - if (burst_size == 4): - handle_buffer_write_for_burst = [ - Case(ctr, { - 0x0: ad_o_n.eq(~tosbus_fifo_dout.data[ 0: 32]), - 0x1: ad_o_n.eq(~tosbus_fifo_dout.data[32: 64]), - 0x2: ad_o_n.eq(~tosbus_fifo_dout.data[64: 96]), - ##0x3: ad_o_n.eq(~tosbus_fifo_dout.data[96:128]), - #0x0: ad_o_n.eq(~tosbus_fifo_dout_data_byterev[ 0: 32]), - #0x1: ad_o_n.eq(~tosbus_fifo_dout_data_byterev[32: 64]), - #0x2: ad_o_n.eq(~tosbus_fifo_dout_data_byterev[64: 96]), - ##0x3: ad_o_n.eq(~tosbus_fifo_dout_data_byterev[96:128]), - }), - ] - handle_last_buffer_write_for_burst = [ - ad_o_n.eq(~tosbus_fifo_dout.data[96:128]), # last word - ] - elif (burst_size == 8): - handle_buffer_write_for_burst = [ - Case(ctr, { - 0x0: ad_o_n.eq(~tosbus_fifo_dout.data[ 0: 32]), - 0x1: ad_o_n.eq(~tosbus_fifo_dout.data[ 32: 64]), - 0x2: ad_o_n.eq(~tosbus_fifo_dout.data[ 64: 96]), - 0x3: ad_o_n.eq(~tosbus_fifo_dout.data[ 96:128]), - 0x4: ad_o_n.eq(~tosbus_fifo_dout.data[128:160]), - 0x5: ad_o_n.eq(~tosbus_fifo_dout.data[160:192]), - 0x6: ad_o_n.eq(~tosbus_fifo_dout.data[192:224]), - #0x7: ad_o_n.eq(~tosbus_fifo_dout.data[224:256]), - }), - ] - handle_last_buffer_write_for_burst = [ - ad_o_n.eq(~tosbus_fifo_dout.data[224:256]), # last word - ] - else: - raise ValueError(f"Unsupported burst_size {burst_size}") - - dma_fsm.act("Burst4DatCycleTM0", - master_oe.eq(1), # for start - ad_oe.eq(1), # for write data - start_o_n.eq(1), # start finished, but still need to be driven - *handle_buffer_write_for_burst, - If(sampled_ack, # oups - #NextValue(led0, 1), - #NextValue(led1, 1), - tosbus_fifo.re.eq(1), # remove FIFO entry to avoid infinite repeat - NextState("FinishCycle"), - ).Elif(sampled_tm0, - NextValue(ctr, ctr + 1), - If(ctr == (burst_size - 2), # burst next-to-last - NextState("Burst4DatCycleAck"), - ).Else( - NextState("Burst4DatCycleTM0"), - ) - ) - ) - dma_fsm.act("Burst4DatCycleAck", - master_oe.eq(1), # for start - ad_oe.eq(1), # for write data - start_o_n.eq(1), # start finished, but still need to be driven - *handle_last_buffer_write_for_burst, - If(sampled_ack, - tosbus_fifo.re.eq(1), # remove FIFO entry at last - # fixme: check status ??? (tm0 and tm1 should be active for no-error) - #NextValue(led0, (~sampled_tm0 | ~sampled_tm1)), - NextState("FinishCycle"), - ) - ) - - # stuff at this end so we don't use the signals inadvertantly - - # real NuBus signals - nub_tm0n = platform.request("tm0_3v3_n") - nub_tm1n = platform.request("tm1_3v3_n") - nub_startn = platform.request("start_3v3_n") - nub_ackn = platform.request("ack_3v3_n") - nub_adn = platform.request("ad_3v3_n") - nub_idn = platform.request("id_3v3_n") - - # Tri-state - self.specials += Tristate(nub_tm0n, tm0_o_n, tmo_oe, tm0_i_n) - self.specials += Tristate(nub_tm1n, tm1_o_n, tmo_oe, tm1_i_n) - self.specials += Tristate(nub_ackn, ack_o_n, tmo_oe, ack_i_n) - self.specials += Tristate(nub_adn, ad_o_n, ad_oe, ad_i_n) - self.specials += Tristate(nub_startn, start_o_n, master_oe, start_i_n) - self.comb += [ - id_i_n.eq(nub_idn), - ] - - # NubusFPGA-only signals - nf_tmoen = platform.request("tmoen") - nf_nubus_ad_dir = platform.request("nubus_ad_dir") - - self.comb += [ - nf_tmoen.eq(~tmo_oe), - nf_nubus_ad_dir.eq(~ad_oe), - ] - - # real Nubus signal, for master - nub_rqstn = platform.request("rqst_3v3_n") - - # Tri-state - self.specials += Tristate(nub_rqstn, rqst_o_n, rqst_oe, rqst_i_n) - - # NubusFPGA-only signals, for master - nub_arbcy_n = platform.request("arbcy_n") - nf_grant = platform.request("grant") - nf_nubus_master_dir = platform.request("nubus_master_dir") - nf_fpga_to_cpld_signal = platform.request("fpga_to_cpld_signal") - - # NuBus90 signals, , for completeness - nub_clk2xn = ClockSignal(cd_nubus90) - nub_tm2n = platform.request("tm2_3v3_n") - - self.comb += [ - nf_nubus_master_dir.eq(master_oe), - nub_arbcy_n.eq(~start_arbitration), - grant.eq(nf_grant), - nf_fpga_to_cpld_signal.eq(~rqst_oe), - ] - - - def add_sources(self, platform): - # sampling of data on falling edge of clock, done in verilog - platform.add_source("nubus_sampling.v", "verilog") diff --git a/nubus-to-ztex-gateware/nubus_full_sampling.py b/nubus-to-ztex-gateware/nubus_full_unified.py similarity index 61% rename from nubus-to-ztex-gateware/nubus_full_sampling.py rename to nubus-to-ztex-gateware/nubus_full_unified.py index 2337e63..bf88308 100644 --- a/nubus-to-ztex-gateware/nubus_full_sampling.py +++ b/nubus-to-ztex-gateware/nubus_full_unified.py @@ -10,6 +10,7 @@ class NuBus(Module): def __init__(self, soc, burst_size, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, wb_read, wb_write, wb_dma, + usesampling=False, cd_nubus="nubus", cd_nubus90="nubus90"): platform = soc.platform @@ -18,24 +19,31 @@ class NuBus(Module): #led0 = platform.request("user_led", 0) #led1 = platform.request("user_led", 1) - nub_clk = ClockSignal(cd_nubus) - nub_resetn = ~ResetSignal(cd_nubus) - nub_clk_prev_bits = 4 # how many cycles after posedge do we still dare set some signals (i.e. still before setup time before negedge) - nub_clk_prev = Signal(nub_clk_prev_bits) - nub_clk_negedge = Signal() - nub_clk_posedge = Signal() - nub_clk_insetup = Signal() - self.sync += [ - nub_clk_prev[0].eq(nub_clk), - ] - self.sync += [ - nub_clk_prev[i].eq(nub_clk_prev[i-1]) for i in range(1, nub_clk_prev_bits) - ] - self.sync += [ - nub_clk_negedge.eq(~nub_clk & nub_clk_prev[0]), - nub_clk_posedge.eq( nub_clk & ~nub_clk_prev[0]), - nub_clk_insetup.eq( nub_clk & (nub_clk_prev != ((2**nub_clk_prev_bits)-1))), # if one of the previous X cycles is zero, we're early enough to set up signals - ] + if (usesampling): + # when using 'sampling', the NuBus signals are sampled at sys_clk frequency instead of synchronously using nubus_clk + # I'm not completely sure about timings, but in practice it seems to work... + # The major benefit is that when a read is detected, it is sent to the Wishbone synchronously as the signals are already in sys_clk + # And when Wishbone answers, we just wait for the next detected NuBus edge to answer + # It significantly improves read latency + # Writes don't see the same improvement, are they always are fire-and-forget in a FIFO anyway + nub_clk = ClockSignal(cd_nubus) + nub_resetn = ~ResetSignal(cd_nubus) + nub_clk_prev_bits = 4 # how many cycles after posedge do we still dare set some signals (i.e. still before setup time before negedge) + nub_clk_prev = Signal(nub_clk_prev_bits) + nub_clk_negedge = Signal() + nub_clk_posedge = Signal() + nub_clk_insetup = Signal() + self.sync += [ + nub_clk_prev[0].eq(nub_clk), + ] + self.sync += [ + nub_clk_prev[i].eq(nub_clk_prev[i-1]) for i in range(1, nub_clk_prev_bits) + ] + self.sync += [ + nub_clk_negedge.eq(~nub_clk & nub_clk_prev[0]), + nub_clk_posedge.eq( nub_clk & ~nub_clk_prev[0]), + nub_clk_insetup.eq( nub_clk & (nub_clk_prev != ((2**nub_clk_prev_bits)-1))), # if one of the previous X cycles is zero, we're early enough to set up signals + ] # Signals for tri-stated nubus access # slave @@ -119,10 +127,10 @@ class NuBus(Module): # current value, registered from the sampled/processed/decoded signals # change is controlled by the FSM current_adr = Signal(32) - current_tm0 = Signal() - current_tm1 = Signal() + #current_tm0 = Signal() + #current_tm1 = Signal() current_sel = Signal(4) - current_block = Signal() + #current_block = Signal() current_data = Signal(32) # write FIFO to speed up bus turnaround on NuBus side @@ -131,179 +139,252 @@ class NuBus(Module): ("data", 32), ("sel", 4), ] - self.submodules.write_fifo = write_fifo = SyncFIFOBuffered(width=layout_len(write_fifo_layout), depth=16) + if (usesampling): + self.submodules.write_fifo = write_fifo = SyncFIFOBuffered(width=layout_len(write_fifo_layout), depth=16) + else: + self.submodules.write_fifo = write_fifo = ClockDomainsRenamer({"read": "sys", "write": "nubus"})(AsyncFIFOBuffered(width=layout_len(write_fifo_layout), depth=16)) 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.sync += [ - #If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge - If(nub_clk_negedge, - sampled_tm0.eq(~tm0_i_n), - sampled_tm1.eq(~tm1_i_n), - sampled_start.eq(~start_i_n), - sampled_rqst.eq(~rqst_i_n), - sampled_ack.eq(~ack_i_n), - sampled_ad.eq(~ad_i_n), + if (usesampling): + # sys_clk sampling of the nubus signals + self.sync += [ + #If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge + If(nub_clk_negedge, + sampled_tm0.eq(~tm0_i_n), + sampled_tm1.eq(~tm1_i_n), + sampled_start.eq(~start_i_n), + sampled_rqst.eq(~rqst_i_n), + sampled_ack.eq(~ack_i_n), + sampled_ad.eq(~ad_i_n), + ) + ] + self.comb += [ + decoded_block.eq(sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0), # 1x block write or 1x block read + decoded_sel[3].eq(sampled_tm1 & sampled_ad[1] & sampled_ad[0] & sampled_tm0 # Byte 3 + | sampled_tm1 & sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 1 + | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word + ), + decoded_sel[2].eq(sampled_tm1 & sampled_ad[1] & ~sampled_ad[0] & sampled_tm0 # Byte 2 + | sampled_tm1 & sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 1 + | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word + ), + decoded_sel[1].eq(sampled_tm1 & ~sampled_ad[1] & sampled_ad[0] & sampled_tm0 # Byte 1 + | sampled_tm1 & ~sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 0 + | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word + ), + decoded_sel[0].eq(sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & sampled_tm0 # Byte 0 + | sampled_tm1 & ~sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 0 + | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word + ), + ] + else: + # nubus-synchronous sampling (in Verilog for negedge) + self.specials += Instance("nubus_sampling", + i_nub_clkn = ClockSignal(cd_nubus), + i_nub_resetn = ~ResetSignal(cd_nubus), + i_nub_tm0n = tm0_i_n, + i_nub_tm1n = tm1_i_n, + i_nub_startn = start_i_n, + i_nub_rqstn = rqst_i_n, + i_nub_ackn = ack_i_n, + i_nub_adn = ad_i_n, + + o_tm0 = sampled_tm0, + o_tm1 = sampled_tm1, + o_start = sampled_start, + o_rqst = sampled_rqst, + o_ack = sampled_ack, + o_ad = sampled_ad, + + o_sel = decoded_sel, + o_block = decoded_block, + o_busy = decoded_busy, ) - ] - - self.comb += [ - decoded_block.eq(sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0), # 1x block write or 1x block read - decoded_sel[3].eq(sampled_tm1 & sampled_ad[1] & sampled_ad[0] & sampled_tm0 # Byte 3 - | sampled_tm1 & sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 1 - | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word - ), - decoded_sel[2].eq(sampled_tm1 & sampled_ad[1] & ~sampled_ad[0] & sampled_tm0 # Byte 2 - | sampled_tm1 & sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 1 - | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word - ), - decoded_sel[1].eq(sampled_tm1 & ~sampled_ad[1] & sampled_ad[0] & sampled_tm0 # Byte 1 - | sampled_tm1 & ~sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 0 - | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word - ), - decoded_sel[0].eq(sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & sampled_tm0 # Byte 0 - | sampled_tm1 & ~sampled_ad[1] & sampled_ad[0] & ~sampled_tm0 # Half 0 - | sampled_tm1 & ~sampled_ad[1] & ~sampled_ad[0] & ~sampled_tm0 # Word - ), - ] self.read_ctr = read_ctr = Signal(32) self.writ_ctr = writ_ctr = Signal(32) - self.submodules.slave_fsm = slave_fsm = FSM(reset_state="Reset") - slave_fsm.act("Reset", - NextState("Idle") - ) - slave_fsm.act("Idle", - # only react to transaction start at posedge - If(nub_clk_posedge & (decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & ~sampled_tm1,# & ~decoded_block, # regular read (we always send back 32 bits, so don't worry about byte/word) - If(decoded_myslot, - NextValue(current_adr, processed_ad), - ).Else( # decoded_mysuperslot, - NextValue(current_adr, processed_super_ad), - ), - #NextValue(current_tm0, sampled_tm0), - #NextValue(current_tm1, sampled_tm1), - #NextValue(current_sel, decoded_sel), - #NextValue(current_block, decoded_block), - #If(decoded_block, - # NextValue(decoded_block_memory, 1),), - NextValue(read_ctr, read_ctr + 1), - NextState("WaitWBRead"), - ).Elif(nub_clk_posedge & (decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & sampled_tm1,# & ~decoded_block, # regular write + if (usesampling): + self.submodules.slave_fsm = slave_fsm = FSM(reset_state="Reset") + slave_fsm.act("Reset", + NextState("Idle") + ) + slave_fsm.act("Idle", + # only react to transaction start at posedge + If(nub_clk_posedge & (decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & ~sampled_tm1,# & ~decoded_block, # regular read (we always send back 32 bits, so don't worry about byte/word) If(decoded_myslot, NextValue(current_adr, processed_ad), ).Else( # decoded_mysuperslot, - NextValue(current_adr, processed_super_ad), + NextValue(current_adr, processed_super_ad), ), - #NextValue(current_tm0, sampled_tm0), - #NextValue(current_tm1, sampled_tm1), - NextValue(current_sel, decoded_sel), - #NextValue(current_block, decoded_block), - #If(decoded_block, - # NextValue(decoded_block_memory, 1),), - #NextState("GetNubusWriteData"), - NextValue(writ_ctr, writ_ctr + 1), - If(write_fifo.writable, - NextState("NubusWriteDataToFIFO"), + NextValue(read_ctr, read_ctr + 1), + NextState("WaitWBRead"), + ).Elif(nub_clk_posedge & (decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & sampled_tm1,# & ~decoded_block, # regular write + If(decoded_myslot, + NextValue(current_adr, processed_ad), + ).Else( # decoded_mysuperslot, + NextValue(current_adr, processed_super_ad), + ), + NextValue(current_sel, decoded_sel), + NextValue(writ_ctr, writ_ctr + 1), + If(write_fifo.writable, + NextState("NubusWriteDataToFIFO"), + ).Else( + NextState("NubusWaitForFIFO"), + ) + ) + ) + slave_fsm.act("WaitWBRead", + wb_read.cyc.eq(1), + wb_read.stb.eq(1), + wb_read.we.eq(0), + wb_read.sel.eq(0xf), + wb_read.adr.eq(current_adr[2:32]), + tmo_oe.eq(1), + tm0_o_n.eq(1), + tm1_o_n.eq(1), + ack_o_n.eq(1), + If(wb_read.ack, + NextValue(current_data, wb_read.dat_r), + If(nub_clk_insetup, + ad_oe.eq(1), + ad_o_n.eq(~wb_read.dat_r), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + NextState("FinishRead"), ).Else( - NextState("NubusWaitForFIFO"), + NextState("WaitBeforeFinishRead"), ) - ) - ) - slave_fsm.act("WaitWBRead", - wb_read.cyc.eq(1), - wb_read.stb.eq(1), - wb_read.we.eq(0), - wb_read.sel.eq(0xf), - wb_read.adr.eq(current_adr[2:32]), - tmo_oe.eq(1), - tm0_o_n.eq(1), - tm1_o_n.eq(1), - ack_o_n.eq(1), - If(wb_read.ack, - NextValue(current_data, wb_read.dat_r), - If(nub_clk_insetup, - ad_oe.eq(1), - ad_o_n.eq(~wb_read.dat_r), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - NextState("FinishRead"), - ).Else( - NextState("WaitBeforeFinishRead"), - ) - ) - ) - slave_fsm.act("WaitBeforeFinishRead", - tmo_oe.eq(1), - tm0_o_n.eq(1), - tm1_o_n.eq(1), - ack_o_n.eq(1), - If(nub_clk_insetup, - ad_oe.eq(1), - ad_o_n.eq(~current_data), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - NextState("FinishRead"), - ), - ) - slave_fsm.act("FinishRead", - tmo_oe.eq(1), - ad_oe.eq(1), - ad_o_n.eq(~current_data), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - #If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge - If(nub_clk_negedge, - NextState("ReadCleanup"), - ) - ) - slave_fsm.act("ReadCleanup", - tmo_oe.eq(1), - ad_oe.eq(1), - ad_o_n.eq(~current_data), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - NextState("Idle"), - ), - - slave_fsm.act("NubusWriteDataToFIFO", - tmo_oe.eq(1), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - #If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge - If(nub_clk_negedge, - write_fifo.we.eq(1), - NextState("WriteCleanup"), - ) - ) - slave_fsm.act("NubusWaitForFIFO", - tmo_oe.eq(1), - tm0_o_n.eq(1), - tm1_o_n.eq(1), - ack_o_n.eq(1), - If(nub_clk_posedge & write_fifo.writable, - NextState("NubusWriteDataToFIFO"), - ) - ) - slave_fsm.act("WriteCleanup", # extra sysclk cycle after negedge - tmo_oe.eq(1), - tm0_o_n.eq(0), - tm1_o_n.eq(0), - ack_o_n.eq(0), - NextState("Idle"), - ) + ) + ) + slave_fsm.act("WaitBeforeFinishRead", + tmo_oe.eq(1), + tm0_o_n.eq(1), + tm1_o_n.eq(1), + ack_o_n.eq(1), + If(nub_clk_insetup, + ad_oe.eq(1), + ad_o_n.eq(~current_data), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + NextState("FinishRead"), + ), + ) + slave_fsm.act("FinishRead", + tmo_oe.eq(1), + ad_oe.eq(1), + ad_o_n.eq(~current_data), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + #If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge + If(nub_clk_negedge, + NextState("ReadCleanup"), + ) + ) + slave_fsm.act("ReadCleanup", + tmo_oe.eq(1), + ad_oe.eq(1), + ad_o_n.eq(~current_data), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + NextState("Idle"), + ), + + slave_fsm.act("NubusWriteDataToFIFO", + tmo_oe.eq(1), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + #If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge + If(nub_clk_negedge, + write_fifo.we.eq(1), + NextState("WriteCleanup"), + ) + ) + slave_fsm.act("NubusWaitForFIFO", + tmo_oe.eq(1), + tm0_o_n.eq(1), + tm1_o_n.eq(1), + ack_o_n.eq(1), + If(nub_clk_posedge & write_fifo.writable, + NextState("NubusWriteDataToFIFO"), + ) + ) + slave_fsm.act("WriteCleanup", # extra sysclk cycle after negedge + tmo_oe.eq(1), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + NextState("Idle"), + ) + else: + self.submodules.slave_fsm = slave_fsm = ClockDomainsRenamer(cd_nubus)(FSM(reset_state="Reset")) + slave_fsm.act("Reset", + NextState("Idle") + ) + slave_fsm.act("Idle", + If((decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & ~sampled_tm1,# & ~decoded_block, # regular read (we always send back 32 bits, so don't worry about byte/word) + If(decoded_myslot, + NextValue(current_adr, processed_ad), + ).Else( # decoded_mysuperslot, + NextValue(current_adr, processed_super_ad), + ), + NextValue(read_ctr, read_ctr + 1), + NextState("WaitWBRead"), + ).Elif((decoded_myslot | decoded_mysuperslot) & sampled_start & ~sampled_ack & sampled_tm1,# & ~decoded_block, # regular write + If(decoded_myslot, + NextValue(current_adr, processed_ad), + ).Else( # decoded_mysuperslot, + NextValue(current_adr, processed_super_ad), + ), + NextValue(current_sel, decoded_sel), + NextValue(writ_ctr, writ_ctr + 1), + NextState("NubusWriteDataToFIFO"), + ) + ) + slave_fsm.act("WaitWBRead", + wb_read.cyc.eq(1), + wb_read.stb.eq(1), + wb_read.we.eq(0), + wb_read.sel.eq(0xf), + wb_read.adr.eq(current_adr[2:32]), + tmo_oe.eq(1), + tm0_o_n.eq(1), + tm1_o_n.eq(1), + ack_o_n.eq(1), + If(wb_read.ack, + ad_oe.eq(1), + ad_o_n.eq(~wb_read.dat_r), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + NextState("Idle"), + ) + ) + slave_fsm.act("NubusWriteDataToFIFO", + tmo_oe.eq(1), + tm0_o_n.eq(1), + tm1_o_n.eq(1), + ack_o_n.eq(1), + If(write_fifo.writable, + write_fifo.we.eq(1), + tm0_o_n.eq(0), + tm1_o_n.eq(0), + ack_o_n.eq(0), + NextState("Idle"), + ) + ) # connect the write FIFO inputs self.comb += [ write_fifo_din.adr.eq(current_adr), # recorded - write_fifo_din.data.eq(~ad_i_n), # we do it live, direct from the bus as we use it at the same time we update sampled_ad + write_fifo_din.data.eq(~ad_i_n if usesampling else sampled_ad), write_fifo_din.sel.eq(current_sel), # recorded ] # deal with emptying the Write FIFO to the write WB @@ -630,12 +711,6 @@ class NuBus(Module): ) ) - #self.comb += [ - # led0.eq(~dma_fsm.ongoing("Idle")), - # #led1.eq(dma_fsm.ongoing("Burst4DatCycleAck") | dma_fsm.ongoing("Burst4DatCycleTM0") ), - # led1.eq(sampled_rqst | wb_dma.cyc), - #] - # stuff at this end so we don't use the signals inadvertantly # real NuBus signals @@ -688,14 +763,14 @@ class NuBus(Module): nf_fpga_to_cpld_signal.eq(~rqst_oe), ] - self.sync += [ - If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge - decoded_busy.eq(~decoded_busy & nub_ackn & ~nub_startn # beginning of transaction - | decoded_busy & nub_ackn & nub_resetn), # hold during cycle - ) - ] + if (usesampling): + self.sync += [ + If((~nub_clk & nub_clk_prev[0]), # simultaneous with setting negedge + decoded_busy.eq(~decoded_busy & nub_ackn & ~nub_startn # beginning of transaction + | decoded_busy & nub_ackn & nub_resetn), # hold during cycle + ) + ] - def add_sources(self, platform): # sampling of data on falling edge of clock, done in verilog platform.add_source("nubus_sampling.v", "verilog") diff --git a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py index 29751b4..f66f574 100644 --- a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py +++ b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py @@ -16,8 +16,7 @@ from litex.soc.cores.led import LedChaser import ztex213_nubus import nubus_to_fpga_export -import nubus_full -import nubus_full_sampling +import nubus_full_unified import nubus_stat from litedram.modules import MT41J128M16 @@ -303,7 +302,7 @@ class NuBusFPGA(SoCCore): # Interface NuBus to wishbone # we need to cross clock domains - xibus=1 + xibus=False if (xibus): wishbone_master_sys = wishbone.Interface(data_width=self.bus.data_width) self.submodules.wishbone_master_nubus = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_master_sys, cd_master="nubus", cd_slave="sys") @@ -333,9 +332,9 @@ class NuBusFPGA(SoCCore): #] self.comb += irq_line.eq(fb_irq) # active low, enable if one is low else: - sampling = 1 + usesampling = True wishbone_master_sys = wishbone.Interface(data_width=self.bus.data_width) - if (not sampling): + if (not usesampling): # we need an extra CDC self.submodules.wishbone_master_nubus = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_master_sys, cd_master="nubus", cd_slave="sys") # for non-sampling only nubus_writemaster_sys = wishbone.Interface(data_width=self.bus.data_width) wishbone_slave_nubus = wishbone.Interface(data_width=self.bus.data_width) @@ -390,26 +389,17 @@ class NuBusFPGA(SoCCore): self.comb += dma_irq.eq(self.exchange_with_mem.irq) - if (sampling): - self.submodules.nubus = nubus_full_sampling.NuBus(soc=self, - burst_size=burst_size, - tosbus_fifo=self.tosbus_fifo, - fromsbus_fifo=self.fromsbus_fifo, - fromsbus_req_fifo=self.fromsbus_req_fifo, - wb_read=wishbone_master_sys, - wb_write=nubus_writemaster_sys, - wb_dma=wishbone_slave_nubus, - cd_nubus="nubus") - else: - self.submodules.nubus = nubus_full.NuBus(soc=self, - burst_size=burst_size, - tosbus_fifo=self.tosbus_fifo, - fromsbus_fifo=self.fromsbus_fifo, - fromsbus_req_fifo=self.fromsbus_req_fifo, - wb_read=self.wishbone_master_nubus, - wb_write=nubus_writemaster_sys, - wb_dma=wishbone_slave_nubus, - cd_nubus="nubus") + self.submodules.nubus = nubus_full_unified.NuBus(soc=self, + burst_size=burst_size, + tosbus_fifo=self.tosbus_fifo, + fromsbus_fifo=self.fromsbus_fifo, + fromsbus_req_fifo=self.fromsbus_req_fifo, + wb_read=(wishbone_master_sys if usesampling else self.wishbone_master_nubus), # CDC or not + wb_write=nubus_writemaster_sys, + wb_dma=wishbone_slave_nubus, + usesampling=usesampling, + cd_nubus="nubus") + self.bus.add_master(name="NuBusBridgeToWishbone", master=wishbone_master_sys) self.bus.add_slave("DMA", self.wishbone_slave_sys, SoCRegion(origin=self.mem_map.get("master", None), size=0x40000000, cached=False)) self.bus.add_master(name="NuBusBridgeToWishboneWrite", master=nubus_writemaster_sys)