Fix UpConverter write path not working as intended
LiteDRAM controler does not check if wdata stream has valid signal set, it assumes that wdata has valid data when cmd is send. Signed-off-by: Maciej Dudek <mdudek@antmicro.com>
This commit is contained in:
parent
7b3c6abd50
commit
c54fc4af82
|
@ -186,6 +186,7 @@ class LiteDRAMNativePortUpConverter(Module):
|
||||||
send_inner_cmd_addr = Signal.like(port_to.cmd.addr)
|
send_inner_cmd_addr = Signal.like(port_to.cmd.addr)
|
||||||
send_inner_cmd_we = Signal.like(port_to.cmd.we)
|
send_inner_cmd_we = Signal.like(port_to.cmd.we)
|
||||||
|
|
||||||
|
send_wdata_latch = Signal(reset=1)
|
||||||
self.cmd_buffer = cmd_buffer = stream.SyncFIFO([ ("cmd_addr", send_cmd_addr.nbits),
|
self.cmd_buffer = cmd_buffer = stream.SyncFIFO([ ("cmd_addr", send_cmd_addr.nbits),
|
||||||
("cmd_we", send_cmd_we.nbits)],
|
("cmd_we", send_cmd_we.nbits)],
|
||||||
cmd_buffer_depth)
|
cmd_buffer_depth)
|
||||||
|
@ -207,10 +208,10 @@ class LiteDRAMNativePortUpConverter(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
send_fsm.act("SEND",
|
send_fsm.act("SEND",
|
||||||
port_to.cmd.valid.eq(1),
|
port_to.cmd.valid.eq(~send_inner_cmd_we | (port_to.wdata.valid & send_wdata_latch)),
|
||||||
port_to.cmd.addr.eq(send_inner_cmd_addr),
|
port_to.cmd.addr.eq(send_inner_cmd_addr),
|
||||||
port_to.cmd.we.eq(send_inner_cmd_we),
|
port_to.cmd.we.eq(send_inner_cmd_we),
|
||||||
If(port_to.cmd.ready,
|
If(port_to.cmd.ready & port_to.cmd.valid,
|
||||||
If(cmd_buffer.source.valid,
|
If(cmd_buffer.source.valid,
|
||||||
cmd_buffer.source.ready.eq(1),
|
cmd_buffer.source.ready.eq(1),
|
||||||
NextValue(send_inner_cmd_addr, cmd_buffer.source.cmd_addr),
|
NextValue(send_inner_cmd_addr, cmd_buffer.source.cmd_addr),
|
||||||
|
@ -221,6 +222,18 @@ class LiteDRAMNativePortUpConverter(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# send_latch keeps track if we have already send write command to valid wdata
|
||||||
|
self.sync += [
|
||||||
|
If(port_to.cmd.ready & port_to.cmd.valid & send_inner_cmd_we & ~wdata_finished,
|
||||||
|
# we have avlid cmd and wdata, but port_to is not ready to recive data, send cmd
|
||||||
|
# and lock out further write commands until we send our wdata
|
||||||
|
send_wdata_latch.eq(0),
|
||||||
|
).Elif(wdata_finished,
|
||||||
|
# we have send our wdata, unlock send
|
||||||
|
send_wdata_latch.eq(1),
|
||||||
|
)
|
||||||
|
]
|
||||||
# Command flow is quite complicate, nonlinear and it depends on type read/write,
|
# Command flow is quite complicate, nonlinear and it depends on type read/write,
|
||||||
# so here is summary:
|
# so here is summary:
|
||||||
# This FSM receives commands from `port_from` and pushes them to `cmd_buffer` queue,
|
# This FSM receives commands from `port_from` and pushes them to `cmd_buffer` queue,
|
||||||
|
@ -293,6 +306,7 @@ class LiteDRAMNativePortUpConverter(Module):
|
||||||
fsm.act("WAIT-FOR-CMD",
|
fsm.act("WAIT-FOR-CMD",
|
||||||
If(port_from.cmd.valid,
|
If(port_from.cmd.valid,
|
||||||
NextValue(counter, 0),
|
NextValue(counter, 0),
|
||||||
|
NextValue(cmd_last, 0),
|
||||||
NextValue(cmd_addr, port_from.cmd.addr[log2_int(ratio):]),
|
NextValue(cmd_addr, port_from.cmd.addr[log2_int(ratio):]),
|
||||||
NextValue(cmd_we, port_from.cmd.we),
|
NextValue(cmd_we, port_from.cmd.we),
|
||||||
If(port_from.cmd.we,
|
If(port_from.cmd.we,
|
||||||
|
@ -485,14 +499,12 @@ class LiteDRAMNativePortUpConverter(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(wdata_fifo.source.valid & wdata_fifo.source.ready,
|
|
||||||
Case(write_chunk, cases)
|
|
||||||
),
|
|
||||||
If(wdata_finished,
|
If(wdata_finished,
|
||||||
write_inner_counter.eq(0),
|
write_inner_counter.eq(0),
|
||||||
wdata_buffer.we.eq(0),
|
wdata_buffer.we.eq(0),
|
||||||
).Elif(wdata_fifo.source.valid & wdata_fifo.source.ready,
|
).Elif(wdata_fifo.source.valid & wdata_fifo.source.ready,
|
||||||
write_inner_counter.eq(write_inner_counter + 1)
|
write_inner_counter.eq(write_inner_counter + 1),
|
||||||
|
Case(write_chunk, cases)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -509,10 +521,16 @@ class LiteDRAMNativePortUpConverter(Module):
|
||||||
If(self.send_cmd_busy,
|
If(self.send_cmd_busy,
|
||||||
NextState("WAIT-TO-SEND")
|
NextState("WAIT-TO-SEND")
|
||||||
).Else(
|
).Else(
|
||||||
If(port_from.cmd.valid & port_from.cmd.we,
|
|
||||||
NextValue(counter, 0),
|
NextValue(counter, 0),
|
||||||
|
NextValue(cmd_last, 0),
|
||||||
|
If(port_from.cmd.valid & port_from.cmd.we,
|
||||||
NextValue(cmd_addr, port_from.cmd.addr[log2_int(self.ratio):]),
|
NextValue(cmd_addr, port_from.cmd.addr[log2_int(self.ratio):]),
|
||||||
NextValue(cmd_we, port_from.cmd.we),
|
NextValue(cmd_we, port_from.cmd.we),
|
||||||
|
port_from.cmd.ready.eq(1),
|
||||||
|
NextValue(counter, 1),
|
||||||
|
NextValue(ordering[:1 * log2_int(self.ratio)],
|
||||||
|
port_from.cmd.addr[:log2_int(self.ratio)]),
|
||||||
|
NextValue(cmd_last, port_from.cmd.last),
|
||||||
NextState("FILL")
|
NextState("FILL")
|
||||||
).Else(
|
).Else(
|
||||||
NextState("WAIT-FOR-CMD")
|
NextState("WAIT-FOR-CMD")
|
||||||
|
@ -536,8 +554,9 @@ class LiteDRAMNativePortUpConverter(Module):
|
||||||
self.send_cmd_we.eq(port_from.cmd.we),
|
self.send_cmd_we.eq(port_from.cmd.we),
|
||||||
NextValue(cmd_addr, port_from.cmd.addr[log2_int(self.ratio):]),
|
NextValue(cmd_addr, port_from.cmd.addr[log2_int(self.ratio):]),
|
||||||
NextValue(cmd_we, port_from.cmd.we),
|
NextValue(cmd_we, port_from.cmd.we),
|
||||||
If(self.send_cmd_busy,
|
|
||||||
NextValue(counter, 0),
|
NextValue(counter, 0),
|
||||||
|
NextValue(cmd_last, 0),
|
||||||
|
If(self.send_cmd_busy,
|
||||||
NextState("WAIT-TO-SEND")
|
NextState("WAIT-TO-SEND")
|
||||||
).Else(
|
).Else(
|
||||||
port_from.cmd.ready.eq(1),
|
port_from.cmd.ready.eq(1),
|
||||||
|
|
|
@ -14,7 +14,7 @@ from litex.soc.interconnect import wishbone
|
||||||
from litedram.frontend.wishbone import LiteDRAMWishbone2Native
|
from litedram.frontend.wishbone import LiteDRAMWishbone2Native
|
||||||
from litedram.common import LiteDRAMNativePort
|
from litedram.common import LiteDRAMNativePort
|
||||||
|
|
||||||
from test.common import DRAMMemory, MemoryTestDataMixin
|
from test.common import *
|
||||||
|
|
||||||
|
|
||||||
class TestWishbone(MemoryTestDataMixin, unittest.TestCase):
|
class TestWishbone(MemoryTestDataMixin, unittest.TestCase):
|
||||||
|
@ -40,6 +40,7 @@ class TestWishbone(MemoryTestDataMixin, unittest.TestCase):
|
||||||
main_generator(dut),
|
main_generator(dut),
|
||||||
dut.mem.write_handler(dut.port),
|
dut.mem.write_handler(dut.port),
|
||||||
dut.mem.read_handler(dut.port),
|
dut.mem.read_handler(dut.port),
|
||||||
|
timeout_generator(10000)
|
||||||
]
|
]
|
||||||
run_simulation(dut, generators, vcd_name='sim.vcd')
|
run_simulation(dut, generators, vcd_name='sim.vcd')
|
||||||
self.assertEqual(dut.mem.mem, mem_expected)
|
self.assertEqual(dut.mem.mem, mem_expected)
|
||||||
|
|
Loading…
Reference in New Issue