adder in verilog - verilog

I am designing an adder in Verilog. It will have two inputs of size N and two outputs. The first output has a size of 2N and the second has a size of K.
This is what I have so far:
module adder(
out,
CCR,
inA,
inB
);
parameter N=8,CCR_size=8;
parameter M=2*N;
input [N-1:0] inA,inB;
output [M-1:0] out;
output [CCR_size-1:0] CCR;
reg [N:0] temp;
always #(inA or inB)
begin
temp = inA+inB;
CCR[0] = temp[N];
out[N-1:0]= temp[N-1:0];
out[M-1:N]= 'b0;
end
endmodule
Moved from comment:
However this didn't compile. I have errors in line
CCR[0],out[N-1:0] and out[M-1:N]
# Error: VCP2858 adder.v : (16, 20): CCR[0] is not a valid left-hand side of a procedural assignment.
# Error: VCP2858 adder.v : (17, 28): out[N-1:0] is not a valid left-hand side of a procedural assignment.
# Error: VCP2858 adder.v : (18, 20): out[M-1:N] is not a valid left-hand side of a procedural assignment.
What is wrong with the above code?

Register data types are used as variables in procedural blocks.
A register data type must be used when the signal is on the left-hand side of a procedural assignment.
Since the default type of ports is wire you get an error.
Changing your output ports to type reg should solve the problem.
output reg[M-1:0] out;
output reg[CCR_size-1:0] CCR;

Including the answer from #damage declaring the outputs as reg types, you also have CCR defined as 8 bits wide and then only assign the LSB.
The Bit growth from an Adder is 1 bit over the largest input.
I would implement as:
module adder(
parameter N =8,
parameter CCR_size=8
)(
input [N-1:0] inA,
input [N-1:0] inB,
output [2*N-1:0] out,
output reg [CCR_size-1:0] CCR,
);
reg [n:0] sum;
always #* begin
{CCR, sum} = inA + inB;
end
assign out = sum; //Will Zero pad
endmodule

Related

Why is this line getting the error : Expecting a left parenthesis ( '(' ) [12.1.2][7.1(IEEE)]?

I have a Verilog code for a simple multiplier as shown below, which takes two 32-b inputs which are split into two (16-b MSB and 16-b LSB) and multiplied:
parameter WordLen1 = 32, WordLen2 = 16;
output [WordLen2-1:0] M;
input clk;
input signed [WordLen1-1:0] X, W1;
reg signed [WordLen1-1 :0] X_reg, W1_reg, M;
wire signed [WordLen2-1:0] mul1, mul2, M_out;
assign mul1 = X_reg[31:16] * W1_reg[31:16]; <--- 16-b MSB
assign mul2 = X_reg[15:0] * W1_reg[15:0]; <--- 16-b LSB
assign M_out = mul1 + mul2;
always#(posedge clk)
begin
X_reg <= X;
W1_reg <= W1;
M <= M_out;
end
endmodule
The testbench for the code is below:
Note : The inputs are read from two external text files having 32-b values each.
module testbench;
reg clk;
parameter WL1 = 32, WL2 = 16;
reg [WL1-1:0] Xinarray [0:1]; // define memory arrays to hold inputs
reg [WL1-1:0] W1inarray [0:1];
logic signed [WL1-1:0] X,W1; <------ Error : Expecting a left parenthesis
endmodule
I am getting the following error in my test bench:
logic signed [WL1-1:0] X,W1;
|
ncvlog: *E,EXPLPA (../src/mult_hidden_tb.v,9|11): expecting a left parenthesis ('(') [12.1.2][7.1(IEEE)].
logic signed [WL1-1:0] X,W1;
|
ncvlog: *E,EXPLPA (../src/mult_hidden_tb.v,9|17): expecting a left parenthesis ('(') [12.1.2][7.1(IEEE)].
logic signed [WL1-1:0] X,W1;
|
ncvlog: *E,EXPLPA (../src/mult_hidden_tb.v,9|24): expecting a left parenthesis ('(') [12.1.2][7.1(IEEE)].
logic signed [WL1-1:0] X,W1;
|
ncvlog: *E,EXPLPA (../src/mult_hidden_tb.v,9|27): expecting a left parenthesis ('(') [12.1.2][7.1(IEEE)].
I'm not sure what I'm doing wrong.
You need to check ncverilog tool compile the code as system verilog code, not as verilog.
"logic" data type is defined in system verilog.
But in Verilog, "logic" is not defined.
In Verilog, you can use "wire" or "reg".
So if you want to compile the code as verilog, "logic" must changed into "reg" or "wire".
But then the variable cannot be used in "always"(or "initial") and "assign" together.
In case of input port(you defined X and W1 as input at your top module), you may use "reg" used at "initial" or "always" block.

Why am I getting the error : part select cannot be applied to scalar in my testbench?

I have designed a multiplier circuit that has two 32-b inputs, that would be split into two 16-b values and multiplied separately after which the results will be added together. Here is a part of the logic:
parameter WordLen1 = 32, WordLen2 = 16;
output [WordLen2-1:0] M;
input clk;
input signed [WordLen1-1:0] X, W1;
reg signed [WordLen1-1 :0] X_reg, W1_reg, M;
wire signed [WordLen2-1:0] mul1, mul2, M_out;
assign mul1 = X_reg[31:16] * W1_reg[31:16];
assign mul2 = X_reg[15:0] * W1_reg[15:0];
assign M_out = mul1 + mul2;
The test bench of the code is as follows:
module testbench;
reg clk;
parameter WL1 = 32, WL2 = 16;
reg [WL1-1:0] Xinarray [0:1]; // define memory arrays to hold inputs
reg [WL1-1:0] W1inarray [0:1];
wire [WL2-1:0] M;
integer i;
mult_hidden uut(M,clk,X,W1);
initial begin
$readmemb("input.txt", Xinarray); // read values into arrays from files
$readmemb("weight1.txt", W1inarray);
$display("Starting...");
for (i=0; i<=1; i=i+1) // loop through all values in the memories
begin
X[31:0] = Xinarray[i]; // set the inputs from the memory arrays
W1[31:0] = W1inarray[i];
$display("...Done");
$finish;
end
end
always #1 clk = !clk;
endmodule
The input files have 32-b binary numbers each. On compiling the code, I am getting the following error messages :
X[31:0] = Xinarray[i]; // set the inputs from the memory arrays
|
ncvlog: *E,WANOTL (../src/mult_hidden_tb.v,21|1): A net is not a legal lvalue in this context [9.3.1(IEEE)].
X[31:0] = Xinarray[i]; // set the inputs from the memory arrays
|
ncvlog: *E,NOPSOS (../src/mult_hidden_tb.v,21|1): Part-select operator cannot be applied to scalar [4.2.1(IEEE)].
W1[31:0] = W1inarray[i];
|
ncvlog: *E,WANOTL (../src/mult_hidden_tb.v,22|2): A net is not a legal lvalue in this context [9.3.1(IEEE)].
W1[31:0] = W1inarray[i];
|
ncvlog: *E,NOPSOS (../src/mult_hidden_tb.v,22|2): Part-select operator cannot be applied to scalar [4.2.1(IEEE)].
make: *** [mult_hidden] Error 1
How do I need to modify my testbench so that the input text files are read and the 32-b inputs are split into 16-b values each for the multiplication to happen?
You need to explicitly declare the signals in the testbench.
Verilog implicitly declares X as a 1-bit net (like a wire). But, you need it to be a different type and bit width. The same is true for W1.
Adding this line to your testbench clears up all the compile error messages:
logic signed [WL1-1:0] X, W1;
Unlike wire, logic allows the procedural assignments (in the initial block).
Place this line at the top of your testbench. For example:
module testbench;
reg clk;
parameter WL1 = 32, WL2 = 16;
reg [WL1-1:0] Xinarray [0:1]; // define memory arrays to hold inputs
reg [WL1-1:0] W1inarray [0:1];
logic signed [WL1-1:0] X, W1; // <------- Here
There are a couple problems right off the bat:
In your module, you're not assigning your input X and W1 to the X_reg and W1_reg registers.
You haven't declared your X and W1 variables in your testbench. They're inferred as 1 bit wires which can't be assigned like you're trying to do.
This is stylistic but your variable names obscure meaning. Consider renaming them to make understanding your code easier both for yourself and others.

How to write to "wire" and passing parameters to arrays of instances in Verilog

I have the following code:
module X;
wire [11:0] mga [0:15];
// other code omitted here for clarity
reg [11:0] globalStartAddresses [0:15];
reg [11:0] globalEndAddresses [0:15];
localMMU mmu[0:15](clock, globalStartAddresses, globalEndAddresses, mrw, mdi, mdo, mga);
task dispatcher;
// parameters
output reg dataReady;
input readWrite;
input [7:0] dataIn;
output reg [7:0] dataOut;
input [11:0] globalAddress;
// local variables
integer x, selected;
begin
for(x=0; x<16; x=x+1) begin
if(globalAddress >= globalStartAddresses[x] && globalAddress <= globalEndAddresses[x]) selected=x;
end
mrw[selected]=readWrite;
mdi[selected]=dataIn;
assign mga[selected]=globalAddress;
if(readWrite==1)
wait(mdo[selected]!=0);
else
wait(mdo[selected]!=dataIn);
dataOut=mdo[selected];
end
endtask
endmodule
I get 2 errors in the code:
In the array instance declaration of "localMMU", it states that "globalStartAddress[ ] should be present", but I have declared it just above as is evident.
In the assign statement inside the task, it states that only variables are allowed on LHS.
(I am using VeritakWin 3.84F) Please tell me how can I rectify these 2 problems. Thanks.
globalStartAddresses and globalEndAddresses are both of type array but array can not be passed directly between two modules. You must flatten the array into a vector and then pass it to a module. The problem is answered here :
How to pass array structure between two verilog modules
Left hand side of procedural continuous assignment can not be of type wire while in continuous assignment, left hand side must be just of type wire. As a solution, change mga type to reg. The same problem answered here:
Continuous assignment verilog

How can i make my verilog shifter more general?

Here i have a shifter but as of rite now it only works for up to 3 bits. I've been looking and i can't find out how to make it work for up to 8 bits.
module shifter(a,b,out);
input [7:0] a, b;
output [7:0] out;
wire [7:0] out1, out2, out3;
mux_8b_2to1 first(a[7:0], {a[3:0],a[7:4]}, b[2], out1);
mux_8b_2to1 second(out1[7:0], {out1[5:0],out1[7:6]}, b[1], out2);
mux_8b_2to1 third(out2[7:0], {out2[6:0],out2[7]}, b[0], out);
endmodule
What you have is a Barrel Shifter. Two ways to make it more generic are make it a functional model (still synthesis-able) or structural model with a generate block. Both approaches follow IEEE Std 1364-2001 (aka Verilog-2001).
The functional generic approach for a barrel shifter only needs a down-shifter. The general function is out = {in,in} >> (WIDTH-shift) where leftover bits can be ignored. To protect for double-roll (i.e. shift > WIDTH ), use the mod operator on the shift (WIDTH-(shift%WIDTH)).
module barrel_shifter_functional #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
( input wire [WIDTH-1:0] in,
input wire [ CTRL-1:0] shift,
output wire [WIDTH-1:0] out );
assign out = {2{in}} >> (WIDTH-(shift%WIDTH));
endmodule
The structural generic approach for a barrel shifter needs a generate block. The for loop in the generate block will unravel at compile time, not run time like a for loop like in an always block. To keep it generic also have have the 2-to-1 mux have a parametrized width. FYI, you can use the generate block with functional code too, for example comment out the mux_2to1 instantiation and uncomment the assign statement below it. Learn more about the generate block by reading IEEE Std 1800-2012 ยง 27. Generate constructs.
module barrel_shifter_structeral #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
( input wire [WIDTH-1:0] in,
input wire [ CTRL-1:0] shift,
output wire [WIDTH-1:0] out );
wire [WIDTH-1:0] tmp [CTRL:0];
assign tmp[CTRL] = in;
assign out = tmp[0];
genvar i;
generate
for (i = 0; i < CTRL; i = i + 1) begin : mux
mux_2to1 #(.WIDTH(WIDTH)) g(
.in0(tmp[i+1]),
.in1({tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]}),
.sel(shift[i]),
.out(tmp[i]) );
// assign tmp[i] = shift[i] ? {tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]} : tmp[i+1];
end : mux
endgenerate
endmodule
module mux_2to1 #( parameter WIDTH=8 )
( input wire [WIDTH-1:0] in0, in1,
input wire sel,
output wire [WIDTH-1:0] out );
assign out = sel ? in1 : in0;
endmodule
Both examples are functionally equivalent and synthesize provided CTRL is less than or equal to the ceiling of log2(WIDTH). Synthesis will likely give different results. The generate method will exclusively use 2-to-1 muxes while the pure functional method will depend on the quality of the optimizer.
Working example # http://www.edaplayground.com/s/6/500
I've used the >> and << operators to generate a synthetizable design using ISEWebPack, as this:
module shifter(
input wire [7:0] a,
input wire [7:0] b,
input wire leftright, // 0=shift right, 1=shift left
output reg [7:0] out
);
always #* begin
if (leftright==0)
out = a>>b;
else
out = a<<b;
end
endmodule
This way, the symthesis tool will know that you want to implement a shifter and can use its own macros to best synthetize it:
Synthesizing Unit <shifter>.
Related source file is "shifter.v".
Found 8-bit shifter logical right for signal <out$shift0002> created at line 30.
Found 8-bit shifter logical left for signal <out$shift0003> created at line 32.

Two's complement in verilog

I've been trying to build a module which returns the two's complement representation of the (3-bit) input (first bit being the sign). I think that the following code is correct conceptually, but I am probably missing something about it's structure: when I try to compile, I get the following errors:
(vlog-2110) Illegal reference to net "f_o".
(vlog-2110) Illegal reference to net "f_o".
(vlog-2110) Illegal reference to net "f_o".
Searching for that error showed it is usually seen when using a variable as input and output at the same time, but that's not my case. Could you point where the error is?
module ca2 (a_i,f_o);
input [2:0] a_i;
output [2:0] f_o;
always #(a_i[2:0] or f_o[2:0])
begin
if (a_i[2] == 1)
begin
f_o[2] = a_i[2];
f_o[1:0] = (~a_i[1:0] + 'b1);
end
else
begin
f_o = a_i;
end
end
endmodule
In Verilog, undeclared identifiers are considered implicit wire declarations in most circumstances. Since f_o has not been declared the compiler considers it a wire, not a variable. This causes the compiler to complain about all the assignments.
// What was typed
module ca2 (a_i,f_o);
input [2:0] a_i;
output [2:0] f_o;
// What the compiler implicitly declares
wire [2:0] a_i;
wire [2:0] f_o;
To fix it you can declare the variable or declare both the port and the variable.
module ca2 (a_i,f_o);
input [2:0] a_i;
output [2:0] f_o;
reg [2:0] f_o;
module ca2 (a_i,f_o);
input [2:0] a_i;
output reg [2:0] f_o;
f_o needs to be declared as a reg. output reg [2:0] f_o.
Also I am not sure what you are calculating, that is not a standard twos complement.
module ca2 (
input [2:0] a_i,
output [2:0] twos_comp,
output [2:0] also_twos_comp
);
assign twos_comp = ~a_i + 1'b1;
assign also_twos_comp = -a_i ;
endmodule
You may be dealing with an encoded input, but twos_complement is to negate the number I would expect the sign bit (MSB) to change. Although we refer to it as a sign bit it also contains information about the value and therefore can not just be stripped off and leave the number unchanged.
The first solution -> In sequential circuits, the output must be in the form of a reg.
and Next we need to know that in two's complement we start from bit zero to get to the end so the condition is incorrect.
If the zero bit is one, then the zero bit is unchanged and the rest of the bits change to not.
module ca2 (input [2:0] a_i,output reg [2:0] f_o);
always #(a_i[2:0] or f_o[2:0]) begin
if (a_i[0] == 1'b1) begin
f_o[0] = a_i[0];
f_o[2:1] = (~a_i[2:1]);
end
else
if(a_i[1]==1'b1) begin
f_o[1:0] = a_i[1:0];
f_o[2] = (~a_i[2]);
end
else
if(a_i[2] == 1'b1) begin
f_o = a_i ;
end
end
endmodule
The second solution -> In binary numbers, if we subtract the number from zero, we get two's complement .
module ca2 (input [2:0] a_i,output reg [2:0] f_o);
always #(a_i[2:0] or f_o[2:0]) begin
f_o = 3'b000 - a_i ;
end
endmodule
The third solution -> all bits change to not and Finally, they are added to the number one (3'b000 = 3'b0)
module ca2 (input [2:0] a_i,output reg [2:0] f_o);
reg [2:0] finish ;
always #(a_i[2:0] or f_o[2:0]) begin
finish = (~a_i);
f_o = finish + 3'b001 ;
end
endmodule

Resources