diff --git a/Bender.yml b/Bender.yml index c6d9ad1e9..305c09c4d 100644 --- a/Bender.yml +++ b/Bender.yml @@ -63,6 +63,7 @@ sources: - test/tb_axi_atop_filter.sv - test/tb_axi_cdc.sv - test/tb_axi_delayer.sv + - test/tb_axi_dw_downsizer.sv - test/tb_axi_isolate.sv - test/tb_axi_lite_to_apb.sv - test/tb_axi_lite_to_axi.sv diff --git a/scripts/run_vsim.sh b/scripts/run_vsim.sh index 3cd1aef4c..e2f0db5e7 100755 --- a/scripts/run_vsim.sh +++ b/scripts/run_vsim.sh @@ -27,6 +27,12 @@ for DW in 8 16 32 64 128 256 512 1024; do call_vsim tb_axi_lite_to_axi -GDW=$DW -t 1ps -c done +for DW in 8 16 32 64 128 256 512 1024; do + for (( MULT = 2; MULT <= `echo 1024/$DW`; MULT *= 2 )); do + call_vsim tb_axi_dw_downsizer -GDW=$DW -GMULT=$MULT -t 1ps -c + done +done + call_vsim tb_axi_delayer for MAX_TXNS in 1 3 12; do call_vsim tb_axi_atop_filter -GN_TXNS=1000 -GAXI_MAX_WRITE_TXNS=$MAX_TXNS diff --git a/src/axi_dw_converter.sv b/src/axi_dw_converter.sv index 5e0c5ea3e..2111132ae 100644 --- a/src/axi_dw_converter.sv +++ b/src/axi_dw_converter.sv @@ -56,7 +56,7 @@ module axi_dw_converter #( .AxiMaxTrans (AxiMaxTrans ), .AxiIdWidth (AxiIdWidth ), .AxiUserWidth (AxiUserWidth ) - ) i_axi_data_upsize ( + ) i_axi_dw_upsizer ( .clk_i (clk_i ), .rst_ni (rst_ni ), .slv_aw_id (slv.aw_id ), @@ -160,7 +160,7 @@ module axi_dw_converter #( .AxiMaxTrans (AxiMaxTrans ), .AxiIdWidth (AxiIdWidth ), .AxiUserWidth (AxiUserWidth ) - ) i_axi_data_downsize ( + ) i_axi_dw_downsizer ( .clk_i (clk_i ), .rst_ni (rst_ni ), .slv_aw_id (slv.aw_id ), diff --git a/src/axi_dw_downsizer.sv b/src/axi_dw_downsizer.sv index c1d0869a9..c22c39855 100644 --- a/src/axi_dw_downsizer.sv +++ b/src/axi_dw_downsizer.sv @@ -14,15 +14,17 @@ // Data width downsize conversion. // Connects a narrow master to a wider slave. +`include "axi/typedef.svh" + import axi_pkg::*; module axi_dw_downsizer #( - parameter int AxiAddrWidth = 64 , - parameter int AxiMstDataWidth = 64 , - parameter int AxiSlvDataWidth = 64 , - parameter int AxiMaxTrans = 1 , - parameter int AxiIdWidth = 4 , - parameter int AxiUserWidth = 1 , + parameter int AxiAddrWidth = 64, + parameter int AxiMstDataWidth = 64, + parameter int AxiSlvDataWidth = 64, + parameter int AxiMaxTrans = 1 , + parameter int AxiIdWidth = 4 , + parameter int AxiUserWidth = 1 , // Dependent parameters, do not change! parameter AxiMstStrbWidth = AxiMstDataWidth/8 , @@ -174,7 +176,7 @@ module axi_dw_downsizer #( .AxiVldRdy(1'b1 ), .ExtPrio (1'b0 ), .LockIn (1'b1 ) - ) i_arbiter_slv_r ( + ) i_slv_r_arb ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), @@ -216,8 +218,7 @@ module axi_dw_downsizer #( qos : slv_ar_qos , region: slv_ar_region, atop : '0 , - user : slv_ar_user , - valid : slv_ar_valid + user : slv_ar_user }; assign slv_aw = '{ id : slv_aw_id , @@ -231,8 +232,7 @@ module axi_dw_downsizer #( qos : slv_aw_qos , region: slv_aw_region, atop : slv_aw_atop , - user : slv_aw_user , - valid : slv_aw_valid + user : slv_aw_user }; rr_arb_tree #( @@ -278,7 +278,7 @@ module axi_dw_downsizer #( .AxiVldRdy(1'b1 ), .ExtPrio (1'b0 ), .LockIn (1'b1 ) - ) i_arbiter_mst_ar ( + ) i_mst_ar_arb ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), @@ -462,7 +462,7 @@ module axi_dw_downsizer #( r_req_d.ar.len = 255 - align_adj ; end end - end : BURST_INCR + end endcase end end @@ -481,16 +481,16 @@ module axi_dw_downsizer #( mst_r_ready_tran[t] = 1'b1; if (mst_r_valid) begin - automatic addr_t mi_offset = r_req_q.ar.addr[$clog2(AxiMstStrbWidth)-1:0] ; - automatic addr_t si_offset = r_req_q.ar.addr[$clog2(AxiSlvStrbWidth)-1:0] ; - automatic addr_t size_mask = (1 << r_req_q.ar.size) - 1 ; + automatic addr_t mst_offset = r_req_q.ar.addr[(AxiMstStrbWidth == 1 ? 1 : $clog2(AxiMstStrbWidth)) - 1:0]; + automatic addr_t slv_offset = r_req_q.ar.addr[(AxiSlvStrbWidth == 1 ? 1 : $clog2(AxiSlvStrbWidth)) - 1:0]; + automatic addr_t size_mask = (1 << r_req_q.ar.size) - 1 ; // Lane steering for (int b = 0; b < AxiSlvStrbWidth; b++) begin - if ((b >= si_offset) && - (b - si_offset < (1 << r_req_q.size)) && - (b + mi_offset - si_offset < AxiMstStrbWidth)) begin - r_req_d.r.data[8*b+:8] = mst_r_data[8 * (b + mi_offset - si_offset) +: 8]; + if ((b >= slv_offset) && + (b - slv_offset < (1 << r_req_q.size)) && + (b + mst_offset - slv_offset < AxiMstStrbWidth)) begin + r_req_d.r.data[8*b+:8] = mst_r_data[8 * (b + mst_offset - slv_offset) +: 8]; end end @@ -610,8 +610,8 @@ module axi_dw_downsizer #( // Request was accepted if (!w_req_q.aw_valid) if (slv_w_valid) begin - automatic addr_t mi_offset = w_req_q.aw.addr[$clog2(AxiMstStrbWidth)-1:0] ; - automatic addr_t si_offset = w_req_q.aw.addr[$clog2(AxiSlvStrbWidth)-1:0] ; + automatic addr_t mst_offset = w_req_q.aw.addr[(AxiMstStrbWidth == 1 ? 1 : $clog2(AxiMstStrbWidth)) - 1:0]; + automatic addr_t slv_offset = w_req_q.aw.addr[(AxiSlvStrbWidth == 1 ? 1 : $clog2(AxiSlvStrbWidth)) - 1:0]; // Valid output mst_w_valid = 1'b1 ; @@ -620,11 +620,11 @@ module axi_dw_downsizer #( // Serialization for (int b = 0; b < AxiSlvStrbWidth; b++) - if ((b >= si_offset) && - (b - si_offset < (1 << w_req_q.aw.size)) && - (b + mi_offset - si_offset < AxiMstStrbWidth)) begin - mst_w_data[8 * (b + mi_offset - si_offset) +: 8] = slv_w_data[8 * b +: 8]; - mst_w_strb[b + mi_offset - si_offset] = slv_w_strb[b] ; + if ((b >= slv_offset) && + (b - slv_offset < (1 << w_req_q.aw.size)) && + (b + mst_offset - slv_offset < AxiMstStrbWidth)) begin + mst_w_data[8 * (b + mst_offset - slv_offset) +: 8] = slv_w_data[8 * b +: 8]; + mst_w_strb[b + mst_offset - slv_offset] = slv_w_strb[b] ; end end diff --git a/src/axi_dw_upsizer.sv b/src/axi_dw_upsizer.sv index 27d742120..f32ee39dd 100644 --- a/src/axi_dw_upsizer.sv +++ b/src/axi_dw_upsizer.sv @@ -14,6 +14,8 @@ // Data width upsize conversion. // Connects a wide master to a narrower slave. +`include "axi/typedef.svh" + import axi_pkg::*; module axi_dw_upsizer #( @@ -168,7 +170,7 @@ module axi_dw_upsizer #( .DataType (slv_r_chan_t), .ExtPrio (1'b0 ), .AxiVldRdy(1'b1 ) - ) i_arbiter_slv_r ( + ) i_slv_r_arb ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), @@ -210,8 +212,7 @@ module axi_dw_upsizer #( qos : slv_ar_qos , region: slv_ar_region, atop : '0 , - user : slv_ar_user , - valid : slv_ar_valid + user : slv_ar_user }; assign slv_aw = '{ id : slv_aw_id , @@ -225,8 +226,7 @@ module axi_dw_upsizer #( qos : slv_aw_qos , region: slv_aw_region, atop : slv_aw_atop , - user : slv_aw_user , - valid : slv_aw_valid + user : slv_aw_user }; rr_arb_tree #( @@ -272,7 +272,7 @@ module axi_dw_upsizer #( .AxiVldRdy(1'b1 ), .ExtPrio (1'b0 ), .LockIn (1'b1 ) - ) i_arbiter_mst_ar ( + ) i_mst_ar_arb ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), @@ -449,8 +449,8 @@ module axi_dw_upsizer #( // Request was accepted if (!r_req_q.ar_valid) if (mst_r_valid && (idqueue_id == t) && idqueue_valid) begin - automatic addr_t mi_offset = r_req_q.ar.addr[$clog2(AxiMstStrbWidth)-1:0]; - automatic addr_t si_offset = r_req_q.ar.addr[$clog2(AxiSlvStrbWidth)-1:0]; + automatic addr_t mst_offset = r_req_q.ar.addr[(AxiMstStrbWidth == 1 ? 1 : $clog2(AxiMstStrbWidth)) - 1:0]; + automatic addr_t slv_offset = r_req_q.ar.addr[(AxiSlvStrbWidth == 1 ? 1 : $clog2(AxiSlvStrbWidth)) - 1:0]; // Valid output slv_r_valid_tran[t] = 1'b1 ; @@ -458,10 +458,10 @@ module axi_dw_upsizer #( // Serialization for (int b = 0; b < AxiMstStrbWidth; b++) - if ((b >= mi_offset) && - (b - mi_offset < (1 << r_req_q.size)) && - (b + si_offset - mi_offset < AxiSlvStrbWidth)) begin - slv_r_tran[t].data[8*(b + si_offset - mi_offset) +: 8] = mst_r_data[8 * b +: 8]; + if ((b >= mst_offset) && + (b - mst_offset < (1 << r_req_q.size)) && + (b + slv_offset - mst_offset < AxiSlvStrbWidth)) begin + slv_r_tran[t].data[8*(b + slv_offset - mst_offset) +: 8] = mst_r_data[8 * b +: 8]; end // Acknowledgment @@ -576,17 +576,17 @@ module axi_dw_upsizer #( slv_w_ready = ~mst_w_valid || mst_w_ready; if (slv_w_valid && slv_w_ready) begin - automatic addr_t mi_offset = w_req_q.aw.addr[$clog2(AxiMstStrbWidth)-1:0]; - automatic addr_t si_offset = w_req_q.aw.addr[$clog2(AxiSlvStrbWidth)-1:0]; - automatic addr_t size_mask = (1 << w_req_q.size) - 1 ; + automatic addr_t mst_offset = w_req_q.aw.addr[(AxiMstStrbWidth == 1 ? 1 : $clog2(AxiMstStrbWidth)) - 1:0]; + automatic addr_t slv_offset = w_req_q.aw.addr[(AxiSlvStrbWidth == 1 ? 1 : $clog2(AxiSlvStrbWidth)) - 1:0]; + automatic addr_t size_mask = (1 << w_req_q.size) - 1 ; // Lane steering for (int b = 0; b < AxiMstStrbWidth; b++) - if ((b >= mi_offset) && - (b - mi_offset < (1 << w_req_q.size)) && - (b + si_offset - mi_offset < AxiSlvStrbWidth)) begin - w_req_d.w.data[8 * b +: 8] = slv_w_data[8 * (b + si_offset - mi_offset) +: 8]; - w_req_d.w.strb[b] = slv_w_strb[b + si_offset - mi_offset] ; + if ((b >= mst_offset) && + (b - mst_offset < (1 << w_req_q.size)) && + (b + slv_offset - mst_offset < AxiSlvStrbWidth)) begin + w_req_d.w.data[8 * b +: 8] = slv_w_data[8 * (b + slv_offset - mst_offset) +: 8]; + w_req_d.w.strb[b] = slv_w_strb[b + slv_offset - mst_offset] ; end w_req_d.len = w_req_q.len - 1 ; diff --git a/test/tb_axi_dw_downsizer.do b/test/tb_axi_dw_downsizer.do new file mode 100644 index 000000000..8a1080e74 --- /dev/null +++ b/test/tb_axi_dw_downsizer.do @@ -0,0 +1,4 @@ +add wave -position insertpoint \ + sim:/tb_axi_dw_downsizer/i_dw_converter/gen_dw_downsize/i_axi_dw_downsizer/AxiMstDataWidth \ + sim:/tb_axi_dw_downsizer/i_dw_converter/gen_dw_downsize/i_axi_dw_downsizer/AxiSlvDataWidth \ + sim:/tb_axi_dw_downsizer/i_dw_converter/gen_dw_downsize/i_axi_dw_downsizer/* \ No newline at end of file diff --git a/test/tb_axi_dw_downsizer.sv b/test/tb_axi_dw_downsizer.sv new file mode 100644 index 000000000..a96fef719 --- /dev/null +++ b/test/tb_axi_dw_downsizer.sv @@ -0,0 +1,125 @@ +// Copyright 2020 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// File : tb_axi_dw_downsizer.sv +// Author : Matheus Cavalcante +// Created : 09.02.2019 + +// Copyright (C) 2020 ETH Zurich, University of Bologna +// All rights reserved. + +`include "axi/assign.svh" + +module tb_axi_dw_downsizer; + + parameter AW = 64; + parameter IW = 4; + parameter DW = 32; + parameter UW = 8; + parameter MULT = 8; + + localparam tCK = 1ns; + + logic clk = 0; + logic rst = 1; + logic done = 0; + + AXI_BUS_DV #( + .AXI_ADDR_WIDTH (AW ), + .AXI_DATA_WIDTH (MULT * DW), + .AXI_ID_WIDTH (IW ), + .AXI_USER_WIDTH (UW ) + ) axi_master_dv (clk); + + AXI_BUS #( + .AXI_ADDR_WIDTH (AW ), + .AXI_DATA_WIDTH (MULT * DW), + .AXI_ID_WIDTH (IW ), + .AXI_USER_WIDTH (UW ) + ) axi_master(); + + axi_test::rand_axi_master #( + .AW (AW ), + .DW (MULT * DW), + .IW (IW ), + .UW (UW ), + .MAX_READ_TXNS (8 ), + .MAX_WRITE_TXNS (8 ), + .TA (200ps ), + .TT (700ps ) + ) axi_master_drv = new ( axi_master_dv ); + + AXI_BUS_DV #( + .AXI_ADDR_WIDTH (AW), + .AXI_DATA_WIDTH (DW), + .AXI_ID_WIDTH (IW), + .AXI_USER_WIDTH (UW) + ) axi_slave_dv (clk); + + AXI_BUS #( + .AXI_ADDR_WIDTH (AW), + .AXI_DATA_WIDTH (DW), + .AXI_ID_WIDTH (IW), + .AXI_USER_WIDTH (UW) + ) axi_slave (); + + axi_test::rand_axi_slave #( + .AW (AW ), + .DW (DW ), + .IW (IW ), + .UW (UW ), + .TA (200ps), + .TT (700ps) + ) axi_slave_drv = new (axi_slave_dv); + + `AXI_ASSIGN(axi_master, axi_master_dv); + `AXI_ASSIGN(axi_slave_dv, axi_slave) ; + + axi_dw_converter #( + .AxiSlvDataWidth(MULT*DW), + .AxiMstDataWidth(DW ), + .AxiIdWidth (IW ), + .AxiUserWidth (UW ), + .AxiMaxTrans (4 ) + ) i_dw_converter ( + .clk_i (clk ), + .rst_ni(rst ), + .slv (axi_master), + .mst (axi_slave ) + ); + + initial begin + #tCK; + rst <= 0; + #tCK; + rst <= 1; + #tCK; + while (!done) begin + clk <= 1; + #(tCK/2); + clk <= 0; + #(tCK/2); + end + end + + initial begin + axi_master_drv.reset() ; + axi_master_drv.add_memory_region({AW{1'b0}}, {AW{1'b1}}, axi_pkg::WTHRU_NOALLOCATE); + axi_master_drv.run(50, 50) ; + done = 1; + end + + initial begin + axi_slave_drv.reset(); + axi_slave_drv.run() ; + end + +// vsim -voptargs=+acc work.tb_axi_dw_downsizer +endmodule : tb_axi_dw_downsizer