I am trying to write the Verilog code for a multiplexer module, that has a parametrized number of inputs. I am aware that you can pack the inputs together and use the select input to slice that packed variable but I want to use a binary tree structure for my multiplexer.
The problem lies in using auxiliary variables to properly index inner wires (interm_w), meaning I need to be able to modify certain integer variables after each iteration of my inner for loop, but I don't know how. These variables include P, M, and K.
module multiplexer_v2(input_data_array, select, output_data);
parameter WIDTH = 16;
parameter NUMBER_OF_INPUTS = 8;
parameter SELECT_WIDTH = $clog2(NUMBER_OF_INPUTS);
localparam INTERMEDIATE_WIRES_COUNT = interm_value(SELECT_WIDTH, NUMBER_OF_INPUTS); // this is a function, that works correctly.
input [SELECT_WIDTH-1:0] select;
input [WIDTH-1:0] input_data_array [0:NUMBER_OF_INPUTS-1];
output [WIDTH-1:0] output_data;
wire [WIDTH-1:0] interm_w [0:INTERMEDIATE_WIRES_COUNT-1];
genvar i;
genvar j;
int K = NUMBER_OF_INPUTS / 2;
int M = NUMBER_OF_INPUTS;
int P = 0;
generate
for(i = 0; i < SELECT_WIDTH; i=i+1) begin
for(j = 0; j < K; j=j+1) begin
multiplexer_2_input #(
.WIDTH(WIDTH)
) mux_i (
.input_0(interm_w[P + j * 2]),
.input_1(interm_w[P + j * 2 + 1]),
.select(select[SELECT_WIDTH - i - 1]),
.output_data(interm_w[M + j])
);
end
P = M; // line 51 is here
M = M + K;
K = K / 2;
end
endgenerate
endmodule
I have tried using datatypes such as localparam, int, integer, parameter, and genvar for these variables, and moving around their initialization, but I face the same errors each time:
** Error: (vlog-13069) .../multiplexer_v2.sv(51): near "=": syntax error, unexpected '='.
** Error: .../multiplexer_v2.sv(51): (vlog-13205) Syntax error found in the scope following 'P'. Is there a missing '::'?
I would greatly appreciate any help I can get.
The interm_value() function is as follows:
function int interm_value(input int select_width, input int number_of_inputs);
begin
int i;
int interm_value;
int K;
interm_value = 0;
K = number_of_inputs;
for(i = 0; i < select_width; i=i+1) begin
interm_value = interm_value + K;
K = K / 2;
end
return interm_value + 1;
end
endfunction
The reason for the syntax errors is that variables require procedural assignments (from within an always block, for example). But, you are not doing that.
One approach to debugging problems associated with generate for loops is to manually unroll the loop.
In your code, the outer loop iterates 3 times. Removing the loop code, you are left with these assignments for M and P:
int M = NUMBER_OF_INPUTS;
int P = 0;
P = M;
P = M;
P = M;
M = M + K;
M = M + K;
M = M + K;
Those assignments should be inside a procedural block. Also, as you can see, it doesn't make much sense to assign the same value to P multiple times.
With that explanation, I recommend trying to design something simpler without the loops at first.
Related
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.
Is below sort of generate loop is valid in system verilog.
genvar i,j;
for (i=0,j=5; i<5 && j<10; i++,j++) begin:M1
integer t;
initial begin
t = i*j;
end
endgenerate
Nope. I'm not even sure what the behavior of this code should be, or in what order they execute.
genvar i,j;
for (i = 0; i <5; i++) begin
for (j = 5; j < 10; j++) begin
$display("%d", i*j);
end
end
you don't need 'endgenerate' in the end.
You cannot do much with genvars in your example.
The following code mimics what you asked for, but it might not work with all simulators. It works with synopsys vcs but does not work with icarus.
module g;
genvar i;
for (i=0; i<5; i++) begin:M
if (i == 0) begin:B
parameter j = 5;
end
else begin:B
parameter j = g.M[i-1].B.j + 1;
end
integer t;
initial begin
t = i*B.j;
$display(i, B.j, t);
end
end // block: M
endmodule // g
the idea is to declare the parameter j inside the generate loop so that its value is an increment of the value declared in the previous iteration. You need to add a named block 'B' to declare conditionally.
How do I truncate the width of a genvar variable? For instance, if I have:
parameter LENGTH = 8;
genvar i;
for(i = 0; i < LENGTH; i = i + 2) begin
somemodule #(WIDTH($clog2(LENGTH))
)
tmp (.a(i)
,.b(i+1)
,.c(output)
);
end
endgenerate
When I simulate in ModelSim, I would get port size does not match connection size. I know the problem lies in that genvar is 32 bit wide, and my module's width varies.
I tried
genvar [$clog2(LENGTH)-1:0] i;
and
.a(i[$clog2(LENGTH)-1:0])
but they are not syntactically correct.
How do I get around this problem?
You can use an intermediate parameter declared with a data type for this
parameter int LENGTH = 8;
parameter int WIDTH = $clog2(LENGTH);
for(genvar i = 0; i < LENGTH; i = i + 2) begin
parameter bit [WIDTH-1:0] A = i;
somemodule #(.WIDTH(WIDTH))
)
tmp (.a(A)
,.b(A+1'b1)
,.c(output)
);
end
I want to convert this c code to verilog module but I am having some difficulty
void window_averaging(void) {
register unsigned int i, k;
for (i = 0; i < 128; i++) {
// Copying first 128 output samples to the Window 0 and so on till Window 7.
W[count][i] = O[i];
}
for (i = 0; i < 128; i++) {
for (k = 0; k< 8; k++) {
O[i] += W[k][i];
}
O[i] /= 8; // Averaging over 8 window
}
count = (count++)%8; // Count = 0 after all the window elements are filled.
}
Verilog:
module window_averaging(
input [16:0]in_noise, //input from noise cancellation
input clk,
output reg [16:0]window_average // output after window averaging
);
integer i;
integer k;
integer count = 0;
reg [16:0] store_elements[0:7][0:128]; // 2-D array for window averaging
reg [16:0] temp;
always #(posedge clk)
begin
// Copying first 128 output samples to the Window 0 and so on till Window 7
for(i=0 ; i < 128 ; i = 1+1)
begin
store_elements[count][i] = in_noise;
end
for(i=0; i<128 ; i=i+1)
begin
for(k=0;k<8;k = k+1)
begin
temp = temp + store_elements[i][k];
end
window_average = temp/8;
count = (count+1)%8;
end
end
endmodule
The errors I am getting are syntax error near "(" and "=". I am little new to verilog can anyone help me how to proceed.
First you are trying to drive a wire from inside an #always block which is not allowed. If you convert the wires to regs then it will work:
module window_averaging(
input [16:0]in_noise, //input from noise cancellation
input clk,
output reg [16:0]window_average // output after window averaging
);
integer i;
integer k;
integer count = 0;
reg [16:0] store_elements[0:7][0:128]; // 2-D array for window averaging
reg [16:0] temp;
...
Also I believe to be consistent with your C code the line count = (count+1)%8; should be outside the for loop like so:
window_average = temp/8;
end
count = (count+1)%8;
end
endmodule
I don't know what you are using to compile, but I think the following stuff should give you errors:
For the first loop:
for(i=0 ; i < 128 ; i = 1+1)
change to i= i+1
Also, in line:
temp = temp + store_elements[i][k];
remember the declaration store_elements[0:7][0:128] , so may be switch i and k ?
This isn't an answer really. Sorry, I don't have comment privilege yet.
Basically, what is the best practice for programmatically specifying fan-out in System Verilog?
module fanout
#(
parameter N = 4
)
(
input i,
output j [N-1:0]
);
always # (*) begin
for (int k = 0; k < N; k++) begin
j[k] = i;
end
end
endmodule
This allows the width of the output vector to be a parameter -- are there any issues with this? Will this synthesize okay?
You can use the replication operator. This allows you to replicate a value a fixed number of times and concatenate them.
Example (Note you need to change the output to a packed data type output [N-1:0] j:
module fanout
#(
parameter N = 4
)
(
input i,
output [N-1:0] j
);
assign j = {N{i}};
endmodule
Runnable example on EDA playground: http://www.edaplayground.com/x/9vn
You can use a default in an assignment pattern
module fanout
#(
parameter N = 4
)
(
input i,
output j[N]
);
assign j = '{default:i};
endmodule