SystemVerilog Error: variable written by continuous and procedural assignments - verilog

I want to create a test bench for my ALU circuit. When i compile it, i get some errors:
module ALU_TB();
logic [7:0] A, B, w;
logic [2:0] s, n;
logic co, ci, si;
wire ov, neg, zero, gt, eq;
ALU alu8(A, B, s, si, ci, n, co, ov, zero, neg, gt, eq, w);
assign A = 8'b10000000, B = 8'b0, s = 3'b0, ci = 1'b0, si = 1'b0, n = 3'b011;
initial begin
integer i;
for (i = 0; i < 7; i = i + 1) begin
s = s + 3'b001;
repeat(8) #59 A = {A[0], A[7:1]};
#59 B = 8'b10000000; A = 8'b01011010;
repeat(8) #59 B = {~B[0], B[7:1]};
end
end
endmodule
These are the compile errors for lines 12, 13, 14, 14, 15:
** Error: (vlog-3838) variable 's' written by continuous and procedural assignments.
** Error: (vlog-3838) variable'A' written by continuous and procedural assignments.
** Error: (vlog-3838) Variable 'B' written by continuous and procedural assignments.
** Error: (vlog-3838) Variable 'A' written by continuous and procedural assignments.
** Error: (vlog-3838) Variable 'B' written by continuous and procedural assignments.
What these errors mean?

You are using 'A', 'B' , 'S' in continuous assignment (assign) and also in procedural block(initial). A variable cannot be used in continuous and procedural assignment at the same time.
By the way, logic of your code is not correct. For example when you assign B=0, it means B will be 0 all the time (That's why it is called continuous assignment!). But you are changing B in initial block!
It seems that you wanted to initialize signals using assign which is totally wrong. Initial blocks are used for this purpose.
And finally, put the declaration of variable 'i' outside of initial block.
integer i;
initial begin
A = 8'b10000000;
B = 8'b0;
s = 3'b0;
ci = 1'b0;
si = 1'b0;
n = 3'b011;
#1 for (i = 0; i < 7; i = i + 1) begin
// your code here
end
end

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.

How do I fix Syntax error near "=" in casez statement?

For a lab in a digital design course, I am designing a partial ALU. I have defined its operations and am required to use a casez statement to govern which function (either addition of a & b w/ overflow checking, bitwise inversion of b, a AND b, and a OR b) is selected by the four 2-bit combos of sel:
module eightbit_palu(input wire[7:0] a, b,
input wire[1:0] sel,
output wire[7:0] f,
output wire ovf);
wire[7:0] sum, bitInv, bitAnd, bitOr;
wire sumOvf;
assign sum = a + b;
assign sumOvf = (a+b>127)||(a+b<-128) ? 1 : 0;
assign bitInv = !b;
assign bitAnd = a & b;
assign bitOr = a | b;
always #(a or b or sel) begin
casez(sel)
2'b00: f = sum; ovf = sumOvf;
2'b01: f = bitInv; ovf = 0;
2'b10: f = bitAnd; ovf = 0;
2'b11: f = bitOr; ovf = 0;
endcase
end
endmodule
I have embedded the casez statement within an always #, but I am getting a syntax error that I believe might be due to the outputs being wires. I am not sure how to work around that seemingly simple issue.
I tried turning the variables declared before the assign statements into regs, but then there was a problem converting them to wires. I would really appreciate some insight as to how Verilog works — unfortunately my professor is teaching in SystemVerilog, yet our labs are required to be in Verilog.
Yes, you should change your output wires to reg since you are making procedural assignments to them (inside an always block).
The other error is that you need to add begin/end keywords around multiple statements in each case item. Here is code that compiles cleanly for me:
module eightbit_palu(input wire[7:0] a, b,
input wire[1:0] sel,
output reg [7:0] f,
output reg ovf);
wire[7:0] sum, bitInv, bitAnd, bitOr;
wire sumOvf;
assign sum = a + b;
assign sumOvf = (a+b>127)||(a+b<-128) ? 1 : 0;
assign bitInv = !b;
assign bitAnd = a & b;
assign bitOr = a | b;
always #(a or b or sel) begin
casez(sel)
2'b00: begin f = sum; ovf = sumOvf; end
2'b01: begin f = bitInv; ovf = 0; end
2'b10: begin f = bitAnd; ovf = 0; end
2'b11: begin f = bitOr; ovf = 0; end
endcase
end
endmodule
You also have a problem with this line:
always #(a or b or sel) begin
A sensitivity list should include only signals on the RHS of assignments within the block. Your list incorrectly includes a and b, and it misses others like sum. You should use an implicit sensitivity list which automatically includes the appropriate signals.
always #*

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.

Verilog Case Block Concatenation Syntax

I can't seem to figure out what the proper syntax is to do {c_out, result} = {a + b + c_in} within a case block. The c_out doesn't work in my test bench, if I add 32'hffffffff + 1'b1 I get c_out = 0, result = 32'b0. What's the correct way to do this?
module verification_alu(
input c_in
input [W-1:0] a, b,
input [2:0] operation,
output reg [W-1:0] result
output reg c_out
);
parameter W = 32;
always#*
begin
case(operation)
0: result = a;
1: result = ~a;
2: {c_out, result} = {a + b + c_in};
3: {c_out, result} = {a - b + c_in};
4: result = a | b;
5: result = a & b;
default: {c_out, result} = {W-2'b0}; // will this line fill with zeros properly?
endcase
end
endmodule
Also, side question, what should be the proper output of 32'b0 - 1'b1? Should I be getting 32'hffffffff?
The reason the addition and subtraction operations are not working is because you are wrapping the calculation in the concatenation operator ({}). Verilog determines the bit size of an operation partially based on the operands in an expression as well as by the context of that expression. In your case, the expression a + b + c_in is being evaluated as W-bits because the maximum length of any of the variables in that expression is W (ie, a and b are that length and because Verilog will first evaluate this addition (or two additions) before moving on to evaluating the {} operator wrapping it). By removing this unneeded step, you should get the proper (W+1)-bit evaluation of a + b + c_in; so the line would be: 3: {c_out, result} = a - b + c_in;. For more on this, see IEEE1800-2012, section 11.6.
To answer two of your other questions:
No, the expression {W-2'b0} will not zero fill but will instead result in the value W as you are telling the simulator to subtract 2'b0 from W. You are thinking of {(W-2){1'b0}}, or specially for zero filling '0 (because its so common, you can also use '1, 'x, or 'z for filling 1, don't care or high-Z respectively). (Note {c_out, result} has width W+1, not W-2 though)
Finally, 32'b0 - 1'b1 will most likely yield 32'hffffffff, but it is subject to the rules above on sizing (and sign extension rules as well).
A revised description:
module verification_alu #(parameter W=32) (
input wire c_in,
input wire [W-1:0] a,
input wire [W-1:0] b,
input wire [2:0] operation,
output reg [W-1:0] result,
output reg c_out
);
always #* begin
case(operation)
0: result = a;
1: result = ~a;
2: {c_out, result} = a + b + c_in;
3: {c_out, result} = a - b + c_in;
4: result = a | b;
5: result = a & b;
default: {c_out, result} = 0; // will this line fill with zeros properly?
endcase
end
endmodule
The point is to assure that at least one of the operands have the same size as the result you want, so I prepend a 0 bit to both a and b.
I have verified this to work even for sizes far beyond the size of an ordinary integer:
module tb;
reg c_in;
reg [127:0] a;
reg [127:0] b;
reg [2:0] op;
wire [127:0] res;
wire c_out;
verification_alu #(.W(128)) uut (c_in, a, b, op, res, c_out);
initial begin
c_in = 0;
a = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
b = 128'h00000000000000000000000000000001;
op = 3'd2;
#100;
$display ("RES = %H C_OUT = %d\n", res, c_out);
#100;
c_in = 0;
a = 128'h00000000000000000000000000000000;
b = 128'h00000000000000000000000000000001;
op = 3;
#100;
$display ("RES = %H C_OUT = %d\n", res, c_out);
#100;
op = 7;
#100;
$display ("RES = %H C_OUT = %d\n", res, c_out);
$finish;
end
endmodule
Chronologic VCS simulator copyright 1991-2014
Contains Synopsys proprietary information.
Compiler version J-2014.12-SP1-1; Runtime version J-2014.12-SP1-1; Oct 11 17:47 2015
RES = 00000000000000000000000000000000 C_OUT = 1
RES = ffffffffffffffffffffffffffffffff C_OUT = 1
RES = 00000000000000000000000000000000 C_OUT = 0
$finish called from file "testbench.sv", line 35.
$finish at simulation time 500
You can edit and/or run the testbench along with the revised module at http://www.edaplayground.com/x/CJV
EDIT: ouch! I didn't realized the OP had used the concatenation operator { } for embracing the three operands. Yes! your code is way much simpler. I'll edit the code in my answer.
First of all as per your code the parameter definitions in the input ports will not be accessible by compiler and will throw syntax error, you have to mention the parameter definitions before your i/o declarations since it is been accessed in i/o declarations, verilog comes with a syntax as to avoid this
module module_name #(parameter W =value)
{} is a concatenation operator used with "," eg: a=1bit b= 1bit c=2bit so we can give c={a,b}; so the correct syntax is as simple as
2: {c_out, result} = a + b + c_in;
3: {c_out, result} = a - b + c_in;
to fill it with zeros a mix of parameter with curly braces will help in resolving (the inner curly brace will act as replication operator)
default: {c_out, result} = {(W-2){1'b0}};

Set multiple registers in a single line (Verilog)

If I have a number of registers;
reg a;
reg b;
reg c;
is it possible to set a value (1'b0) to all of them in a single line (like in C), inside an always block, like this:
a <= b <= c <= 1'b0;
or would it see the two right-most non-blocking assignment operators as less-than-or-equal-to operators and do a logic evaluation?
Or would it be possible with blocking operators?
a = b = c = 1'b0;
In SystemVerilog, you can do
{a,b,c} <= '0; // non-blocking
or
a = (b = (c = '0) ); // blocking

Resources