axis_replay_buffer: Fix slave handshaking
Handshaking happens on the rising edge based on the current values of
ready/valid. Fix the current (incorrect) logic. Additionally, modify the
testbench to properly stimulate AXI stream cores. This will catch
several handshaking failures fixed in previous commits.
Fixes: 52325f2
("Add AXI stream replay buffer")
Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
parent
58cebe5ac2
commit
2c2527e8d9
|
@ -62,8 +62,7 @@ module axis_replay_buffer (
|
||||||
parameter BUF_SIZE = 54;
|
parameter BUF_SIZE = 54;
|
||||||
localparam BUF_WIDTH = $clog2(BUF_SIZE + 1);
|
localparam BUF_WIDTH = $clog2(BUF_SIZE + 1);
|
||||||
|
|
||||||
reg [DATA_WIDTH - 1:0] s_axis_data_last;
|
reg s_axis_ready_next;
|
||||||
reg s_axis_valid_last, s_axis_last_last, s_axis_ready_next;
|
|
||||||
reg m_axis_valid_next, m_axis_last_next;
|
reg m_axis_valid_next, m_axis_last_next;
|
||||||
reg sent_last, sent_last_next;
|
reg sent_last, sent_last_next;
|
||||||
reg [DATA_WIDTH - 1:0] buffer [(2 ** BUF_WIDTH) - 1:0];
|
reg [DATA_WIDTH - 1:0] buffer [(2 ** BUF_WIDTH) - 1:0];
|
||||||
|
@ -77,10 +76,10 @@ module axis_replay_buffer (
|
||||||
s_ptr_next = s_ptr;
|
s_ptr_next = s_ptr;
|
||||||
last_next = last;
|
last_next = last;
|
||||||
last_ptr_next = last_ptr;
|
last_ptr_next = last_ptr;
|
||||||
if (s_axis_valid_last && s_axis_ready) begin
|
if (s_axis_valid && s_axis_ready) begin
|
||||||
we = 1;
|
we = 1;
|
||||||
s_ptr_next = s_ptr + 1;
|
s_ptr_next = s_ptr + 1;
|
||||||
if (s_axis_last_last) begin
|
if (s_axis_last) begin
|
||||||
last_next = 1;
|
last_next = 1;
|
||||||
last_ptr_next = s_ptr;
|
last_ptr_next = s_ptr;
|
||||||
end
|
end
|
||||||
|
@ -141,11 +140,10 @@ module axis_replay_buffer (
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (we)
|
if (we)
|
||||||
buffer[s_ptr[BUF_WIDTH - 1:0]] <= { s_axis_data_last };
|
buffer[s_ptr[BUF_WIDTH - 1:0]] <= { s_axis_data };
|
||||||
if (re)
|
if (re)
|
||||||
{ m_axis_data } <= buffer[m_ptr[BUF_WIDTH - 1:0]];
|
{ m_axis_data } <= buffer[m_ptr[BUF_WIDTH - 1:0]];
|
||||||
last_ptr <= last_ptr_next;
|
last_ptr <= last_ptr_next;
|
||||||
s_axis_data_last <= s_axis_data;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk, posedge rst) begin
|
always @(posedge clk, posedge rst) begin
|
||||||
|
@ -154,8 +152,6 @@ module axis_replay_buffer (
|
||||||
s_ptr <= 0;
|
s_ptr <= 0;
|
||||||
last <= 0;
|
last <= 0;
|
||||||
replayable <= 1;
|
replayable <= 1;
|
||||||
s_axis_valid_last <= 0;
|
|
||||||
s_axis_last_last <= 0;
|
|
||||||
s_axis_ready <= 1;
|
s_axis_ready <= 1;
|
||||||
m_axis_valid <= 0;
|
m_axis_valid <= 0;
|
||||||
m_axis_last <= 0;
|
m_axis_last <= 0;
|
||||||
|
@ -165,8 +161,6 @@ module axis_replay_buffer (
|
||||||
s_ptr <= s_ptr_next;
|
s_ptr <= s_ptr_next;
|
||||||
last <= last_next;
|
last <= last_next;
|
||||||
replayable <= replayable_next;
|
replayable <= replayable_next;
|
||||||
s_axis_valid_last <= s_axis_valid;
|
|
||||||
s_axis_last_last <= s_axis_last;
|
|
||||||
s_axis_ready <= s_axis_ready_next;
|
s_axis_ready <= s_axis_ready_next;
|
||||||
m_axis_last <= m_axis_last_next;
|
m_axis_last <= m_axis_last_next;
|
||||||
m_axis_valid <= m_axis_valid_next;
|
m_axis_valid <= m_axis_valid_next;
|
||||||
|
|
|
@ -28,10 +28,8 @@ async def send_packet(signals, packet, ratio=1, last_extra=0):
|
||||||
if 'last' in signals:
|
if 'last' in signals:
|
||||||
signals['last'].value = last
|
signals['last'].value = last
|
||||||
await RisingEdge(signals['clk'])
|
await RisingEdge(signals['clk'])
|
||||||
while True:
|
while not signals['ready'].value:
|
||||||
await FallingEdge(signals['clk'])
|
await RisingEdge(signals['clk'])
|
||||||
if signals['ready'].value:
|
|
||||||
break
|
|
||||||
signals['valid'].value = 0
|
signals['valid'].value = 0
|
||||||
if ratio != 1 and not last:
|
if ratio != 1 and not last:
|
||||||
await ClockCycles(signals['clk'], ratio - 1, rising=False)
|
await ClockCycles(signals['clk'], ratio - 1, rising=False)
|
||||||
|
@ -40,13 +38,14 @@ async def recv_packet(signals, packet, last=None):
|
||||||
if last is None:
|
if last is None:
|
||||||
last = len(packet)
|
last = len(packet)
|
||||||
|
|
||||||
|
await RisingEdge(signals['clk'])
|
||||||
for i, val in enumerate(packet):
|
for i, val in enumerate(packet):
|
||||||
while not signals['valid'].value or not signals['ready'].value:
|
while not signals['valid'].value or not signals['ready'].value:
|
||||||
await FallingEdge(signals['clk'])
|
await RisingEdge(signals['clk'])
|
||||||
assert signals['data'].value == val
|
assert signals['data'].value == val
|
||||||
if 'last' in signals:
|
if 'last' in signals:
|
||||||
assert signals['last'].value == (i == last - 1)
|
assert signals['last'].value == (i == last - 1)
|
||||||
await FallingEdge(signals['clk'])
|
await RisingEdge(signals['clk'])
|
||||||
|
|
||||||
@timeout(30, 'us')
|
@timeout(30, 'us')
|
||||||
async def test_replay(buf, in_ratio, out_ratio):
|
async def test_replay(buf, in_ratio, out_ratio):
|
||||||
|
|
Loading…
Reference in New Issue