library/common: Update the packing IPs to be more generic

main
Ionut Podgoreanu 2022-08-02 11:01:00 +01:00 committed by Laszlo Nagy
parent 0595f93452
commit 79579f65df
3 changed files with 55 additions and 34 deletions

View File

@ -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,20 +141,13 @@ module ad_pack #(
integer i;
always @(*) begin
out_mask = 'b0;
idata_packed = 'bx;
if (STEP>0) begin
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 else begin
if (in_use_nx[0]) begin
out_mask = {O_W{1'b1}};
idata_packed = idata_dd_nx;
end
end
end
assign pack_wr = ivalid_d & |in_use_nx[SH_W-O_W:0];

View File

@ -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,20 +122,17 @@ 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
end
end
end
always @(*) begin
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;
@ -127,7 +140,6 @@ module ad_upack #(
end
end
end
end
always @(posedge clk) begin
if (ovalid_s) begin

View File

@ -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)];