diff --git a/README.md b/README.md index 489eee09b..b6729e4fc 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,15 @@ In addition to the documents linked in the following table, we are setting up [d | [`axi_xbar`](src/axi_xbar.sv) | Fully-connected AXI4+ATOP crossbar with an arbitrary number of slave and master ports. | [Doc](doc/axi_xbar.md) | | [`axi_xp`](src/axi_xp.sv) | AXI Crosspoint (XP) with homomorphous slave and master ports. | | +## Synthesizable Verification Modules + +The following modules are meant to be used for verification purposes only but are synthesizable to be used in FPGA environments. + +| Name | Description | +|------------------------------------------------------|---------------------------------------------------------------------------------------------------------| +| [`axi_bus_compare`](src/axi_bus_compare.sv) | Compares two buses of the same type (and in the same clock domain), returns events on mismatch. | +| [`axi_slave_compare`](src/axi_slave_compare.sv) | Compares two slave devices of the same type (and in the same clock domain), returns events on mismatch. | + ### Simulation-Only Modules In addition to the modules above, which are available in synthesis and simulation, the following modules are available only in simulation. Those modules are widely used in our testbenches, but they are also suitable to build testbenches for AXI modules and systems outside this repository. diff --git a/src/axi_bus_compare.sv b/src/axi_bus_compare.sv index 84d396613..b92e6159f 100644 --- a/src/axi_bus_compare.sv +++ b/src/axi_bus_compare.sv @@ -12,6 +12,7 @@ // Authors: // - Thomas Benz +`include "axi/assign.svh" /// Synthesizable test module comparing two AXI channels of the same type /// This module is meant to be used in FPGA-based verification. module axi_bus_compare #( @@ -79,22 +80,23 @@ module axi_bus_compare #( // Channel Signals //----------------------------------- // assign request payload A - assign axi_a_req_o.aw = axi_a_req_i.aw; - assign axi_a_req_o.w = axi_a_req_i.w; - assign axi_a_req_o.ar = axi_a_req_i.ar; + + `AXI_ASSIGN_AW_STRUCT(axi_a_req_o.aw, axi_a_req_i.aw) + `AXI_ASSIGN_W_STRUCT(axi_a_req_o.w, axi_a_req_i.w) + `AXI_ASSIGN_AR_STRUCT(axi_a_req_o.ar, axi_a_req_i.ar) // assign response payload A - assign axi_a_rsp_o.r = axi_a_rsp_i.r; - assign axi_a_rsp_o.b = axi_a_rsp_i.b; + `AXI_ASSIGN_R_STRUCT(axi_a_rsp_o.r, axi_a_rsp_i.r) + `AXI_ASSIGN_B_STRUCT(axi_a_rsp_o.b, axi_a_rsp_i.b) // assign request payload B - assign axi_b_req_o.aw = axi_b_req_i.aw; - assign axi_b_req_o.w = axi_b_req_i.w; - assign axi_b_req_o.ar = axi_b_req_i.ar; + `AXI_ASSIGN_AW_STRUCT(axi_b_req_o.aw, axi_b_req_i.aw) + `AXI_ASSIGN_W_STRUCT(axi_b_req_o.w, axi_b_req_i.w) + `AXI_ASSIGN_AR_STRUCT(axi_b_req_o.ar, axi_b_req_i.ar) // assign response payload B - assign axi_b_rsp_o.r = axi_b_rsp_i.r; - assign axi_b_rsp_o.b = axi_b_rsp_i.b; + `AXI_ASSIGN_R_STRUCT(axi_b_rsp_o.r, axi_b_rsp_i.r) + `AXI_ASSIGN_B_STRUCT(axi_b_rsp_o.b, axi_b_rsp_i.b) // fifo handshaking signals A id_t fifo_valid_aw_a, fifo_ready_aw_a; @@ -314,40 +316,38 @@ module axi_bus_compare #( // Input Handshaking A //----------------------------------- always_comb begin : gen_handshaking_a - for (int id = 0; id < 2**AxiIdWidth; id++) begin - // aw - // defaults - fifo_valid_aw_a = '0; - fifo_sel_ready_aw_a = '0; - // assign according id - fifo_valid_aw_a [axi_a_req_i.aw.id] = fifo_sel_valid_aw_a; - fifo_sel_ready_aw_a = fifo_ready_aw_a[axi_a_req_i.aw.id]; - - - // b - // defaults - fifo_valid_b_a = '0; - fifo_sel_ready_b_a = '0; - // assign according id - fifo_valid_b_a [axi_a_rsp_i.b.id] = fifo_sel_valid_b_a; - fifo_sel_ready_b_a = fifo_ready_b_a[axi_a_rsp_i.b.id]; - - // ar - // defaults - fifo_valid_ar_a = '0; - fifo_sel_ready_ar_a = '0; - // assign according id - fifo_valid_ar_a [axi_a_req_i.ar.id] = fifo_sel_valid_ar_a; - fifo_sel_ready_ar_a = fifo_ready_ar_a[axi_a_req_i.ar.id]; - - // b - // defaults - fifo_valid_r_a = '0; - fifo_sel_ready_r_a = '0; - // assign according id - fifo_valid_r_a [axi_a_rsp_i.r.id] = fifo_sel_valid_r_a; - fifo_sel_ready_r_a = fifo_ready_r_a[axi_a_rsp_i.r.id]; - end + // aw + // defaults + fifo_valid_aw_a = '0; + fifo_sel_ready_aw_a = '0; + // assign according id + fifo_valid_aw_a [axi_a_req_i.aw.id] = fifo_sel_valid_aw_a; + fifo_sel_ready_aw_a = fifo_ready_aw_a[axi_a_req_i.aw.id]; + + + // b + // defaults + fifo_valid_b_a = '0; + fifo_sel_ready_b_a = '0; + // assign according id + fifo_valid_b_a [axi_a_rsp_i.b.id] = fifo_sel_valid_b_a; + fifo_sel_ready_b_a = fifo_ready_b_a[axi_a_rsp_i.b.id]; + + // ar + // defaults + fifo_valid_ar_a = '0; + fifo_sel_ready_ar_a = '0; + // assign according id + fifo_valid_ar_a [axi_a_req_i.ar.id] = fifo_sel_valid_ar_a; + fifo_sel_ready_ar_a = fifo_ready_ar_a[axi_a_req_i.ar.id]; + + // b + // defaults + fifo_valid_r_a = '0; + fifo_sel_ready_r_a = '0; + // assign according id + fifo_valid_r_a [axi_a_rsp_i.r.id] = fifo_sel_valid_r_a; + fifo_sel_ready_r_a = fifo_ready_r_a[axi_a_rsp_i.r.id]; end @@ -516,40 +516,38 @@ module axi_bus_compare #( // Input Handshaking B //----------------------------------- always_comb begin : gen_handshaking_b - for (int id = 0; id < 2**AxiIdWidth; id++) begin - // aw - // defaults - fifo_valid_aw_b = '0; - fifo_sel_ready_aw_b = '0; - // assign according id - fifo_valid_aw_b [axi_b_req_i.aw.id] = fifo_sel_valid_aw_b; - fifo_sel_ready_aw_b = fifo_ready_aw_b[axi_b_req_i.aw.id]; - - - // b - // defaults - fifo_valid_b_b = '0; - fifo_sel_ready_b_b = '0; - // assign according id - fifo_valid_b_b [axi_b_rsp_i.b.id] = fifo_sel_valid_b_b; - fifo_sel_ready_b_b = fifo_ready_b_b[axi_b_rsp_i.b.id]; - - // ar - // defaults - fifo_valid_ar_b = '0; - fifo_sel_ready_ar_b = '0; - // assign according id - fifo_valid_ar_b [axi_b_req_i.ar.id] = fifo_sel_valid_ar_b; - fifo_sel_ready_ar_b = fifo_ready_ar_b[axi_b_req_i.ar.id]; - - // b - // defaults - fifo_valid_r_b = '0; - fifo_sel_ready_r_b = '0; - // assign according id - fifo_valid_r_b [axi_b_rsp_i.r.id] = fifo_sel_valid_r_b; - fifo_sel_ready_r_b = fifo_ready_r_b[axi_b_rsp_i.r.id]; - end + // aw + // defaults + fifo_valid_aw_b = '0; + fifo_sel_ready_aw_b = '0; + // assign according id + fifo_valid_aw_b [axi_b_req_i.aw.id] = fifo_sel_valid_aw_b; + fifo_sel_ready_aw_b = fifo_ready_aw_b[axi_b_req_i.aw.id]; + + + // b + // defaults + fifo_valid_b_b = '0; + fifo_sel_ready_b_b = '0; + // assign according id + fifo_valid_b_b [axi_b_rsp_i.b.id] = fifo_sel_valid_b_b; + fifo_sel_ready_b_b = fifo_ready_b_b[axi_b_rsp_i.b.id]; + + // ar + // defaults + fifo_valid_ar_b = '0; + fifo_sel_ready_ar_b = '0; + // assign according id + fifo_valid_ar_b [axi_b_req_i.ar.id] = fifo_sel_valid_ar_b; + fifo_sel_ready_ar_b = fifo_ready_ar_b[axi_b_req_i.ar.id]; + + // b + // defaults + fifo_valid_r_b = '0; + fifo_sel_ready_r_b = '0; + // assign according id + fifo_valid_r_b [axi_b_rsp_i.r.id] = fifo_sel_valid_r_b; + fifo_sel_ready_r_b = fifo_ready_r_b[axi_b_rsp_i.r.id]; end @@ -584,4 +582,4 @@ module axi_bus_compare #( assign mismatch_o = (|aw_mismatch_o) | (|w_mismatch_o) | (|b_mismatch_o) | (|ar_mismatch_o) | (|r_mismatch_o); -endmodule : axi_bus_compare +endmodule diff --git a/src/axi_slave_compare.sv b/src/axi_slave_compare.sv index 28a380fc4..a4442985c 100644 --- a/src/axi_slave_compare.sv +++ b/src/axi_slave_compare.sv @@ -12,6 +12,7 @@ // Authors: // - Thomas Benz +`include "axi/assign.svh" /// Synthesizable test module comparing two AXI slaves of the same type. /// The reference response is always passed to the master, whereas the test response /// is discarded after handshaking. @@ -123,8 +124,8 @@ module axi_slave_compare #( // assemble buses always_comb begin // request - axi_ref_req_in = axi_mst_req_i; - axi_test_req_in = axi_mst_req_i; + `AXI_SET_REQ_STRUCT(axi_ref_req_in, axi_mst_req_i) + `AXI_SET_REQ_STRUCT(axi_test_req_in, axi_mst_req_i) // overwrite valids in requests axi_ref_req_in.aw_valid = aw_valid_ref; axi_ref_req_in.ar_valid = ar_valid_ref; @@ -140,7 +141,7 @@ module axi_slave_compare #( ar_ready_test = axi_test_rsp_in.ar_ready; w_ready_test = axi_test_rsp_in.w_ready; // response - axi_mst_rsp_o = axi_ref_rsp_in; + `AXI_SET_RESP_STRUCT(axi_mst_rsp_o, axi_ref_rsp_in) // overwrite readies axi_mst_rsp_o.aw_ready = aw_ready_mst; axi_mst_rsp_o.w_ready = w_ready_mst; @@ -181,4 +182,4 @@ module axi_slave_compare #( .axi_b_rsp_i ( axi_test_rsp_i ) ); -endmodule : axi_slave_compare +endmodule diff --git a/test/tb_axi_bus_compare.sv b/test/tb_axi_bus_compare.sv index 050cbdd46..c8cd1c91c 100644 --- a/test/tb_axi_bus_compare.sv +++ b/test/tb_axi_bus_compare.sv @@ -109,8 +109,8 @@ module tb_axi_bus_compare #( // assemble buses always_comb begin // request - axi_req_a_in = axi_req; - axi_req_b_in = axi_req; + `AXI_SET_REQ_STRUCT(axi_req_a_in, axi_req) + `AXI_SET_REQ_STRUCT(axi_req_b_in, axi_req) // overwrite valids in requests axi_req_a_in.aw_valid = aw_valid_a; axi_req_a_in.ar_valid = ar_valid_a; @@ -126,7 +126,7 @@ module tb_axi_bus_compare #( ar_ready_b = axi_rsp_b_in.ar_ready; w_ready_b = axi_rsp_b_in.w_ready; // response - axi_rsp = axi_rsp_a_in; + `AXI_SET_RESP_STRUCT(axi_rsp, axi_rsp_a_in) // overwrite readies axi_rsp.aw_ready = aw_ready; axi_rsp.w_ready = w_ready; @@ -307,4 +307,4 @@ module tb_axi_bus_compare #( $finish(); end -endmodule : tb_axi_bus_compare +endmodule diff --git a/test/tb_axi_slave_compare.sv b/test/tb_axi_slave_compare.sv index 5413bf86d..45809e5d2 100644 --- a/test/tb_axi_slave_compare.sv +++ b/test/tb_axi_slave_compare.sv @@ -236,4 +236,4 @@ module tb_axi_slave_compare #( $finish(); end -endmodule : tb_axi_slave_compare +endmodule