axis_wb_bridge: Fix AXIS master

The AXI stream master doesn't cope with slaves that aren't ready all the
time. There are two separate issues: first, the data was only valid for one
cycle. Second, the handshake logic was incorrect. Rectify these, and modify
the testbench to test for this condition.

Fixes: 7514231 ("Add AXIS-Wishbone bridge")
Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
Sean Anderson 2023-03-04 14:32:04 -05:00
parent d2b4351899
commit 10a4199381
2 changed files with 17 additions and 12 deletions

View File

@ -46,7 +46,7 @@ module axis_wb_bridge (
localparam RESP1 = 9;
localparam RESP0 = 10;
reg s_axis_ready_next, s_axis_valid_last, m_axis_ready_last, m_axis_valid_next;
reg s_axis_ready_next, s_axis_valid_last, m_axis_valid_next;
reg [7:0] s_axis_data_last, m_axis_data_next;
reg wb_ack_last, wb_err_last;
reg wb_stb_next, wb_we_next;
@ -58,7 +58,7 @@ module axis_wb_bridge (
always @(*) begin
s_axis_ready_next = s_axis_ready;
m_axis_valid_next = m_axis_valid;
m_axis_data_next = 8'bX;
m_axis_data_next = m_axis_data;
wb_cyc = wb_stb;
wb_stb_next = wb_stb;
@ -137,15 +137,15 @@ module axis_wb_bridge (
overflow_latch_next = 0;
state_next = wb_we || wb_err ? RESP0 : RESP2;
end
RESP2: if (m_axis_ready_last) begin
RESP2: if (m_axis_ready && m_axis_valid) begin
m_axis_data_next = wb_data_latch[15:8];
state_next = RESP1;
end
RESP1: if (m_axis_ready_last) begin
RESP1: if (m_axis_ready && m_axis_valid) begin
m_axis_data_next = wb_data_latch[7:0];
state_next = RESP0;
end
RESP0: if (m_axis_ready_last) begin
RESP0: if (m_axis_ready && m_axis_valid) begin
m_axis_valid_next = 0;
s_axis_ready_next = 1;
state_next = IDLE;
@ -167,7 +167,6 @@ module axis_wb_bridge (
if (rst) begin
s_axis_ready <= 1;
s_axis_valid_last <= 0;
m_axis_ready_last <= 0;
m_axis_valid <= 0;
wb_ack_last <= 0;
wb_err_last <= 0;
@ -177,7 +176,6 @@ module axis_wb_bridge (
end else begin
s_axis_ready <= s_axis_ready_next;
s_axis_valid_last <= s_axis_valid;
m_axis_ready_last <= m_axis_ready;
m_axis_valid <= m_axis_valid_next;
wb_ack_last <= wb_ack;
wb_err_last <= wb_err;

View File

@ -4,11 +4,12 @@
import cocotb
from cocotb.binary import BinaryValue
from cocotb.clock import Clock
from cocotb.regression import TestFactory
from cocotb.triggers import FallingEdge, Timer
from .axis_replay_buffer import send_packet, recv_packet
from .mdio import wb_read, wb_write, wb_err
from .util import BIT, GENMASK
from .util import BIT, ClockEnable, GENMASK, timeout
CMD_CLEAR = BIT(0)
CMD_WE = BIT(1)
@ -68,8 +69,8 @@ class Encoder:
self.last_addr = (addr & ~GENMASK(7, 0)) | ((addr + postinc) & GENMASK(7, 0))
return (cmd, *addr_bytes, *data_bytes)
@cocotb.test(timeout_time=10, timeout_unit='us')
async def test_bridge(bridge):
@timeout(10, 'us')
async def test_bridge(bridge, in_ratio, out_ratio):
bridge.clk.value = BinaryValue('Z')
bridge.rst.value = 1
bridge.s_axis_valid.value = 0
@ -82,6 +83,7 @@ async def test_bridge(bridge):
bridge.rst.value = 0
await cocotb.start(Clock(bridge.clk, 8, units='ns').start())
await FallingEdge(bridge.clk)
await cocotb.start(ClockEnable(bridge.clk, bridge.m_axis_ready, out_ratio))
s_axis = {
'clk': bridge.clk,
@ -112,7 +114,7 @@ async def test_bridge(bridge):
e = Encoder()
async def read(addr, data, postinc=False, resp=0):
await send_packet(s_axis, e.encode(addr, None, postinc))
await send_packet(s_axis, e.encode(addr, None, postinc), in_ratio)
bridge.overflow.value = bool(resp & STATUS_OVERFLOW)
if resp & STATUS_ERR:
@ -125,7 +127,7 @@ async def test_bridge(bridge):
await recv_packet(m_axis, (resp, *data.to_bytes(2, 'big')))
async def write(addr, data, postinc=False, resp=STATUS_WE):
await send_packet(s_axis, e.encode(addr, data, postinc))
await send_packet(s_axis, e.encode(addr, data, postinc), in_ratio)
bridge.overflow.value = bool(resp & STATUS_OVERFLOW)
if resp & STATUS_ERR:
@ -164,3 +166,8 @@ async def test_bridge(bridge):
await read(7, 8, resp=STATUS_ERR)
await read(9, 10, resp=STATUS_OVERFLOW)
await write(11, 12)
bridge_tests = TestFactory(test_bridge)
bridge_tests.add_option('in_ratio', (1, 4))
bridge_tests.add_option('out_ratio', (1, 4))
bridge_tests.generate_tests()