Skip to content

Commit

Permalink
axi_chan_compare: Adds parameter to allow reordered transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
fischeti committed May 24, 2023
1 parent f24b1fa commit 53eaea6
Showing 1 changed file with 48 additions and 17 deletions.
65 changes: 48 additions & 17 deletions src/axi_chan_compare.sv
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
module axi_chan_compare #(
/// Ignore ID field if it was remapped
parameter bit IgnoreId = 1'b0,
/// Allow reordered responses of different IDs,
/// not compatible with `IgnoreId`
parameter bit AllowReordering = 1'b0,
/// AXI ID Width
parameter int unsigned IdWidth = 1,
parameter type aw_chan_t = logic,
parameter type w_chan_t = logic,
parameter type b_chan_t = logic,
Expand Down Expand Up @@ -123,43 +128,54 @@ module axi_chan_compare #(
// verilog_lint: waive-stop line-length
endfunction

localparam NumIds = (AllowReordering)? 2**IdWidth : 1;

// queues
aw_chan_t aw_queue [$];
w_chan_t w_queue [$];
b_chan_t b_queue [$];
ar_chan_t ar_queue [$];
r_chan_t r_queue [$];
aw_chan_t aw_queue [NumIds-1:0][$];
w_chan_t w_queue [$];
b_chan_t b_queue [NumIds-1:0][$];
ar_chan_t ar_queue [NumIds-1:0][$];
r_chan_t r_queue [NumIds-1:0][$];

// requests generated at axi A: enqueue elements
always_ff @(posedge clk_a_i) begin : proc_enqueue_a
// aw
if (axi_a_req.aw_valid & axi_a_res.aw_ready)
aw_queue.push_back(axi_a_req.aw);
if (AllowReordering) aw_queue[axi_a_req.aw.id].push_back(axi_a_req.aw);
else aw_queue[0].push_back(axi_a_req.aw);
// w
if (axi_a_req.w_valid & axi_a_res.w_ready)
w_queue.push_back(axi_a_req.w);
// ar
if (axi_a_req.ar_valid & axi_a_res.ar_ready)
ar_queue.push_back(axi_a_req.ar);
if (AllowReordering) ar_queue[axi_a_req.ar.id].push_back(axi_a_req.ar);
else ar_queue[0].push_back(axi_a_req.ar);
end

// responses generated at axi B: enqueue elements
always_ff @(posedge clk_b_i) begin : proc_enqueue_b
// b
if (axi_b_res.b_valid & axi_b_req.b_ready)
b_queue.push_back(axi_b_res.b);
if (AllowReordering) b_queue[axi_b_res.b.id].push_back(axi_b_res.b);
else b_queue[0].push_back(axi_b_res.b);
// r
if (axi_b_res.r_valid & axi_b_req.r_ready)
r_queue.push_back(axi_b_res.r);
if (AllowReordering) r_queue[axi_b_res.r.id].push_back(axi_b_res.r);
else r_queue[0].push_back(axi_b_res.r);
end

// requests arriving at axi B from A: dequeue elements and check
always_ff @(posedge clk_b_i) begin : proc_dequeue_and_check_b
// aw
if (axi_b_req.aw_valid & axi_b_res.aw_ready) begin
automatic aw_chan_t aw_exp, aw_recv;
if (aw_queue.size() == 0) $error("AW queue is empty!");
aw_exp = aw_queue.pop_front(); // verilog_lint: waive always-ff-non-blocking
if (AllowReordering) begin
if (aw_queue[axi_b_req.aw.id].size() == 0) $error("AW queue is empty!");
aw_exp = aw_queue[axi_b_req.aw.id].pop_front(); // verilog_lint: waive always-ff-non-blocking
end else begin
if (aw_queue[0].size() == 0) $error("AW queue is empty!");
aw_exp = aw_queue[0].pop_front(); // verilog_lint: waive always-ff-non-blocking
end
aw_recv = axi_b_req.aw;
if (IgnoreId) begin
aw_exp.id = 'X;
Expand All @@ -184,8 +200,13 @@ module axi_chan_compare #(
// ar
if (axi_b_req.ar_valid & axi_b_res.ar_ready) begin
automatic ar_chan_t ar_exp, ar_recv;
if (ar_queue.size() == 0) $error("AR queue is empty!");
ar_exp = ar_queue.pop_front(); // verilog_lint: waive always-ff-non-blocking
if (AllowReordering) begin
if (ar_queue[axi_b_req.ar.id].size() == 0) $error("AR queue is empty!");
ar_exp = ar_queue[axi_b_req.ar.id].pop_front(); // verilog_lint: waive always-ff-non-blocking
end else begin
if (ar_queue[0].size() == 0) $error("AR queue is empty!");
ar_exp = ar_queue[0].pop_front(); // verilog_lint: waive always-ff-non-blocking
end
ar_recv = axi_b_req.ar;
if (IgnoreId) begin
ar_exp.id = 'X;
Expand All @@ -203,8 +224,13 @@ module axi_chan_compare #(
// b
if (axi_a_res.b_valid & axi_a_req.b_ready) begin
automatic b_chan_t b_exp, b_recv;
if (b_queue.size() == 0) $error("B queue is empty!");
b_exp = b_queue.pop_front(); // verilog_lint: waive always-ff-non-blocking
if (AllowReordering) begin
if (b_queue[axi_a_res.b.id].size() == 0) $error("B queue is empty!");
b_exp = b_queue[axi_a_res.b.id].pop_front(); // verilog_lint: waive always-ff-non-blocking
end else begin
if (b_queue[0].size() == 0) $error("B queue is empty!");
b_exp = b_queue[0].pop_front(); // verilog_lint: waive always-ff-non-blocking
end
b_recv = axi_a_res.b;
if (IgnoreId) begin
b_exp.id = 'X;
Expand All @@ -218,8 +244,13 @@ module axi_chan_compare #(
// r
if (axi_a_res.r_valid & axi_a_req.r_ready) begin
automatic r_chan_t r_exp, r_recv;
if (r_queue.size() == 0) $error("R queue is empty!");
r_exp = r_queue.pop_front(); // verilog_lint: waive always-ff-non-blocking
if (AllowReordering) begin
if (r_queue[axi_a_res.r.id].size() == 0) $error("R queue is empty!");
r_exp = r_queue[axi_a_res.r.id].pop_front(); // verilog_lint: waive always-ff-non-blocking
end else begin
if (r_queue[0].size() == 0) $error("R queue is empty!");
r_exp = r_queue[0].pop_front(); // verilog_lint: waive always-ff-non-blocking
end
r_recv = axi_a_res.r;
if (IgnoreId) begin
r_exp.id = 'X;
Expand Down

0 comments on commit 53eaea6

Please sign in to comment.