diff --git a/library/common/ad_pack.v b/library/common/ad_pack.v index 4d8d91b40..4342427b3 100644 --- a/library/common/ad_pack.v +++ b/library/common/ad_pack.v @@ -1,6 +1,6 @@ // *************************************************************************** // *************************************************************************** -// Copyright 2014 - 2020 (c) Analog Devices, Inc. All rights reserved. +// Copyright 2014 - 2022 (c) Analog Devices, Inc. All rights reserved. // // In this HDL repository, there are many different and unique modules, consisting // of various HDL (Verilog or VHDL) components. The individual modules are @@ -40,7 +40,7 @@ // - data unit defined in bits by UNIT_W e.g 8 is a byte // // Constraints: -// - O_W >= I_W +// - O_W > I_W // - no backpressure // // Data format: @@ -72,12 +72,13 @@ module ad_pack #( output reg ovalid = 'b0 ); - // Width of shift reg is integer multiple of input data width - localparam SH_W = ((O_W/I_W)+|(O_W % I_W))*I_W; - localparam STEP = O_W % I_W; + // The Width of the shift reg is an integer multiple of input data width + localparam SH_W = ((O_W/I_W) + ((O_W%I_W) > 0) + ((I_W % (O_W - ((O_W/I_W)*I_W) + ((O_W%I_W) == 0))) > 0))*I_W; + // The Step of the algorithm is the greatest common divisor of O_W and I_W + localparam STEP = gcd(O_W, I_W); reg [O_W*UNIT_W-1:0] idata_packed; - reg [SH_W*UNIT_W-1:0] idata_d = 'h0; + reg [I_W*UNIT_W-1:0] idata_d = 'h0; reg ivalid_d = 'h0; reg [SH_W*UNIT_W-1:0] idata_dd = 'h0; reg [SH_W-1:0] in_use = 'b0; @@ -87,6 +88,21 @@ module ad_pack #( wire [SH_W-1:0] in_use_nx; wire pack_wr; + function [31:0] gcd; + input [31:0] a; + input [31:0] b; + begin + while (a != b) begin + if (a > b) begin + a = a-b; + end else begin + b = b-a; + end + end + gcd = a; + end + endfunction + generate if (I_REG) begin : i_reg @@ -125,18 +141,11 @@ module ad_pack #( integer i; always @(*) begin out_mask = 'b0; - idata_packed = 'bx; - if (STEP>0) begin - for (i = SH_W-O_W; i >= 0; i=i-STEP) begin - if (in_use_nx[i]) begin - out_mask = {O_W{1'b1}} << i; - idata_packed = idata_dd_nx >> i*UNIT_W; - end - end - end else begin - if (in_use_nx[0]) begin - out_mask = {O_W{1'b1}}; - idata_packed = idata_dd_nx; + idata_packed = 'b0; + for (i = SH_W-O_W; i >= 0; i=i-STEP) begin + if (in_use_nx[i]) begin + out_mask = {O_W{1'b1}} << i; + idata_packed = idata_dd_nx >> i*UNIT_W; end end end diff --git a/library/common/ad_upack.v b/library/common/ad_upack.v index 9d52be3a5..b8218863f 100644 --- a/library/common/ad_upack.v +++ b/library/common/ad_upack.v @@ -1,6 +1,6 @@ // *************************************************************************** // *************************************************************************** -// Copyright 2014 - 2020 (c) Analog Devices, Inc. All rights reserved. +// Copyright 2014 - 2022 (c) Analog Devices, Inc. All rights reserved. // // In this HDL repository, there are many different and unique modules, consisting // of various HDL (Verilog or VHDL) components. The individual modules are @@ -40,7 +40,7 @@ // - data unit defined in bits by UNIT_W e.g 8 is a byte // // Constraints: -// - O_W <= I_W +// - O_W < I_W // - LATENCY 1 // - no backpressure // @@ -73,9 +73,10 @@ module ad_upack #( output reg ovalid = 'b0 ); - // Width of shift reg is integer multiple of output data width - localparam SH_W = ((I_W/O_W)+1)*O_W; - localparam STEP = I_W % O_W; + // The Width of the shift reg is an integer multiple of output data width + localparam SH_W = ((I_W/O_W) + ((I_W%O_W) > 0) + ((O_W % (I_W - ((I_W/O_W)*O_W) + ((I_W%O_W) == 0))) > 0))*O_W; + // The Step of the algorithm is the greatest common divisor of I_W and O_W + localparam STEP = gcd(I_W, O_W); localparam LATENCY = 1; // Minimum input latency from iready to ivalid @@ -93,6 +94,21 @@ module ad_upack #( wire [O_W*UNIT_W-1:0] odata_s; wire ovalid_s; + function [31:0] gcd; + input [31:0] a; + input [31:0] b; + begin + while (a != b) begin + if (a > b) begin + a = a-b; + end else begin + b = b-a; + end + end + gcd = a; + end + endfunction + assign unit_valid = (in_use | inmask); assign in_use_nx = unit_valid >> O_W; @@ -106,11 +122,9 @@ module ad_upack #( always @(*) begin inmask = {I_W{ivalid}}; - if (STEP>0) begin - for (i = STEP; i < O_W; i=i+STEP) begin - if (in_use[i-1]) begin - inmask = {I_W{ivalid}} << i; - end + for (i = STEP; i < O_W; i=i+STEP) begin + if (in_use[i-1]) begin + inmask = {I_W{ivalid}} << i; end end end @@ -119,11 +133,9 @@ module ad_upack #( idata_d_nx = idata_d; if (ivalid) begin idata_d_nx = {{(SH_W-I_W)*UNIT_W{1'b0}},idata}; - if (STEP>0) begin - for (i = STEP; i < O_W; i=i+STEP) begin - if (in_use[i-1]) begin - idata_d_nx = (idata << UNIT_W*i) | idata_d; - end + for (i = STEP; i < O_W; i=i+STEP) begin + if (in_use[i-1]) begin + idata_d_nx = (idata << UNIT_W*i) | idata_d; end end end diff --git a/library/common/tb/ad_pack_tb.v b/library/common/tb/ad_pack_tb.v index 32e4be084..d415ace8c 100644 --- a/library/common/tb/ad_pack_tb.v +++ b/library/common/tb/ad_pack_tb.v @@ -36,7 +36,7 @@ module ad_pack_tb; @(posedge clk); i = 0; j = 0; - while (i < VECT_W/(I_W*UNIT_W)) begin + while (i < (VECT_W/(I_W*UNIT_W) + (VECT_W%(I_W*UNIT_W)>0))) begin @(posedge clk); if ($urandom % 2 == 0) begin idata <= input_vector[i*(I_W*UNIT_W) +: (I_W*UNIT_W)];