how to declare integer variable in verilog to keep track of a value to be used in multiple for loops? - verilog

so I have this assignment to make a generic Wallace tree multiplier in Verilog, I wrote the code but didn't test it yet. my problem is in the 2nd stage where I am supposed to bypass some wires which couldn't fit in the current stage into the next stage and the results of the current stages are passed to next stage, so I made a simple for loop to that operation:
/*the logic in this module*/
generate
for(i = 0; i < size/3; i = i + 1)
begin
integer k = 0;
for(j = i; j < size-3; j = j + 3)
begin
CSAlike #(2 * size) parallelAdder(intermediateWires[k][i+1], intermediateWires[k+1][i+1], intermediateWires[j][i], intermediateWires[j+1][i], intermediateWires[j+2][i]);
k = k + 2;
end
/*assign the wires from this stage who couldn't fit into the current stage (0 or 1 or 2 wires)*/
for(l = size-(size%3); l < size; l = l + 1)
begin
assign intermediateWires[k][i+1] = intermediateWires[l][i];
k = k + 1;
end
end
endgenerate
well , ModelSim give me this error :
vlog -work work -stats=none {D:/PROJECTS/third year/first term/VLSI/mini project 2/codes (before synthesis)/verilog codes/multiplierTree.v}
Model Technology ModelSim - Intel FPGA Edition vlog 2020.1 Compiler 2020.02 Feb 28 2020
-- Compiling module multiplierTree
** Warning: D:/PROJECTS/third year/first term/VLSI/mini project 2/codes (before synthesis)/verilog codes/multiplierTree.v(17): (vlog-2417) Multiple packed dimensions are not allowed.
-- Compiling module multiplyAllBits
** Warning: D:/PROJECTS/third year/first term/VLSI/mini project 2/codes (before synthesis)/verilog codes/multiplierTree.v(46): (vlog-2417) Multiple packed dimensions are not allowed.
-- Compiling module addIntermedaiteWires
** Warning: D:/PROJECTS/third year/first term/VLSI/mini project 2/codes (before synthesis)/verilog codes/multiplierTree.v(61): (vlog-2417) Multiple packed dimensions are not allowed.
** Warning: D:/PROJECTS/third year/first term/VLSI/mini project 2/codes (before synthesis)/verilog codes/multiplierTree.v(67): (vlog-2417) Multiple packed dimensions are not allowed.
** Error: (vlog-13069) D:/PROJECTS/third year/first term/VLSI/mini project 2/codes (before synthesis)/verilog codes/multiplierTree.v(92): near "=": syntax error, unexpected '='.
** Error: D:/PROJECTS/third year/first term/VLSI/mini project 2/codes (before synthesis)/verilog codes/multiplierTree.v(92): (vlog-13205) Syntax error found in the scope following 'k'. Is there a missing '::'?
and this is the full code:
/*resources :
https://www.youtube.com/watch?v=4-l_PGPog9o
https://www.youtube.com/watch?v=lcPIMvI57dM
*/
module multiplierTree #(parameter size = 32) (Res, OVF, A, B, clk);
/*the inputs to be multiplies*/
input [size-1:0] A, B;
input clk;
reg [size-1:0] A_in, B_in;
/*the outputs from the multiplier*/
output reg [(size-1)*2:0] Res;
output wire OVF; // overflow flag
/*intermediate wires for clean code*/
wire [size-1:0][(size-1)*2:0] wiresMultiplied;
wire [(size-1)*2:0] secondStage_Res, secondStage_carry, totalRes;
/*calling necessary modules*/
multiplyAllBits #(size) firstStage(wiresMultiplied, A_in, B_in);
addIntermedaiteWires #(size) secondStage(secondStage_Res, secondStage_carry, wiresMultiplied);
addResWithCarry #(2 * size) thirdStage(totalRes, secondStage_Res, secondStage_carry);
/*important assigns*/
assign OVF = Res[(size-1)*2] ^ A[size-1] & Res[(size-1)*2] ^ B[size-1] ;
/*the logic of the module*/
always#(posedge clk)
begin
A_in <= A;
B_in <= B;
Res <= totalRes;
end
endmodule
/*this is the first stage in the wallace tree*/
module multiplyAllBits #(parameter size = 32) (wiresMultiplied, A, B);
/*inputs to 1st stage of wallace tree*/
input wire [size-1:0] A, B;
/*outputs from the 1st stage*/
output wire [size-1:0][(size-1)*2:0] wiresMultiplied;
/*the actual logic in the circuit*/
genvar i, j;
generate
for(i = 0; i < size; i = i + 1)
assign wiresMultiplied[i] = ({size{B[i]}} & A) << i;
endgenerate
endmodule
/*this is the second stage in wallace tree*/
module addIntermedaiteWires #(parameter size = 32) (Res, carry, wiresMultiplied);
/*inputs coming from the 1st stage*/
input wire [size-1:0][(size-1)*2:0] wiresMultiplied;
/*outputs from 2nd stage*/
output wire [(size-1)*2:0] Res, carry;
/*intermediate wires for clean code*/
wire [size+1:0][size+1:0][(size-1)*2:0] intermediateWires;
genvar i, j, l;
/*important assigns*/
generate
for(i = 0; i < size; i = i + 1)
begin
assign intermediateWires[i][0] = wiresMultiplied[i];
end
endgenerate
/*getting the results*/
assign Res = intermediateWires[size+1][size+1];
assign calling = intermediateWires[size+1][size+1];
/*the logic in this module*/
generate
for(i = 0; i < size/3; i = i + 1)
begin
integer k = 0;
for(j = i; j < size-3; j = j + 3)
begin
CSAlike #(2 * size) parallelAdder(intermediateWires[k][i+1], intermediateWires[k+1][i+1], intermediateWires[j][i], intermediateWires[j+1][i], intermediateWires[j+2][i]);
k = k + 2;
end
/*assign the wires from this stage who couldn't fit into the current stage (0 or 1 or 2 wires)*/
for(l = size-(size%3); l < size; l = l + 1)
begin
assign intermediateWires[k][i+1] = intermediateWires[l][i];
k = k + 1;
end
end
endgenerate
endmodule
/*this is CSA look like to add parallely*/
module CSAlike #(parameter size = 32) (result, carry, A, B, C);
/*list of the inputs*/
input wire [size-1:0] A, B, C;
/*outputs*/
output wire [size-1:0] result, carry;
/*temp genvar*/
genvar i;
/*actual logic of parallel adders*/
for(i = 0; i < size; i = i + 1)
begin
FA fa(A[i], B[i], C[i], result[i], carry[i]);
end
endmodule
module addResWithCarry #(parameter size = 32) (Res_out, Res_in, carry_in);
/*list of the inputs*/
input wire [size-1:0] Res_in, carry_in;
/*outputs*/
output wire [size-1:0] Res_out;
/*using normar adder (verilog adder (adder plus))*/
assign Res_out = Res_in + carry_in;
endmodule
as it tells me that writing
k = k + 2;
is wrong inside the generate loop, but I don't know why, also it gave me some warnings telling me that writing
wire [size-1:0][(size-1)*2:0] wiresMultiplied;
has something wrong with it but IDK what's wrony with my code.

it tells me that writing
k = k + 2;
is wrong inside the generate loop, but I don't know why
It is a syntax error to make that assignment where you do in the code. It is an error for the same reason as this extreme simplification of your code is an error:
module dut;
integer k = 0;
k = k + 2;
endmodule
The integer declaration line is legal, but the other assignment line is illegal because it looks like you are trying to make a procedural assignment outside of a procedural block (like an always block).
When debugging problems with generate loops, it's always helps to "unroll" the loop and start writing out the code the long way. These loops are advanced syntax constructs and are tricky to use. Especially nested loops. Especially for students who are just starting to learn Verilog.

Related

Using a recursive assignment inside for loop in Verilog

I am trying to implement a fitness evaluation function in Verilog called Rosenbrock function (https://en.wikipedia.org/wiki/Rosenbrock_function). The issue I am facing is that if I use the following code it gives me a undefined state since there are 4 drivers to the wire fitness_val.
module test_module1 ( x, fitness);
input [4*2 -1:0] x;
output [1:0] fitness;
wire [1:0] x_i;
wire [1:0] x_im1;
wire [3:0] fitness_val;
wire [3:0] a;
wire [3:0] b;
wire [1:0] x_array1 [3:0];
genvar k;
assign fitness = fitness_val;
genvar j;
generate
for (j =0 ; j <4 ; j = j+1) begin
assign x_array1[j] = x[2*j +: 2];
end
for (k=1; k<4; k=k+1) begin
assign x_i = x_array1[k];
assign x_im1 = x_array1[k-1];
assign a = 100*(x_i[1:0] - x_im1[1:0])*(x_i[1:0] - x_im1[1:0]);
assign b = (1 - x_im1[1:0])*(1 - x_im1[1:0]);
assign fitness_val = fitness_val + a[2:1] + b[2:1];
end
endgenerate
endmodule
module tb_tm1();
wire [1:0] fitness;
wire [4*2-1:0] x_array;
test_module1 tm1(x_array, fitness);
assign x_array = 8'b11100100;
endmodule
However if I expand the for loop in this format, I get a valid output.
assign fitness_val = 100*(x_array1[1] - x_array1[0])*(x_array1[1] - x_array1[0]) + (1 - x_array1[0])*(1 - x_array1[0])
+ 100*(x_array1[2] - x_array1[1])*(x_array1[2] - x_array1[1]) + (1 - x_array1[1])*(1 - x_array1[1])
+ 100*(x_array1[3] - x_array1[2])*(x_array1[3] - x_array1[2]) + (1 - x_array1[2])*(1 - x_array1[2]);
Is there a way to implement this recursively in Verilog?
assign statements run concurrently; not sequentially. Generate loops are static unrolled during elaborations. When two assign statements drive different values to the same net, the result will be x.
To do sequential operations you will need to an always block.
Minimum change as follows (plus ANSI style header):
module test_module1 (
input [4*2 -1:0] x,
output [1:0] fitness ); // <-- ANSI style header
reg [1:0] x_i; // 'always' block assign 'reg' type
reg [1:0] x_im1;
reg [3:0] fitness_val;
reg [3:0] a;
reg [3:0] b;
wire [1:0] x_array1 [3:0]; // 'assign' drives 'wire' type
interger k; // index for loop in an always block
genvar j; // index for a generate loop
assign fitness = fitness_val;
generate
for (j =0 ; j <4 ; j = j+1) begin
assign x_array1[j] = x[2*j +: 2];
end
endgenerate
always #* begin // #* is auto-sensitivity, use for combination logic
fitness_val = 4'b0000; // initial value, otherwise it infers a latch
for (k=1; k<4; k=k+1) begin
x_i = x_array1[k];
x_im1 = x_array1[k-1];
a = 100*(x_i[1:0] - x_im1[1:0])*(x_i[1:0] - x_im1[1:0]);
b = (1 - x_im1[1:0])*(1 - x_im1[1:0]);
fitness_val = fitness_val + a[2:1] + b[2:1];
end
end
endmodule
FYI: 4-bits is not enough to hold the value decimal 100. Do Do you want to make it bigger you did you intend the 100 to represent 4 in binary (4'b0100)?

Systemverilog recursion update value for next stage

I am trying to create a recursive logic in Systemverilog but I seem to be missing the right logic to carry the output of one iteration to the next.
Here is an example of the problem:
parameter WIDTH=4;
module test_ckt #(parameter WIDTH = 4)(CK, K, Z);
input CK;
input [WIDTH-1:0] K;
output reg Z;
wire [WIDTH/2-1:0] tt;
wire [WIDTH-1:0] tempin;
assign tempin = K;
genvar i,j;
generate
for (j=$clog2(WIDTH); j>0; j=j-1)
begin: outer
wire [(2**(j-1))-1:0] tt;
for (i=(2**j)-1; i>0; i=i-2)
begin
glitchy_ckt #(.WIDTH(1)) gckt (tempin[i:i], tempin[(i-1):i-1], tt[((i+1)/2)-1]);
end
// How do I save the value for the next iteration?
wire [(2**(j-1))-1:0] tempin;
assign outer[j].tempin = outer[j].tt;
end
endgenerate
always #(posedge CK)
begin
// How do I use the final output here?
Z <= tt[0];
end
endmodule
module glitchy_ckt #(parameter WIDTH = 1)(A1, B1, Z1);
input [WIDTH-1:0] A1,B1;
output Z1;
assign Z1 = ~A1[0] ^ B1[0];
endmodule
Expected topology:
S1 S2
K3--<inv>--|==
|XOR]---<inv>----|
K2---------|== |
|==
<--gckt---> |XOR]
|==
K1--<inv>--|== |
|XOR]------------|
K0---------|== <-----gckt---->
Example input and expected outputs:
Expected output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 1 <- j=1 and i=1.
Actual output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 0 <- j=1 and i=1. Here, because tempin is not updated, inputs are same as (j=2 & i=1).
Test-bench:
`timescale 1 ps / 1 ps
`include "test_ckt.v"
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
#0 CK = 0;
A = 4'b1010;
#500 $finish;
end
initial begin
//dump waveform
$dumpfile("test_ckt.vcd");
$dumpvars(0,dut);
end
endmodule
How do I make sure that tempin and tt get updated as I go from one stage to the next.
Your code does not have any recursion in it. You were trying to solve it using loops, but generate blocks are very limited constructs and, for example, you cannot access parameters defined in other generate iterations (but you can access variables or module instances).
So, the idea is to use a real recursive instantiation of the module. In the following implementation the module rec is the one which is instantiated recursively. It actually builds the hierarchy from your example (I hope correctly).
Since you tagged it as system verilog, I used the system verilog syntax.
module rec#(WIDTH=1) (input logic [WIDTH-1:0]source, output logic result);
if (WIDTH <= 2) begin
always_comb
result = source; // << generating the result and exiting recursion.
end
else begin:blk
localparam REC_WDT = WIDTH / 2;
logic [REC_WDT-1:0] newSource;
always_comb // << calculation of your expression
for (int i = 0; i < REC_WDT; i++)
newSource[i] = source[i*2] ^ ~source[(i*2)+1];
rec #(REC_WDT) rec(newSource, result); // << recursive instantiation with WIDTH/2
end // else: !if(WIDTH <= 2)
initial $display("%m: W=%0d", WIDTH); // just my testing leftover
endmodule
The module is instantiated first time from the test_ckt:
module test_ckt #(parameter WIDTH = 4)(input logic CK, input logic [WIDTH-1:0] K, output logic Z);
logic result;
rec#(WIDTH) rec(K, result); // instantiate first time )(top)
always_ff #(posedge CK)
Z <= result; // assign the results
endmodule // test_ckt
And your testbench, a bit changed:
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
CK = 0;
A = 4'b1010;
#500
A = 4'b1000;
#500 $finish;
end
initial begin
$monitor("Z=%b", Z);
end
endmodule // mytb
Use of $display/$monitor is more convenient than dumping traces for such small examples.
I did not do much testing of what I created, so there could be issues, but you can get basic ideas from it in any case. I assume it should work with any WIDTH which is power of 2.

Multiplication of 2 matrix in verilog

I've written a code for matrx multiplication in Verilog.
module multiply3x3(i1,i2,i3,i4,i5,i6,i7,i8,i9,j1,j2,j3,j4,j5,j6,j7,j8,j9,prod);
output reg [31:0]prod;
wire [7:0]resultant[3:0][3:0];
wire [7:0]a[3:0][3:0];
wire [7:0]b[3:0][3:0];
genvar i,j,k;
generate
for (i = 0; i <= 2; i=i+1) begin:i_
for (j = 0; j <= 2; j=j+1) begin:j_
assign resultant[i][j] = 8'd0;
for (k = 0; k <= 2; k=k+1) begin:k_
assign resultant[i][j] = resultant[i][j] + a[i][k] * b[k][j];
end
end
end
endgenerate
endmodule
initial begin
#100 prod = {resultant[0][0],resultant[0][1],resultant[0][2],resultant[1][0],resultant[1][1],resultant[1][2],resultant[2][0],resultant[2][1],resultant[2][2]};
end
This is where the multiplication happens, but i cannot get the output for this.
What am I doing wrong?
consider a,b declared properly.
Accumulation (a = a + p) doesn't work with wires. The type wire is supposed to model a physical wire.
You'll have to declare the variable resultant as a reg. The reg type, in Verilog, can in some cases be treated like a variable in other programming languages.
Also, you can't use the assign statement on a wire or reg multiple times (like you've done in line 78 and 80 of https://pastebin.com/txrcwUBd). You should use always (and not generate) blocks to perform such things.
Corrected Verilog:
reg [7:0] resultant[3:0][3:0];
int i, j, k;
always #(*)
for(i=0; i<3; i=i+1)
for(j=0; j<3; j=j+1) begin
resultant[i][j] = 8'd0;
for(k=0; k<3; k=k+1)
resultant[i][j] = resultant[i][j] + (a[i][k]*b[k][j]);
end

Bit slicing in verilog

How can I write wdata[((8*j)+7) : (8*i)] = $random; in verilog programming language? , where i and j are reg type variable. Modelsim gives error for constant range variable. How could I write it in proper manner.
You should think from Hardware prospective for the solution.
Here is one solution. Hope that it will help you.
module temp(clk);
input clk;
reg i, j;
reg [23:0] register, select;
wire [23:0] temp;
initial
begin
i = 'd1;
j = 'd1;
end
generate
for(genvar i = 0; i<24; i++)
begin
assign temp[i] = select[i] ? $random : register[i];
end
endgenerate
always # (posedge clk)
begin
register <= temp;
end
always # *
begin
select = (32'hffff_ffff << ((j<<3)+8)) ^ (32'hffff_ffff << (i<<3));
end
endmodule
Use the array slicing construction. You can find more detailed explanation at Array slicing Q&A
bit [7:0] PA, PB;
int loc;
initial begin
loc = 3;
PA = PB; // Read/Write
PA[7:4] = 'hA; // Read/Write of a slice
PA[loc -:4] = PA[loc+1 +:4]; // Read/Write of a variable slice equivalent to PA[3:0] = PA[7:4];
end
Verilog 2001 Syntax
[M -: N] // negative offset from bit index M, N bit result
[M +: N] // positive offset from bit index M, N bit result

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