From 10a4199381dab0de165cfc0cc015c861c5404776 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Sat, 4 Mar 2023 14:32:04 -0500 Subject: [PATCH] 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 --- rtl/axis_wb_bridge.v | 12 +++++------- tb/axis_wb_bridge.py | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/rtl/axis_wb_bridge.v b/rtl/axis_wb_bridge.v index dd8fcd0..d46c978 100644 --- a/rtl/axis_wb_bridge.v +++ b/rtl/axis_wb_bridge.v @@ -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; diff --git a/tb/axis_wb_bridge.py b/tb/axis_wb_bridge.py index 3835f35..48e7e8c 100644 --- a/tb/axis_wb_bridge.py +++ b/tb/axis_wb_bridge.py @@ -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()