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:
parent
d2b4351899
commit
10a4199381
|
@ -46,7 +46,7 @@ module axis_wb_bridge (
|
||||||
localparam RESP1 = 9;
|
localparam RESP1 = 9;
|
||||||
localparam RESP0 = 10;
|
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 [7:0] s_axis_data_last, m_axis_data_next;
|
||||||
reg wb_ack_last, wb_err_last;
|
reg wb_ack_last, wb_err_last;
|
||||||
reg wb_stb_next, wb_we_next;
|
reg wb_stb_next, wb_we_next;
|
||||||
|
@ -58,7 +58,7 @@ module axis_wb_bridge (
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
s_axis_ready_next = s_axis_ready;
|
s_axis_ready_next = s_axis_ready;
|
||||||
m_axis_valid_next = m_axis_valid;
|
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_cyc = wb_stb;
|
||||||
wb_stb_next = wb_stb;
|
wb_stb_next = wb_stb;
|
||||||
|
@ -137,15 +137,15 @@ module axis_wb_bridge (
|
||||||
overflow_latch_next = 0;
|
overflow_latch_next = 0;
|
||||||
state_next = wb_we || wb_err ? RESP0 : RESP2;
|
state_next = wb_we || wb_err ? RESP0 : RESP2;
|
||||||
end
|
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];
|
m_axis_data_next = wb_data_latch[15:8];
|
||||||
state_next = RESP1;
|
state_next = RESP1;
|
||||||
end
|
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];
|
m_axis_data_next = wb_data_latch[7:0];
|
||||||
state_next = RESP0;
|
state_next = RESP0;
|
||||||
end
|
end
|
||||||
RESP0: if (m_axis_ready_last) begin
|
RESP0: if (m_axis_ready && m_axis_valid) begin
|
||||||
m_axis_valid_next = 0;
|
m_axis_valid_next = 0;
|
||||||
s_axis_ready_next = 1;
|
s_axis_ready_next = 1;
|
||||||
state_next = IDLE;
|
state_next = IDLE;
|
||||||
|
@ -167,7 +167,6 @@ module axis_wb_bridge (
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
s_axis_ready <= 1;
|
s_axis_ready <= 1;
|
||||||
s_axis_valid_last <= 0;
|
s_axis_valid_last <= 0;
|
||||||
m_axis_ready_last <= 0;
|
|
||||||
m_axis_valid <= 0;
|
m_axis_valid <= 0;
|
||||||
wb_ack_last <= 0;
|
wb_ack_last <= 0;
|
||||||
wb_err_last <= 0;
|
wb_err_last <= 0;
|
||||||
|
@ -177,7 +176,6 @@ module axis_wb_bridge (
|
||||||
end else begin
|
end else begin
|
||||||
s_axis_ready <= s_axis_ready_next;
|
s_axis_ready <= s_axis_ready_next;
|
||||||
s_axis_valid_last <= s_axis_valid;
|
s_axis_valid_last <= s_axis_valid;
|
||||||
m_axis_ready_last <= m_axis_ready;
|
|
||||||
m_axis_valid <= m_axis_valid_next;
|
m_axis_valid <= m_axis_valid_next;
|
||||||
wb_ack_last <= wb_ack;
|
wb_ack_last <= wb_ack;
|
||||||
wb_err_last <= wb_err;
|
wb_err_last <= wb_err;
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
import cocotb
|
import cocotb
|
||||||
from cocotb.binary import BinaryValue
|
from cocotb.binary import BinaryValue
|
||||||
from cocotb.clock import Clock
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.regression import TestFactory
|
||||||
from cocotb.triggers import FallingEdge, Timer
|
from cocotb.triggers import FallingEdge, Timer
|
||||||
|
|
||||||
from .axis_replay_buffer import send_packet, recv_packet
|
from .axis_replay_buffer import send_packet, recv_packet
|
||||||
from .mdio import wb_read, wb_write, wb_err
|
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_CLEAR = BIT(0)
|
||||||
CMD_WE = BIT(1)
|
CMD_WE = BIT(1)
|
||||||
|
@ -68,8 +69,8 @@ class Encoder:
|
||||||
self.last_addr = (addr & ~GENMASK(7, 0)) | ((addr + postinc) & GENMASK(7, 0))
|
self.last_addr = (addr & ~GENMASK(7, 0)) | ((addr + postinc) & GENMASK(7, 0))
|
||||||
return (cmd, *addr_bytes, *data_bytes)
|
return (cmd, *addr_bytes, *data_bytes)
|
||||||
|
|
||||||
@cocotb.test(timeout_time=10, timeout_unit='us')
|
@timeout(10, 'us')
|
||||||
async def test_bridge(bridge):
|
async def test_bridge(bridge, in_ratio, out_ratio):
|
||||||
bridge.clk.value = BinaryValue('Z')
|
bridge.clk.value = BinaryValue('Z')
|
||||||
bridge.rst.value = 1
|
bridge.rst.value = 1
|
||||||
bridge.s_axis_valid.value = 0
|
bridge.s_axis_valid.value = 0
|
||||||
|
@ -82,6 +83,7 @@ async def test_bridge(bridge):
|
||||||
bridge.rst.value = 0
|
bridge.rst.value = 0
|
||||||
await cocotb.start(Clock(bridge.clk, 8, units='ns').start())
|
await cocotb.start(Clock(bridge.clk, 8, units='ns').start())
|
||||||
await FallingEdge(bridge.clk)
|
await FallingEdge(bridge.clk)
|
||||||
|
await cocotb.start(ClockEnable(bridge.clk, bridge.m_axis_ready, out_ratio))
|
||||||
|
|
||||||
s_axis = {
|
s_axis = {
|
||||||
'clk': bridge.clk,
|
'clk': bridge.clk,
|
||||||
|
@ -112,7 +114,7 @@ async def test_bridge(bridge):
|
||||||
e = Encoder()
|
e = Encoder()
|
||||||
|
|
||||||
async def read(addr, data, postinc=False, resp=0):
|
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)
|
bridge.overflow.value = bool(resp & STATUS_OVERFLOW)
|
||||||
if resp & STATUS_ERR:
|
if resp & STATUS_ERR:
|
||||||
|
@ -125,7 +127,7 @@ async def test_bridge(bridge):
|
||||||
await recv_packet(m_axis, (resp, *data.to_bytes(2, 'big')))
|
await recv_packet(m_axis, (resp, *data.to_bytes(2, 'big')))
|
||||||
|
|
||||||
async def write(addr, data, postinc=False, resp=STATUS_WE):
|
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)
|
bridge.overflow.value = bool(resp & STATUS_OVERFLOW)
|
||||||
if resp & STATUS_ERR:
|
if resp & STATUS_ERR:
|
||||||
|
@ -164,3 +166,8 @@ async def test_bridge(bridge):
|
||||||
await read(7, 8, resp=STATUS_ERR)
|
await read(7, 8, resp=STATUS_ERR)
|
||||||
await read(9, 10, resp=STATUS_OVERFLOW)
|
await read(9, 10, resp=STATUS_OVERFLOW)
|
||||||
await write(11, 12)
|
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()
|
||||||
|
|
Loading…
Reference in New Issue