Assign value to a 2D array from a 2D array SystemVerilog - verilog

I'm quite new with SystemVerilog, I-m trying to assign a value to a 2D array from another 2D array, but each time I compile this error appers:
Error: (vlog-13069) ../src/dadda tree/daddaTree.sv(75): near "[": syntax error, unexpected '['.
Here the code:
module daddaTree import globals ::*; (
input wire signed [24:0]PP[8],
output wire [31:0]C,
output wire [31:0]S );
// layers of the reduction tree
wire [31:0]l3[8];
wire [31:0]l2[5];
wire [20]Tout_l3;
// zero paffing of the inputs partial products
assign l3[0] = 8'b00000000 & PP[0];
assign l3[1] = 7'b0000000 & PP[1] & 1'b0;
assign l3[2] = 6'b000000 & PP[2] & 2'b00;
assign l3[3] = 5'b00000 & PP[3] & 3'b000;
assign l3[4] = 4'b0000 & PP[4] & 4'b0000;
assign l3[5] = 3'b000 & PP[5] & 5'b00000;
assign l3[6] = 2'b00 & PP[6] & 6'b000000;
assign l3[7] = 1'b0 & PP[7] & 7'b0000000; // MSB for carry of the layer
// bit with no compression
// [4:0]l2[0:4] = '{l3{[4:0][0:4]}}; ERRORS HERE
// assign l2[5][1:4] = l3[5][2:5];
// assign l2[6][2:4] = l3[6][3:6];
// assign l2[7][3:4] = l3[7][6:7];
endmodule
I can assign an entire raw of bit as assign l3[0] = 8'b00000000 & PP[0];, but when I have to assign a slice of an array to another the compiler givve me the above error.
I mean how can assign for example:
"l3 from column 0 to 4, from raw 0 to 4"
to
"l2 from column 0 to 4, from raw 0 to 4"
as an example bits [4:0] of column [0:4] of l2 should have as input bits [4:0] of column [0:4] of l3, that are zeros, or PP values received from another module, so unknwon values.
I can do the assignement manualy untill a certain point:
// bit without compression
assign l2[0][0] = l3[0][0]; // c0
assign l2[1][0] = l3[1][0]; // c1
assign l2[1][1] = l3[1][1];
assign l2[2][0] = l3[2][0]; // c2
assign l2[2][1] = l3[2][1];
assign l2[2][2] = l3[2][2];
assign l2[3][0] = l3[3][0]; // c3
assign l2[3][1] = l3[3][1];
assign l2[3][2] = l3[3][2];
assign l2[3][3] = l3[3][3];
assign l2[4][0] = l3[4][0]; // c4
assign l2[4][1] = l3[4][1];
assign l2[4][2] = l3[4][2];
assign l2[4][3] = l3[4][3];
assign l2[4][4] = l3[4][4];
assign l2[5][1] = l3[5][2]; // c5
assign l2[5][2] = l3[5][3];
assign l2[5][3] = l3[5][4];
assign l2[5][4] = l3[5][5];
but also in this case an error appears
Error (suppressible): ../src/dadda tree/daddaTree.sv(95): (vlog-2698) Index 5 into array dimension 1 of 'l2' is out of bounds.
Please someone can explain me how can I assign it?
Thanks

[4:0]l2[0:4] = '{l3{[4:0][0:4]}} -- what is it supposed to mean? No wonder that there is a syntax error. I guess, you wanted something like the following: assign l2[0:4][4:0] = l3[0:4][4:0] which is impossible, because you take a slice of the lower dimension here.
As for index out of bounds, l2 is declared as wire [31:0]l2[5]; where the outer index is [5], meaning [0:4]. So, when you tried to use index 5 it is out of bounds since the max is 4.
So, your only bet is to use generate for loops, for example (based on your manual code):
for(genvar i = 0; i <= 4; i++) begin: L1
for (genvar j = 0; j < i; j++) begin: L2
assign l2[i][j] = l3[i][j];
end
end
Or maybe like this:
for(genvar i = 0; i <= 4; i++) begin: L1
assign l2[i][i:0] = l3[i][i:0];
end
You have to figure out exact numbers.

Related

How to fix inferring latch(es) error when I use a for loop?

I'm implementing a module to count number of '1's in an input vector and cannot fix the inferring latches error.
Warning (10240): Verilog HDL Always Construct warning at top_module.v(15): inferring latch(es) for variable "count", which holds its previous value in one or more paths through the always construct File: /var/www/verilog/work/vlgaaQTZu_dir/top_module.v Line: 15
Warning (10240): Verilog HDL Always Construct warning at top_module.v(15): inferring latch(es) for variable "mask", which holds its previous value in one or more paths through the always construct File: /var/www/verilog/work/vlgaaQTZu_dir/top_module.v Line: 15
I've tried to add an else expression in the for loop after if statement, and also add an initial statement to initialize the value of count and mask.
module top_module(
input [254:0] in,
output [7:0] out );
wire [7:0]count;
wire [254:0]mask;
initial begin
count = 8'h0;
mask = 255'h1;
end
always #(*)
begin
for(int i = 0; i < 255; i = i + 1)
begin
if(in & mask)
begin
count = count + 1;
mask = mask << 1;
end
else
begin
count = count;
mask = mask;
end
end
out = count;
end
endmodule
I failed to pass the complying.
Adding the initial statement only initializes the variables once at time 0. You need to initialize every time you enter the always block so you never reference the previous values.
always #(*)
begin
count = 8'h0;
mask = 255'h1;
for(int i = 0; i < 255; i = i + 1)
begin
if(in & mask)
begin
count = count + 1;
mask = mask << 1;
end
end
out = count;
end

Selecting a set of parameters based on input value in Verilog

I am working on a Module which changes it's constant values based on the input to calculate it's output.
Let me illustrate what I am looking for,
Let x be the input, y the output and a,b,c,d,e the set of constants.
Module performs something like the following operation:
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); //separate adder and multiplier modules are used and this code itself is huge so just providing the idea.
Now I have used following method to choose the right value for the constants depending on the input: (Pseudo code)
module top (x,clk,y);
input clk;
input [31:0] x;
output [31:0] y;
if (x>=32'h08000000 && x<32'h0A000000) begin
localparam a = 32'h058B90C0;
localparam b = 32'h193C9F60;
localparam c = 32'h29AC1740;
localparam d = 32'hA48B9440;
localparam e = 32'h0B6392E0;
end else if (x>=32'h0A000000 && x<32'h0C000000) begin
localparam a = 32'h028A50C1;
localparam b = 32'hE98B489C;
localparam c = 32'h17402948;
localparam d = 32'h9440E45B;
localparam e = 32'h392E00AF;
end
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); // Module that computes using any of the above mentioned constant sets
endmodule
I get the following errors:
(1) "Unable to bind parameter".
(2) "Cannot evaluate genvar conditional expression: ((x)G(32'000010000....00))&& so on......"
My question is:
My user will give the input through x, right constants will be chosen, my module will calculate and provide the output. Just providing the right constants to the module is enough. How shall I do it? Ideas through pseudo code will be helpful for me.
I had to look up where localparam is allowed. You can define a localparam after a begin : < label >.
I tried it and found that (at least in Vivado) it passed and worked.
always #( a )
if (a>=1)
begin : a_be_1
localparam P1 = 3;
c = P1;
end
else
begin : a_sm_1
localparam P1 = 5;
c = P1;
end

Unusual behavior of verilog code

I am writing one simple asynchronous sequence detector, but i am getting unusual result at one point. Code is working fine with "assign a8 = ((y2&&inp1&&~inp2)||(y1&&inp1)); " but if i replace above line with following lines in my code its not giving the correct result.
assign a6 = (y2&&inp1&&~inp2);
assign a5 = (y1&&inp1);
assign a8 = a6||a5;
Both are technically the same but i am not able to understand why output is not coming correct when i use above lines of code.
module Async_Design(inp1,inp2,outp);
input inp1,inp2;
output outp;
wire y1 ,y2;
/*assign a6 = (y2&&inp1&&~inp2);
assign a5 = (y1&&inp1);
assign a8 = (a6||a5);*/
/*Uncommenting the above section and commenting below
line is not giving correct result*/
assign a8 = ((y2&&inp1&&~inp2)||(y1&&inp1));
Delay D1(y1,a8);
nand(a1,y1,1'b1);
nand(a2,a1,inp1);
nand(a3,a2,1'b1);
nand(a4,a3,inp2);
nand(a5,a4,1'b1);
Delay D2(y2,a5);
assign outp = y1;
endmodule
module Delay(q,inp);
output q;
input inp;
reg q;
initial
begin
q=1'b0;
end
always #(*)
begin
q=((inp&&1'b1)||(inp&&1'b1));
end
endmodule
/***********************************************/
TEST BENCH
/***********************************************/
module Async_Design_Test;
reg inp1,inp2;
wire outp;
reg[15:0] sequence1;
reg[15:0] sequence2;
integer i;
Async_Design Async(inp1,inp2, outp);
initial
begin
sequence1 = 16'b 0101_1111_0111_1111;
sequence2 = 16'b 1010_1010_1110_1111;
for( i = 0; i <= 15; i = i+1)
begin
inp1 = sequence1[i];
inp2 = sequence2[i];
#6
$display( " Input1 = ", inp1, " Input2 = ", inp2, " Output = ", outp,);
end
end
endmodule
Can anyone help me to understand this behavior as i am new to HDL coding
Your code after change is not valid one. Why?
assign a5 = (y1&&inp1);
...
nand(a5,a4,1'b1);
What you're trying to do is drive a5 wire in two different places (btw your compiler should print an error like "can't resolve multiple constant drivers for net a5"). And it won't work, since you can drive a wire only in one place. If you change one of this lines, e.g.:
assign a6 = (y2&&inp1&&~inp2);
assign a7 = (y1&&inp1);
assign a8 = (a6||a7);
you'll get the same output as if you use assign a8 = ((y2&&inp1&&~inp2)||(y1&&inp1)).
PS Consider usage of & and | operators.

Generate block is not assigning any values to wire

Im new to verilog, and Im trying to write certain multiplier, but when I run my testbench it doesn't show much. It looks like generate block does not assign any values to partial. Here is a screen:
And code:
Changed names in code, so it is more familiar for english users.
`timescale 1ns/1ps
`ifndef N_WIDTH
`define N_WIDTH 8
`endif
module mult(datX, datY, result);
parameter n = 8;
input [n-1:0] datX, datY;
output [2*n-1:0] result;
//assign datX = 8'b0;
//assign datY = 8'b0;
wire [n-1:0] partial;
genvar i;
generate
for(i=0; i<n; i=i+1) begin: IloczynyCzesciowe
if(i<7) assign partial[7:i] = datY[n-1-i:0];
if(i==1) assign partial[0] = datY[7];
if(i==7) assign partial[7] = datY[0];
if(i>1) assign partial[i-1:0] = datY[n-1:n-i];
assign partial = datX[i] * partial;
assign result = result + (partial % (2^n-1));
end
endgenerate
endmodule
module testbench_mul;
parameter n = 8;//`N_WIDTH;
parameter clk_period = 2;
reg clk, clk_ena;
reg [n-1:0] a,b;
wire [2*n-1:0] res;
reg [2*n-1:0] res_expected;
initial begin
a = 8'b00000001;
b = 8'b00001111;
#clk_period;
clk = 0;
clk_ena = 1;
$display("actual_s = %d", a );
res_expected = a + b;
end
always begin
#clk_period;
if (clk_ena)
clk = ~clk;
end
mult #(.n(n)) UUT (.datX(a), .datY(b), .result(res));
always #(posedge clk) begin
a = a + 1;
res_expected = a+b;
#1;
if (res != res_expected) begin
$display("ERROR: a: %b, b: %b, sum:%b, expected:%b partial:%d", a,b,res, res_expected, UUT.partial);
end
end
initial
#200 $finish;
endmodule
Please tell me what I'm doing wrong.
The generate block is assigning to partial and result, however there are multiple drivers to the same wire. Generate block expands the code at compile time. When Executed it will be the equivalent to the following:
// loop n=0
assign partial[7:0] = datY[n-1-0:0];
assign partial = datX[0] * partial;
assign result = result + (partial % (2^n-1));
// loop n=1
assign partial[7:1] = datY[n-1-1:0];
assign partial[0] = datY[7];
assign partial = datX[1] * partial;
assign result = result + (partial % (2^n-1));
// loop n=2
assign partial[7:2] = datY[n-1-2:0];
assign partial[2-1:0] = datY[n-1:n-2];
assign partial = datX[2] * partial;
assign result = result + (partial % (2^n-1));
// loop n=3
assign partial[7:3] = datY[n-1-3:0];
assign partial[3-1:0] = datY[n-1:n-3];
assign partial = datX[3] * partial;
assign result = result + (partial % (2^n-1));
// loop n=4
assign partial[7:4] = datY[n-1-4:0];
assign partial[4-1:0] = datY[n-1:n-4];
assign partial = datX[4] * partial;
assign result = result + (partial % (2^n-1));
// loop n=5
assign partial[7:5] = datY[n-1-5:0];
assign partial[5-1:0] = datY[n-1:n-5];
assign partial = datX[5] * partial;
assign result = result + (partial % (2^n-1));
// loop n=6
assign partial[7:6] = datY[n-1-6:0];
assign partial[6-1:0] = datY[n-1:n-6];
assign partial = datX[6] * partial;
assign result = result + (partial % (2^n-1));
// loop n=7
assign partial[7] = datY[0];
assign partial[7-1:0] = datY[n-1:n-7];
assign partial = datX[7] * partial;
assign result = result + (partial % (2^n-1));
Conflicting assignment values will cause the output to be X and having an assignment that feedback on self without a way to break the loop will also always be X.
An always block can be used instead. Part select cannot have variables (e.g. [7:i]), so you need to assign all of the bits at once or assign each bit. This is equivalent to generate code:
reg [2*n-1:0] result;
reg [n-1:0] partial;
integer i;
always #* begin
result = 0;
for(i=0; i<n; i=i+1) begin: IloczynyCzesciowe
// partial[7:0] = {datY,datY} >> (8-i); // this functional also works
for(j=0; j<n; j++) begin : assign_bits
partial[j] = datY[(8+j-i)%8];
end
partial = datX[i] * partial;
result = result + (partial % (2^n-1));
end
end
Note: The multiplier function does work as expected. It is outside the scope of the question to solve it.

How to design a 64 x 64 bit array multiplier in Verilog?

I know how to design a 4x4 array multiplier , but if I follow the same logic , the coding becomes tedious.
4 x 4 - 16 partial products
64 x 64 - 4096 partial products.
Along with 8 full adders and 4 half adders, How many full adders and half adders do I need for 64 x 64 bit. How do I reduce the number of Partial products? Is there any simple way to solve this ?
Whenever tediously coding a repetitive pattern you should use a generate statement instead:
module array_multiplier(a, b, y);
parameter width = 8;
input [width-1:0] a, b;
output [width-1:0] y;
wire [width*width-1:0] partials;
genvar i;
assign partials[width-1 : 0] = a[0] ? b : 0;
generate for (i = 1; i < width; i = i+1) begin:gen
assign partials[width*(i+1)-1 : width*i] = (a[i] ? b << i : 0) +
partials[width*i-1 : width*(i-1)];
end endgenerate
assign y = partials[width*width-1 : width*(width-1)];
endmodule
I've verified this module using the following test-bench:
http://svn.clifford.at/handicraft/2013/array_multiplier/array_multiplier_tb.v
EDIT:
As #Debian has asked for a pipelined version - here it is. This time using a for loop in an always-region for the array part.
module array_multiplier_pipeline(clk, a, b, y);
parameter width = 8;
input clk;
input [width-1:0] a, b;
output [width-1:0] y;
reg [width-1:0] a_pipeline [0:width-2];
reg [width-1:0] b_pipeline [0:width-2];
reg [width-1:0] partials [0:width-1];
integer i;
always #(posedge clk) begin
a_pipeline[0] <= a;
b_pipeline[0] <= b;
for (i = 1; i < width-1; i = i+1) begin
a_pipeline[i] <= a_pipeline[i-1];
b_pipeline[i] <= b_pipeline[i-1];
end
partials[0] <= a[0] ? b : 0;
for (i = 1; i < width; i = i+1)
partials[i] <= (a_pipeline[i-1][i] ? b_pipeline[i-1] << i : 0) +
partials[i-1];
end
assign y = partials[width-1];
endmodule
Note that with many synthesis tools it's also possible to just add (width) register stages after the non-pipelined adder and let the tools register balancing pass do the pipelining.
[how to] reduce the number of partial products?
A method somewhat common used to be modified Booth encoding:
At the cost of more complicated addend selection, it at least almost halves their number.
In its simplest form, considering groups of three adjacent bits (overlapping by one) from one of the operands, say, b, and selecting 0, a, 2a, -2a or -a as an addend.
The code below generates only half of expected the output.
module arr_multi(a, b, y);
parameter w = 8;
input [w-1:0] a, b; // w-width
output [(2*w)-1:0] y; // p-partials
wire [(2*w*w)-1:0] p; //assign width as input bits multiplied by
output bits
genvar i;
assign p[(2*w)-1 : 0] = a[0] ? b : 0; //first output size bits
generate
for (i = 1; i < w; i = i+1)
begin
assign p[(w*(4+(2*(i-1))))-1 : (w*2)*i] = (a[i]?b<<i :0) + p[(w*(4+(2*
(i-2))))-1 :(w*2)*(i-1)];
end
endgenerate
assign y=p[(2*w*w)-1:(2*w)*(w-1)]; //taking last output size bits
endmodule

Resources