sync non-sampling with sampling code

This commit is contained in:
Romain Dolbeau 2022-09-21 23:05:23 +02:00
parent 45de956195
commit b935541f61

View File

@ -7,8 +7,12 @@ import litex
from litex.soc.interconnect import wishbone
class NuBus(Module):
def __init__(self, platform, wb_read, wb_write, wb_dma, cd_nubus="nubus", cd_nubus90="nubus90"):
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)
@ -18,11 +22,11 @@ class NuBus(Module):
# slave
tmo_oe = Signal() # output enable
tm0_i_n = Signal()
tm0_o_n = Signal()
tm0_o_n = Signal(reset = 1)
tm1_i_n = Signal()
tm1_o_n = Signal()
tm1_o_n = Signal(reset = 1)
ack_i_n = Signal()
ack_o_n = Signal()
ack_o_n = Signal(reset = 1)
ad_oe = Signal()
ad_i_n = Signal(32)
@ -31,12 +35,12 @@ class NuBus(Module):
id_i_n = Signal(4)
start_i_n = Signal()
start_o_n = Signal() # master via master_oe
start_o_n = Signal(reset = 1) # master via master_oe
# master
rqst_oe = Signal()
rqst_i_n = Signal()
rqst_o_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*
@ -46,6 +50,7 @@ class NuBus(Module):
sampled_start = Signal()
sampled_ack = Signal()
sampled_ad = Signal(32)
sampled_ad_byterev = Signal(32)
# master
sampled_rqst = Signal()
@ -62,6 +67,10 @@ class NuBus(Module):
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
@ -232,16 +241,59 @@ class NuBus(Module):
]
self.submodules.dma_fsm = dma_fsm = ClockDomainsRenamer(cd_nubus)(FSM(reset_state="Reset"))
ctr = Signal(2) # 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())
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",
@ -256,7 +308,11 @@ class NuBus(Module):
rqst_o_n.eq(0),
If(grant & ~decoded_busy, # I'm now 'owner'
NextValue(owning_bus, 1),
NextState("AdrCycle"),
If(burst,
NextState("Burst4AdrCycle"),
).Else(
NextState("AdrCycle"),
),
)
)
dma_fsm.act("AdrCycle",
@ -307,6 +363,110 @@ class NuBus(Module):
NextState("FinishCycle"),
)
)
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),
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),
ack_o_n.eq(1),
NextValue(ctr, 0),
If(burst_we,
NextState("Burst4DatCycleTM0"),
).Else(
NextState("Burst4ReadWaitForTM0"),
)
)
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,
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),
}),
NextValue(ctr, ctr + 1),
If(ctr == 0x2, # 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),
#fromsbus_fifo_din.data.eq(Cat(fifo_buffer[0:96], sampled_ad)), # we use sampled_ad directly for 96:128
fromsbus_fifo_din.data.eq(Cat(fifo_buffer[0:96], sampled_ad_byterev)), # we use sampled_ad directly for 96:128
# fixme: check status ??? (tm0 and tm1 should be active for no-error)
#NextValue(led0, (~sampled_tm0 | ~sampled_tm1)),
NextState("FinishCycle"),
)
)
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
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]),
}),
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 == 0x2, # 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
#ad_o_n.eq(~tosbus_fifo_dout.data[96:128]), # last word
ad_o_n.eq(~tosbus_fifo_dout_data_byterev[96:128]), # last word
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