"Not a valid l-value" Error in Verilog - verilog

I am new to Verilog (and, to a lesser extent, programming) and am trying to create a program that finds the absolute value of a set of numbers and then calculates for a running average. The running average is 5 points wide, and goes across a data set that is about 40 numbers wide.
I am having trouble with the running average (lines 14-17 design, 24-28 test-bench) and am receiving the errors "o2/out is not a valid l-value in tb.avg." and "o2/out is declared here as a wire". How should I fix this?
Here is my design:
module absolute_value(i1,o1);
input signed [11:0] i1;
output signed [11:0] o1;
assign o1 = i1[11] ? -i1 : i1;
endmodule
module moving_average(k1,k2,k3,k3,k4,o2,out);
input k1, k2, k3, k4, k5;
output [11:0] o2;
output [11:0] out;
integer t;
always begin
assign o2 = (k1 + k2 + k3 + k4 + k5) / 5;
assign out = o2;
end
endmodule
And here is my test-bench:
module tb;
reg signed [11:0] i1;
wire signed [11:0] o1;
reg k1;
reg k2;
reg k3;
reg k4;
reg k5;
wire [11:0] o2;
wire [11:0] out;
absolute_value abs(i1,o1);
moving_average avg(k1,k2,k3,k4,k5,o2,out);
integer t;
initial begin
for (t = -10; t < 30; t = t + 1) begin
#1
i1 <= t;
$display("i1 = %d, o1 = %d", i1, o1);
assign k5 = k4 ? k4 : o1;
assign k4 = k3 ? k3 : o1;
assign k3 = k2 ? k2 : o1;
assign k2 = k1 ? k1 : o1;
assign k1 = o1;
$display("out = %d", out);
$moniter($time, "i1 = %d, o1 = %d, o2 = %d, out = %d k1 = %d, k2 = %d, k3 = %d, k4 = %d, k5 = %d", i1, o1, o2, out, k1, k2, k3, k4, k5);
end
end
endmodule
I'd bet that there are other errors in my program too, so any help is much appreciated.

As mentioned in the comments:
Remove the always and keep the output [11:0] out
or
Change to:
reg [11:0] o2;
reg [11:0] out;
always #( * )
begin
o2 = (k1 + k2 + k3 + k4 + k5) / 5;
out = o2;
end
Second error:
Your port uses k1, k2, k3, k3, k4 and is missing k5.
Thirdly: please don't use the port style from last century. I advise you to switch to the new format:
module moving_average(
input k1, k2, k3, k4, k5,
output signed [11:0] o2,out
);
Or for the second case: output signed reg [11:0] o2,out
Fourth: it is $monitor, not $moniter

Related

In Verilog, what is the pragma directive to inform a simulator / synthesizer to throw an error for undefined netlists? [duplicate]

I have to make a 64 Bit ALU that takes in A and B 64-bit inputs, a carry_in input and outputs a 64bit result along with a 1-bit carry_out. There is also a 5 bit function-select FS. Where FS[0] controls whether B is inverted or not (using a 2to1 mux.) F[1] does the same for the A. And FS[4:2] determines which operation (Adding, subtracting, logical operations, etc) using an 8to1 Mux. Below is the code for the ALU and Testbench.
I'm pretty sure my testbench is good and so is all the separate components for the ALU. I'm not too confident about my top-level where I instantiate and connect all the inputs/outputs. What is causing the high impedance in the waveform?
module ALU(A, B, FS, cin, cout, result);
input [63:0] A, B;
input [4:0] FS;
input cin;
output cout;
output [63:0] result;
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 1'b0, 1'b0, FS[4:2], result);
adder u6 (firstoutA, secoutB, cin, sum, cout);
firstmux u1 (A, !A, FS[1], firstoutA);
secmux u2 (B, !B, FS[0], secoutB);
Alu_shifter u5 (A, left, right);
endmodule
//--------------------------------------------------------------------------------//
//These are the two muxes to split into input and inverted input A,B
module firstmux(a, nota, firstS, firstoutA);
input [63:0] a, nota;
input firstS;
output reg [63:0] firstoutA;
always #(a or nota or firstS)
begin
case(firstS)
0 : firstoutA = a;
1 : firstoutA = nota;
default : firstoutA = 1'bx;
endcase
end
endmodule
//<><><><><><><>//
module secmux(b, notb, secS, secoutB);
input [63:0] b, notb;
input secS;
output reg [63:0] secoutB;
always #(b or notb or secS)
begin
case(secS)
0 : secoutB = b;
1 : secoutB = notb;
default : secoutB = 1'bx;
endcase
end
endmodule
//--------------------------------------------------------------------------------//
//This is the Shifter Blocks
module Alu_shifter (shiftA, right, left); //This shifter block shifts the A input once right or left
input [63:0] shiftA;
output [63:0] right;
output [63:0] left;
shift_right w1 ( //instantiate right shifter block
.a_R(shiftA),
.R(right)
);
shift_left w2 ( //instantiate left shifter block
.a_L(shiftA),
.L(left)
);
endmodule
////////><><><><><><><><><><><><><><><///////
module shift_right (a_R, R); // right shifter block
input [63:0] a_R;
output [63:0] R;
assign R = a_R >> 1; //shift A right once (shift in a 0)
endmodule
module shift_left (a_L, L); //left shifter block
input [63:0] a_L;
output [63:0] L;
assign L = a_L << 1; //shift A left once (shift in a 0)
endmodule
//End shifter blocks (3 total modules)
//----------------------------------------------------//////////////////////
//This is the Adder that Adds A, B and cin
module adder(addA, addB, nic, sum, cout);
input [63:0] addA, addB;
input nic;
output [63:0] sum;
output cout;
assign {cout, sum} = addA + addB + nic;
endmodule
//----------------------------------------------------//////////////////////
//This is the 8to1 Mux that decides which operation is put forward
module eight_one_mux(D0, D1, D2, D3, D4, D5, D6, D7, S, out);
input [63:0] D0, D1, D2, D3, D4, D5, D6, D7;
input [2:0] S;
output reg [63:0] out;
always #(D0 or D1 or D2 or D3 or D4 or D5 or D6 or D7 or S)
begin
case(S)
0 : out = D0; //And
1 : out = D1; //Or
2 : out = D2; //Adder
3 : out = D3; //xor
4 : out = D4; //lefter
5 : out = D5; //righter
6 : out = D6; //GND
7 : out = D7; //GND
default : out = 1'bx;
endcase
end
endmodule
////////////-------------------------------////////////////////////////////
module ALU_tb();
reg [63:0] A, B;
reg [4:0] FS;
reg cin;
wire cout;
wire [63:0] result;
ALU dut (
.A(A),
.B(B),
.FS(FS),
.cin(cin),
.cout(cout),
.result(result)
);
initial begin
A = 8'b11001100;
B = 8'b11001101;
FS = 5'b01101;
cin = 1;
end
always
#5 cin <= ~cin;
always begin
#5
A <= A + 1;
B <= B + 2;
#5;
end
initial begin
#100 $finish;
end
endmodule
```
Unexpected high impedance (z) values are typically the result of undriven signals, and that is the problem with your code.
adder u6 (firstoutA, secoutB, cin, sum, cout);
In the line above, you connect the 1-bit signal firstoutA to the 64-bit addA input port. This connects firstoutA to addA[0], leaving the other 63 bits undriven. Thus, addA[63:1] are all z.
firstoutA is a 1-bit signal because you did not explicitly declare it. Also, undeclared signals are assumed to be of type wire, which default to z.
It is good practice to declare all signals.
To find all undeclared signals, add this to the top of your code:
`default_nettype none
You should get compile errors like:
Error-[IND] Identifier not declared
Identifier 'firstoutA' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
Error-[IND] Identifier not declared
Identifier 'secoutB' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
First you need to define signals (wire) for connections between modules. For example, you have left and right as outputs of Alu_shifter module and they are connected to firstmux and secmux modules; however, they are not defined in your top module. You should add following signal definitions to your topmodule:
wire [63:0] left,right;
wire [63:0] firstoutA;
wire [63:0] secoutB;
wire [63:0] sum;
Also, eight_one_mux module takes eight 64-bit inputs. However, you set the last two of them as 1'b0. You should change them to 64'b0 as below.
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 64'b0, 64'b0, FS[4:2], result);
Finally, !A does not invert all bits of A (same for B). It applies a reduction operation and generates a 1-bit signal (and firstmux module expects a 64-bit signal in its second input port).

Verilog test bench for 4-bit adder with Carry Lookahead [duplicate]

This question already has answers here:
Can anyone help me to create a Verilog testbench?
(2 answers)
Closed 1 year ago.
I'm still honestly a bit unfamiliar with Verilog especially with test benches, considering I've only created a childishly simple project once. I'm not sure how to make a test bench for a Verilog file I've made and so I can't test if it works. Here's my code:
`timescale 1ns/1ps
module adder_4bit_cla(sum, Cout, A, B, S);
input [3:0] A, B;
input S;
output [3:0] sum;
output Cout;
wire P0, G0, P1, G1, P3, G3;
wire C4, C3, C2, C1;
assign
P0 = A[0] ^ B[0],
P1 = A[1] ^ B[1],
P2 = A[2] ^ B[2],
P3 = A[3] ^ B[3];
assign
G0 = A[0] & B[0],
G1 = A[1] & B[1],
G2 = A[2] & B[2],
G3 = A[3] & B[3];
assign
C1 = G0 | (P0 & S),
C2 = G1 | (P1 & G0) | (P1 & P0 & S),
C3 = G2 | (P2 & G1) | (P2 & P1 & G0) | (P2 & P1 & P0 & S),
C4 = G3 | (P3 & G2) | (P3 & P2 & G1) | (P3 & P2 & P1 & G0) | (P3 & P2 & P1 & P0 & S);
assign
sum[0] = P0 ^ S,
sum[1] = P1 ^ C1,
sum[2] = P2 ^ C2,
sum[3] = P3 ^ C3;
assign Cout = C4;
endmodule
Honestly, what I really need to do is a 4-bit adder-subtractor using carry lookahead, but I have no idea how to implement a carry lookahead to begin with so here I am. If anyone could help me that would be really great :<
Edit: I have calmed down and I can finally pinpoint the exact problem: the values of A and B for the test bench. While I could brute force it, how can I make use of loops to increment A and B so that it would be like this:
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
While also updating M?
Use the following to improve your testbench.
`timescale 1ns / 1ps
module adder_4bit_cla_tb();
// inputs - keep them having reg as the data type
reg [3:0] A, B;
reg S;
// outputs - keep them having wire as the data type
wire [3:0] sum;
wire Cout;
adder_4bit_cla adder_4bit_cla_inst
(
.sum(sum), .Cout(Cout), .A(A), .B(B), .S(S)
);
initial begin
A = 4'd1; B = 4'd2; S = 1'd1;
#10 A = 4'd2; B = 4'd5; S = 1'd0;
#10 A = 4'd5; B = 4'd6; S = 1'd0;
#50 $stop;
end
endmodule
Waveform results
Inputs can be fed using for loops as follows.
`timescale 1ns / 1ps
module adder_4bit_cla_tb();
// inputs - keep them having reg as the data type
reg [3:0] A, B;
reg S;
// outputs - keep them having wire as the data type
wire [3:0] sum;
wire Cout;
reg [3:0] i;
adder_4bit_cla adder_4bit_cla_inst
(
.sum(sum), .Cout(Cout), .A(A), .B(B), .S(S)
);
initial begin
for(i = 4'd0; i < 4'd15; i = i + 4'd1) begin
A = i; B = i; S = 1'b0;
#10;
end
#200 $stop;
end
endmodule
Waveform Results

Pipelining a verilog module consisting 10 components connected in series

I am trying to pipeline a module which consists of 5 multipliers and 5 adders connected in series. The module is a polynomial calculator. Without pipelining the module is working perfectly so far.
multipliers [31:0] m0,m1,m2,m3,m4; // separate module
adders [31:0] a0,a1,a2,a3,a4; // separate module
user_input [31:0] input; // register
constants [31:0] c0,c1,c2,c3,c4; // registers
pipeliners [31:0] p0,p1,p3,p4,p4; // pipelining resisters
wires [31:0] w0,w1,w2,w3,w4; // wires
Without pipelining the structure looks like following,
[input]*[c0] => w0 => [w0]+[c1] => w1 => [w1]*[input] => w2 => [w2]+[c2] => w3 ... //goes on like this
As all of them are connected in series, the critical path consists of 10 components.
My implemented pipelining idea is following,
[input]*[c0] => w0 => p0 => [p0]+[c1] => w1 => p1 => [p1]*[input] => w2=> p2 => [p2]+[c2] => w3 ... //goes on like this
I have an error, "cannot be driven by primitives or continuous assignment."It is due to p0,p1,p3 ... registers. Converting them into wire solves the error but then they are not registers anymore. I am using iverilog as compiler.
My question is, how can I do the pipelining so that I get the output using least possible clock cycles and resolve the error as well?
******* Edited version with code *******
`timescale 1ns / 1ps
module poly (
clk,
q,
result
);
input clk;
input [31:0] q; //user input
output [31:0] result;
reg [31:0] c,c0,c1,c2,c3,c4;
reg [31:0] p, p0, p1, p2, p3, p4, p5, p6,p7,p8,p9,p10,p11,p12;
always #(q)
if (q>=32'h08000000 && q<32'h0A000000) begin
c <= 32'h058B90C0;
c0 <= 32'h74599F60;
c1 <= 32'h79481740;
c2 <= 32'h445B7440;
c3 <= 32'h5AF892E0;
c4 <= 32'h9E2C2258;
end else if (q>=32'h0A000000 && q<32'h0C000000)
begin
c <= 32'h258B90C0;
c0 <= 32'hFB942240;
c1 <= 32'h21558EC0;
c2 <= 32'h5D882000;
c3 <= 32'h75F846E8;
c4 <= 32'hF48F5786;
end
wire [31:0] x0,x1,x2,x3,x4;
wire [31:0] y0,y1,y2,y3,y4;
multiplier m4 (.i_multiplicand(q),.i_multiplier(c4),.o_result(x4));
assign = x4;
adder a4 (.a(p0),.b(c3),.c(y4));
assign p1 = y4;
assign p2 = q;
multiplier m3 (.i_multiplicand(p2),.i_multiplier(p1),.o_result(x3));
assign p3 = x3;
adder a3 (.a(p3),.b(c2),.c(y3));
assign p4 = y3;
assign p5 = q;
multiplier m2 (.i_multiplicand(p5),.i_multiplier(p4),.o_result(x2));
assign p6 = x2;
adder a2 (.a(p6),.b(c1),.c(y2));
assign p7 = y2;
assign p8 = q;
multiplier m1 (.i_multiplicand(p8),.i_multiplier(p7),.o_result(x1));
assign p9 = x1;
adder a1 (.a(p9),.b(c0),.c(y1));
assign p10 = y1;
assign p11 = q;
adder a0 (.a(p10),.b(p11),.c(y0));
assign p12 = y0;
multiplier m0 (.i_multiplicand(p12),.i_multiplier(c),.o_result(x0));
assign result = x0;
endmodule
As Morgan already stated you get only registers if you have a reg and a clock.
always #(posedge clk)
begin
p1 <= y4;
p2 <= q;
// etc.
end
Which if you think about it is rather obvious as this is a register:
Which as you can see has as input a signal and a clock.

Structural 2-1 mux fails during elaboration

So I'm trying to write a simple 2-1 mux in Verilog using logic gates and I'm not sure what I'm doing wrong. The code for the mux is as follows:
module MUX_2_1 (i0 ,i1, sel ,o);
input [31:0] i0, i1;
input sel;
output [31:0] o;
wire [31:0] a, b;
and #(8) and1(a, {32{sel}}, i0);
and #(8) and2(b, {32{~sel}}, i1);
or #(8) or1(o, a, b);
endmodule
The module compiles ok, but when I elaborate my test bench I get several errors (one for each gate) that take the form of
gate (and1) has illegal output specification.
I understand how to make write the same mux using data flow, but I'm curious what the actual problem is here. I can't find anything online that suggests that the above code shouldn't work.
For reference, here is my test bench code:
module test_bench;
reg [31:0] I0, I1, I2, I3, I4, I5, I6, I7;
reg [2:0] SEL;
wire [31:0] O8;
//MUX_8_1 mux(I0, I1, I2, I3, I4, I5, I6, I7, SEL, O8);
MUX_2_1 mux(I0, I1, SEL[0], O8);
initial
begin
I0 = 1;
I1 = 2;
I2 = 4;
I3 = 8;
I4 = 16;
I5 = 32;
I6 = 64;
I7 = 128;
SEL = 3'b000;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
SEL = 3'b001;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
SEL = 3'b010;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
SEL = 3'b011;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
SEL = 3'b111;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
SEL = 3'b110;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
SEL = 3'b100;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
SEL = 3'b101;
#50 $display("SEL = %u, O8 = %u\n", SEL, O8);
end
endmodule
What you have done is that you have overridden the parameter of the module (primitive in your case).
To assign the delay of the gate, it is just #<delay_value> used. So you instantiation may look like this:
and #8 and1...;
and #8 and2...;
or #8 or1...;
Paremeter is a very different thing altogether.
A parameter is defined by Verilog as a constant value declared within
the module structure. The value can be used to define a set of
attributes for the module which can characterize its behavior as well
as its physical representation
Suppose you want to make a verilog code, robust for the number of nets or configurable, then you can use the parameters.
For example :
module x (a, b);
input [SIZE-1:0] a;
output [SIZE-1:0] b;
parameter SIZE = 4;
// Your actual Verilog code
endmodule
So this code, by default generate a[3:0], b[3:0]. But since, it is parameterised by the SIZE value. One can override the SIZE value to get different number of nets.
And to override the parameter value, you can use #(<Paramter 1 Value>, <Parameter 2 Value>, ..., <Parameter n Value>).
So if you instantiate module x, with SIZE = 6, then you should write like below:
x x1 #(6) (a, b); // Here SIZE = 6, and so 1[5:0], b[5:0]
Hope you have understood the difference.

Verilog simulation gives x as output

I am trying to simulate the following circuit using veriwell. However, simulation results is giving me the value of each net as x. Since the circuit does not have any backward loop, I guess every net should have either 1 or 0 signals.
module dff (CK,Q,D);
input CK,D;
output Q;
wire NM,NCK;
wire NQ,M;
nmos N7 (M,D,NCK);
not P3 (NM,M);
nmos N9 (NQ,NM,CK);
not P5 (Q,NQ);
not P1 (NCK,CK);
endmodule
module s27(clk, in1, in2, GO, HO, AO, BO, CO, DO, EO, FO, a1, a2, a3, a4, o1, o2);
input clk, in1, in2;
output GO, HO, AO, BO, CO, DO, EO, FO, a1, a2, a3, a4, o1, o2;
wire AO, BO, CO, DO, EO, FO;
wire a1, a2, a3, a4;
wire o1, o2;
dff A(clk,AO,in1);
dff B(clk,BO,in2);
dff C(clk,CO,o1);
dff D(clk,DO,a1);
dff E(clk,EO,a2);
dff F(clk,FO,o2);
dff G(clk,GO,a3);
dff H(clk,HO,a4);
and AND2_1 (a1, AO, CO);
and AND2_2 (a2, CO, BO);
and AND2_3 (a3, AO, FO);
and AND2_4 (a4, FO, BO);
or OR2_1(o1, AO, BO);
or OR2_2(o2, DO, EO);
endmodule
I am using the following testbench (generated using a script):
`timescale 1ns/1ps
module testbench;
parameter sOutFileName = "beSimOut.txt";
parameter nVectorWidth = 3;
parameter nVectorSpace = 1000;
parameter nSimCycle = 10;
/* simulation memory */
reg [nVectorWidth - 1:0] mSimMemory [nVectorSpace - 1:0];
/* simulation vector */
reg [nVectorWidth - 1:0] vSimVector;
/* bench variables */
integer nOutFile, nIndex;
/* connection variable declarations */
wire clk, in1, in2, G0, H0, A0, B0, C0, D0, E0, F0, a1, a2, a3, a4, o1, o2;
/* drive inputs */
assign clk = vSimVector[2];
assign in1 = vSimVector[1];
assign in2 = vSimVector[0];
/* simulation memory population routine */
task populateSimulationMemory;
begin
for (nIndex = 0; nIndex < nVectorSpace; nIndex = nIndex + 1)
mSimMemory[nIndex] = { $random };
end
endtask
/* simulation */
initial
begin
/* start monitoring */
$monitor($time, ": clk = %b, in1 = %b, in2 = %b, GO = %b, HO = %b, AO = %b, BO = %b, CO = %b, DO = %b, EO = %b, FO = %b, a1 = %b, a2 = %b, a3 = %b, a4 = %b, o1 = %b, o2 = %b", clk, in1, in2, GO, HO, AO, BO, CO, DO, EO, FO, a1, a2, a3, a4, o1, o2);
/* populate simulation memory */
populateSimulationMemory;
/* open dump file */
nOutFile = $fopen(sOutFileName);
if (nOutFile == 0)
begin
$display("Can't open %s file for dumping. Exiting ...", sOutFileName);
$finish;
end
/* simulate inputs */
for (nIndex = 0; nIndex < nVectorSpace; nIndex = nIndex + 1)
#nSimCycle vSimVector = mSimMemory[nIndex];
#1 $fclose(nOutFile);
nOutFile = 0;
$finish;
end
/* instantiation */
s27 inst (.clk(clk), .in1(in1), .in2(in2), .GO(GO), .HO(HO), .AO(AO), .BO(BO), .CO(CO), .DO(DO), .EO(EO), .FO(FO), .a1(a1), .a2(a2), .a3(a3), .a4(a4), .o1(o1), .o2(o2));
/* dump */
always #(clk or in1 or in2 or GO or HO or AO or BO or CO or DO or EO or FO or a1 or a2 or a3 or a4 or o1 or o2)
if (nOutFile != 0)
$fdisplay(nOutFile, $time, ": clk = %b, in1 = %b, in2 = %b, GO = %b, HO = %b, AO = %b, BO = %b, CO = %b, DO = %b, EO = %b, FO = %b, a1 = %b, a2 = %b, a3 = %b, a4 = %b, o1 = %b, o2 = %b", clk, in1, in2, GO, HO, AO, BO, CO, DO, EO, FO, a1, a2, a3, a4, o1, o2);
endmodule
Any ideas on why I am not getting the correct output?
Thanks in advance.
The dff is not modeled correctly. With the current dff, M will float (high-Z) when CK is high.
dff should look like this:
not N1 (NCK,CK);
cmos C1 (M,D,NCK,CK);
cmos C2 (M,NNM,CK,NCK);
not N2 (NM,M);
not N3 (NNM,NM);
cmos C3 (NNQ,NNM,CK,NCK);
cmos C4 (NNQ,Q,NCK,CK);
not N3 (NQ,NNQ);
not N4 (Q,NQ);
or as nand gates:
nand DN1 (NM,D,CK);
nand DN2 (M,NM,CK);
nand DN3 (Q,NQ,NM);
nand ND4 (QN,Q,M);
or as behavioral:
always #(posedge CK)
Q <= D;
When I try to compile your code with the VCS simulator, I get a compilation error:
Identifier 'GO' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
In your testbench module, you declare a wire G0 (the number zero), but then you use GO (capital letter O). You should change the zeroes to letter O's.
I don't think this will completely solve your problem, but this was too complicated to fit in a Comment.

Resources