dynamic n-bit modules in verilog - verilog

I am wondering if it is possible in verilog to create an n-bit carry lookahead adder. With some help from the comments I've been able to come this far
module nbit_lookahead(x, y, cin, cout, s);
parameter n = 1;
integer i;
integer j;
input wire [n:0] x, y, cin;
output wire [n:0] cout, s;
wire [n:0] g, p;
reg cpp, gp;
generate
cpp = 1; // ERROR HERE -- Line 25
gpp = 1;
for(i = 0; i < n; i=i+1) begin : outer_loop
assign p[i] = x[i] | y[i];
assign g[i] = x[i] & y[i];
assign s[i] = cin[i]^x[i]^y[i];
for(j = i - 1; j >= 0; j=j-1) begin : inner_loop
cpp &= (cin[j] & p[j] & p[i]); // ERROR HERE -- Line 32
gp &= (g[j] & p[i]) & gp;
end
assign cout[n] = cpp | gp | (x[i] & y[i]);
end
endgenerate
endmodule
The challenge I'm having now is how to assign cpp and gp. I keep getting errors:
Error (10170): Verilog HDL syntax error at fourbit_lookahead.v(25) near text: "="; expecting ".", or "(". Check for and fix any syntax errors that appear immediately before or at the specified keyword.
Error (10170): Verilog HDL syntax error at fourbit_lookahead.v(32) near text: "&"; expecting ".", or "(". Check for and fix any syntax errors that appear immediately before or at the specified keyword.

I'm pretty rusty, but mixing wires and regs looks wrong to me in the for loop. The first thing I would try here is to make cpp and gpp bit vectors, so that everything is parallel. That way you don't have any reassignments in the inner loop. In generate, your have cpp[0]=1'b1, and gpp[0]=1'b1, then in the inner loop, assign cpp[i+1] and gpp[i+1] to your value. It also looks wrong to be setting cout[n] inside every iteration of the loop. You should be setting cout[i] based on cpp[i] and gpp[i].

Related

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

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.

Incomprehensible case expression with macros

In preparation for an exam, I want to go over some Verilog Code and I'm using https://www.jdoodle.com/ as a compiler. But for some reason the cases throw errors.
jdoodle.v:20: syntax error
jdoodle.v:20: error: Incomprehensible case expression.
jdoodle.v:21: syntax error
jdoodle.v:21: error: Incomprehensible case expression.
jdoodle.v:22: syntax error
jdoodle.v:22: error: Incomprehensible case expression.
jdoodle.v:23: syntax error
jdoodle.v:23: error: Incomprehensible case expression.
jdoodle.v:24: syntax error
jdoodle.v:24: error: Incomprehensible case expression.
module ALU (
input wire [2:0]OPCODE,
input wire [31:0]A,
B,
output reg [31:0]RESULT
);
`define ADD 0;
`define SUB 1;
`define MULT 2;
`define DIV 3;
`define MOD 4;
function [31:0] calculate (
input [31:0] A,
input [31:0] B,
input [2:0] OPCODE
);
case (OPCODE)
`ADD: calculate = A + B;
`SUB: calculate = A - B;
`MULT: calculate = A * B;
`DIV: calculate = A / B;
`MOD: calculate = A % B;
endcase
endfunction
always #(A or B or OPCODE)
RESULT = calculate(A, B, OPCODE);
endmodule
Would appreciate any kind of help.
Remove the semicolon at the end your defines.
You are defining ADD as 0;
Thus your code becomes:
case (OPCODE)
0; : calculate = A + B;
1; : calculate = A - B;
2; : calculate = A * B;
3; : calculate = A / B;
4; : calculate = A % B;
endcase

Syntax error: matching begin/end

module booth(num1,num2,prod);
input [22:0] num1,num2;
output [45:0] prod;
reg [22:0]num1_bar;
reg [46:0]sub_1;
reg [22:0]temp;
reg [22:0]result;
reg [1:0]sel;
reg [22:0]add;
reg [22:0]zeros;
assign temp = ~ num1;
assign num1_bar = temp + "00000000000000000000001";
assign sub_1 = {zeros[22:0], num2, "0"};
integer i;
always #* begin
for( i = 0; i < 22; i = i+1) begin
assign sel = sub_1[1:0];
if(sel == "10") begin
assign add = sub_1[46:24] + num1_bar;
assign sub_1 ={add[22],add,sub_1[23:1]};
end
elseif(sel == "01") begin
assign add = sub_1[46:24] + num1 ;
assign sub_1 ={add[22],add,sub_1[23:1]};
end
else begin
assign sub_1= {sub_1[46] ,sub_1[46:1]};
end
end
endmodule
I am trying to implement a floating point multiplier using carry look ahead adder and booth multiplier. After running the above code following errors has occurred only for the booth multiplier.
Please help me out.
ERRORS:
Summary Tue Apr 7 15:25:28 2015
Summary New
ERROR ProjectMgmt:806 - "D:/XILINX PROGRAM/bth/booth.v" Line 45. Syntax error near "begin".
ERROR ProjectMgmt:806 - "D:/XILINX PROGRAM/bth/booth.v" Line 49. Syntax error near "else".
ERROR ProjectMgmt:806 - "D:/XILINX PROGRAM/bth/booth.v" Line 54. Syntax error near "endmodule".
INFO ProjectMgmt:1845 - Analyzing Verilog file "D:/XILINX PROGRAM/bth/booth.v" into library work
You seem to have a confusion between VHDL and Verilog.
Vector constants in Verilog are in the form: Y'zXXXXXXX where Y is the number of bits of the vector, z is the base (b for binary, d for decimal, h for hexadecimal), and XXXX is the constante value in the specified base.
else if must separated
For example, the line:
if(sel == "10") begin
Must be rewritten as:
if(sel == 2'b10) begin
For large vectors, you can ommit the size specifier, and write the constant as this:
assign num1_bar = temp + 'b00000000000000000000001;
You are missing an end matching the begin of the always block.
(Once you have fixed that, you will see that there are other errors, too. See mcleod_ideafix's answer.)

Generate If Statements in Verilog

I'm trying to create a synthesizable, parametrized priority encoder in Verilog. Specifically, I want to find the least significant 1 in a vector and return a vector containing just that 1. For example:
IN[3:0] | OUT[4:0]
--------+---------
1010 | 00010
1111 | 00001
0100 | 00100
0000 | 10000 (special case)
So if the vectors are four bits wide, the code is:
if (in[0]==1'b1) least_one = 1;
else if (in[1]==1'b1) least_one = 2;
else if (in[2]==1'b1) least_one = 4;
else if (in[3]==1'b1) least_one = 8;
else out = 16; // special case in==0, set carry bit
I need a general, scalable way to do this because the input/output vector length is parametrized. My current code is:
module least_one_onehot
#(parameter ADDR_WIDTH=4)
(output reg [ADDR_WIDTH:0] least_one,
input [ADDR_WIDTH-1:0] in);
genvar i;
always #(in) begin
if (in[0]==1'b1) least_one = 1;
generate for (i=1; i<ADDR_WIDTH; i=i+1) begin : U
else if (in[i]==1'b1) least_one = 2**i;
end
endgenerate
else least_one = 2**ADDR_WIDTH;
end
endmodule
When I try to compile this, I receive the following errors:
file: least_one_onehot.v
generate for (i=1; i<ADDR_WIDTH; i=i+1) begin : U
|
ncvlog: *E,GIWSCP (least_one_onehot.v,10|8): Generated instantiation can only be valid within a module scope [12.1.3(IEEE 2001)].
else if (in[i]==1'b1) least_one = 2**i;
|
ncvlog: *E,NOTSTT (least_one_onehot.v,11|6): expecting a statement [9(IEEE)].
endgenerate
|
ncvlog: *E,GIWSCP (least_one_onehot.v,13|12): Generated instantiation can only be valid within a module scope [12.1.3(IEEE 2001)].
else least_one = 2**ADDR_WIDTH;
|
ncvlog: *E,NOTSTT (least_one_onehot.v,14|5): expecting a statement [9(IEEE)]
I've tried various arrangements of the generate, if, and always statements, all without success. Anyone know the proper syntax for this? Case-statement implementation or other alternatives would also be fine. Thanks.
I think you misunderstand how generate works. It isn't a text pre-processor that emits the code in between the generate/endgenerate pair with appropriate substitutions. You have to have complete syntactic entities withing the pair. I don't have access to a simulator right this minute but this might do the trick for you (totally untested)
genvar i;
generate
for (i = 1; i < ADDR_WIDTH; i = i + 1) begin : U
least_one[i] = in[i] & ~|in[i - 1:0];
end
endgenerate
least_one[0] = in[0];
least_one[ADDR_WIDTH] = ~|in;
Ordinarily Verilog would complain about the non-constant bit slice width but since it's within a generate loop it might work.
Failing something like the above you just test for the first set bit in a for-loop and then decode that result.
You do not need a generate block. You could use:
integer i;
reg found;
always #(in) begin
least_one = {(ADDR_WIDTH+1){1'b0}};
found = 1'b0;
for (i=0; i<ADDR_WIDTH; i=i+1) begin
if (in[i]==1'b1 && found==1'b0) begin
least_one[i] = 1'b1;
found = 1'b1;
end
end
least_one[ADDR_WIDTH] = (found==1'b0);
end
If you really want to use a generate block, then you need to assign each bit.
assign least_one[0] = in[0];
assign least_one[ADDR_WIDTH] = (in == {ADDR_WIDTH{1'b0}});
genvar i;
generate
for (i=1; i<ADDR_WIDTH; i=i+1) begin : U
assign least_one[i] = in[i] && (in[i - 1:0] == {i{1'b0}});
end
endgenerate
This simulates the way you want it to, but it is not synthesizable (you didn't specify if that was a requirement):
module least_one_onehot #(parameter ADDR_WIDTH=4) (
output reg [ADDR_WIDTH-1:0] least_one,
input [ADDR_WIDTH-1:0] in
);
always #* begin
least_one = '0;
for (int i=ADDR_WIDTH-1; i>=0; i--) begin
if (in[i]) least_one = 2**i;
end
end
endmodule
Note that it uses SystemVerilog constructs.
Personally, I like the following block of code for what you need:
assign out = {1'b1,in} & ((~{1'b1,in})+1);
You could try this (dropping the extra high bit for legibility), but I like to explicitly do the twos compliment to avoid any potential compatibility problems.
assign out = in & (-1*in);

Verilog: is it possible to do indexed instantiation?

I have a file, that is something similar to
module AB(A,B,Out);
input A,B;
output Out;
wire Out;
assign Out = A & B;
endmodule
I need to use N number of this calculation.
ie i have a=1001; b=0001, I need to do something like bitwise AND, and I have N bits.
I have used it as an instantiation:
op[0] = a[0] & b[0];
op[1] = a[1] & b[1];
op[2] = a[2] & b[2];
op[3] = a[3] & b[3];
op[4] = a[4] & b[4];
When I'm trying to do this with an index i, I have:
AB g(a[i],b[i],Op[i]) for i = 0 to N-1.
If I do this, it says AB is undeclared.
Is this impossible? If so, what is the alternative?
You've a few options:
Parameterise bus sizes in your module
Array of instances
generate statements
But to answer the question, it is possible to do arrays of instances. Here's what the syntax looks like for your AB module.
module testbench ();
localparam WIDTH = 4;
reg [WIDTH-1:0] a_in, b_in;
wire [WIDTH-1:0] out_a;
AB u0[WIDTH-1:0]
(
.A(a_in),
.B(b_in),
.Out(out_a)
);
initial begin
...
end
endmodule
Here, a_in[3], b_in[3] and out_a[3] are mapped to the ports of u0[3].
This is possible using the generate statement which supports an array of instances. This construct was introduced in the Verilog IEEE Std 1364-2001.
genvar i;
generate
for (i=0; i<4; i=i+1) begin
AB g (a[i], b[i], op[i]);
end
endgenerate

Resources