Set multiple registers in a single line (Verilog) - 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

Related

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 #*

Does the following verilog code have a race condition issue?

I am working with a verilog module (shown below) has two always blocks. Won't there be some sort of race condition since one block sets a register and the other uses the register. What kind of issues would this cause?
Thanks,
Stephen
module XYZ
(
input wire CLK,
input wire Reset,
input wire nReset,
input wire [15:0] X,
input wire [15:0] A,
input wire T,
input wire B,
output reg M
);
assign C = X > A;
reg P;
reg N;
always #(posedge CLK, negedge nReset)
begin
if (~nReset)
begin
P <= 1;
N <= 1;
end else begin
if (Reset)
begin
P <= 1;
N <= 1;
end else begin
P <= T? 1: ((C & ~M)? 0: P);
N <= B? 1: ((M & ~C)? 0: N);
end
end
end
always #(posedge CLK, negedge nReset)
begin
if (~nReset)
begin
M <= 0;
end else begin
if (Reset)
begin
M <= 0;
end else begin
M <= M? ~(N & ~C): (P & C);
end
end
end
endmodule
No, there is no race condition. Verilog is an event-driven simulator. Posedge (unless there is a glitch in the clock or reset) is usually executed once per the simulation tick. If you use non-blocking assignments correctly (and it looks like you did), every always block triggered by an edge will use old versions of the input variable values, the values which existed before the clock edge.
Here is a simplified example:
always #(posedge clk)
r <= in;
always #(posedge clk)
out <= r;
What happens in this situation is the following:
r will be assigned the value of in later at the simulation tick, after the always blocks have been evaluated (see the nba scheduling region).
since r has not been yet really changed, the out will be scheduled to be assigned the value of r with the value before the edge.
If r was 0 before the edge and in was 1, at the end of the simulation r will become 1 and out will become 0.
This mimics behavior for real flops in hardware.
In your case it might look as a loop dependency. In reality it it none. For the same reason as above the M value will be the one from before the the posedge and will not cause any race. Flops cannot be involved in the combinational loops due to their properties logical properties.
I completely Agree with the above answer and i would suggest some more to the above answer, when i started learning Verilog i too got the same doubt and these lines from a ref. book clarified my doubts. I am coping the statement here and
for further doubts u can comment here or u can see the
Ref. book page number 135
Book name :Verilog HDL: A Guide to Digital Design and Synthesis,
Second Edition By Samir Palnitkar
nonblocking statements used in Example 2 eliminate the race condition.
At the positive edge of clock, the values of all right-hand-side
variables are "read," and the right-hand-side expressions are
evaluated and stored in temporary variables. During the write
operation, the values stored in the temporary variables are assigned
to the left-handside variables. Separating the read and write
operations ensures that the values of registers a and b are swapped
correctly, regardless of the order in which the write operations are
performed.
On the downside, nonblocking assignments can potentially cause a
degradation in the simulator performance and increase in memory usage.
//Example 2: Two concurrent always blocks with nonblocking
//statements
always #(posedge clock)
a <= b;
always #(posedge clock)
b <= a;
And u can use this type of coding style not compulsory but for the ease of debugging and to fasten simulation u can reduce the usage of begin-end blocks where ever possible
module XYZ
(
input wire CLK,
input wire Reset,
input wire nReset,
input wire [15:0] X,
input wire [15:0] A,
input wire T,
input wire B,
output reg M
);
reg P,N;
always #(posedge CLK, negedge nReset)
if (~nReset)begin
P <= #10 1;
N <= #10 1;
end else if (Reset) begin
P <= #10 1;
N <= #10 1;
end else begin
P <= #10 T ? 1 : ((C & ~M) ? 0: P);
N <= #10 B ? 1 : ((M & ~C) ? 0: N);
end
always #(posedge CLK, negedge nReset)
if (~nReset) M <= #10 0 ;
else if ( Reset) M <= #10 0 ;
else M <= #10 M ? ~(N & ~C): (P & C);
assign C = X > A;
endmodule

SystemVerilog Error: variable written by continuous and procedural assignments

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

Implementing one-bit flags in a 32Bit ALU using Verilog

I am working on an assignment and am a little lost and don't really know how to get started. I need to implement the following flags in a 32Bit ALU:
• Z ("Zero"): Set to 1 ("True") if the result of the operation is zero
• N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number
• O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.
Additionally, a comparison function that compares input a to input b and then set one of three flags:
• LT if input a is less than input b
• GT if input a is greater than input b
• EQ if input a is equal to input b
I need to modify this ALU to include the three flags and comparison outputs then change the test bench to test for all of these modifications.
This was all the information I received for this assignment and there is no textbook or any other resources really. It's an online class, and I cannot get a response from my instructor. So I am a little confused as to how to get started. I am still a total newbie when it comes to digital logic so please bear with me. I just need some help understanding how these flags and comparison works. If any one can explain this a little better to me as far as how they work and what they do, and possibly how I would implement them into the ALU and testbench, I would really appreciate it.
I don't expect anyone to do my assignment, I really just need help understanding it.
ALU
module alu32 (a, b, out, sel);
input [31:0] a, b;
input [3:0] sel;
output [31:0] out,
reg [31:0] out;
//Code starts here
always #(a, b, sel)
begin
case (sel)
//Arithmetic Functions
0 : out <= a + b;
1 : out <= a - b;
2 : out <= b - a;
3 : out <= a * b;
4 : out <= a / b;
5 : out <= b % a;
//Bit-wise Logic Functions
6 : out <= ~a; //Not
7 : out <= a & b; //And
8 : out <= a | b; //Or
9 : out <= a ^ b; //XOR
10 : out <= a ^~ b; //XNOR
//Logic Functions
11 : out <= !a;
12 : out <= a && b;
13 : out <= a || b;
default: out <= a + b;
endcase
end
endmodule
ALU Testbench
module alu32_tb();
reg [31:0] a, b;
reg [3:0] sel;
wire [31:0] out;
initial begin
$monitor("sel=%d a=%d b=%d out=%d", sel,a,b,out);
//Fundamental tests - all a+b
#0 sel=4'd0; a = 8'd0; b = 8'd0;
#1 sel=4'd0; a = 8'd0; b = 8'd25;
#1 sel=4'd0; a = 8'd37; b = 8'd0;
#1 sel=4'd0; a = 8'd45; b = 8'd75;
//Arithmetic
#1 sel=4'd1; a = 8'd120; b = 8'd25; //a-b
#1 sel=4'd2; a = 8'd30; b = 8'd120; //b-a
#1 sel=4'd3; a = 8'd75; b = 8'd3; //a*b
#1 sel=4'd4; a = 8'd75; b = 8'd3; //a/b
#1 sel=4'd5; a = 8'd74; b = 8'd3; //a%b
//Bit-wise Logic Functions
#1 sel=4'd6; a = 8'd31; //Not
#1 sel=4'd7; a = 8'd31; b = 8'd31; //And
#1 sel=4'd8; a = 8'd30; b = 8'd1; //Or
#1 sel=4'd9; a = 8'd30; b = 8'd1; //XOR
#1 sel=4'd10; a = 8'd30; b = 8'd1; //XNOR
//Logic Functions
#1 sel=4'd11; a = 8'd25; //Not
#1 sel=4'd12; a = 8'd30; b = 8'd0; //And
#1 sel=4'd13; a = 8'd0; b = 8'd30; //Or
#1 $finish;
end
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel));
endmodule
You can add these flag outputs to the design. Like the following. Simply connect them in testbench.
// In design:
output zero;
output overflow;
output negative;
// In testbench:
wire zero,overflow,negative;
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel), .zero(zero), .overflow(overflow),.negative(negative));
For logic part, you can do it with continuous assignments. You may need to add some logic for using these flags only during certain values of sel.
Z ("Zero"): Set to 1 ("True") if the result of the operation is zero
So, we can have condition like all the bits of out must be zero. This can be done in many other ways.
// Bit wise OR-ing on out
assign zero = ~(|out);
O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.
According to this description and the code shown, you simply want carry flag here.That is, a signed extension of addition operation. Refer to this page on WikiPedia for overflow condition.
But, Overflow condition is not the same as the carry bit. Overflow represents data loss while carry represents a bit used for calculation in next stage.
So, doing something like following may be useful:
// Extend the result for capturing carry bit
// Simply use this bit if you want result > bus width
{carry,out} <= a+b;
// overflow in signed arithmetic:
assign overflow = ({carry,out[31]} == 2'b01);
N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number
Again this is simply the MSB of the out register. But, the underflow condition is entirely a different thing.
// Depending on sel, subtraction must be performed here
assign negative = (out[31] == 1 && (sel == 1 || sel == 2));
Also, simple condition like assign lt = (a<b) ? 1 : 0; and others can detect the input LT, GT and EQ conditions.
Refer the answer here for the overflow/underflow flag understanding. Overflow-Carry link may also be useful.
Refer Carryout-Overflow, ALU in Verilog and ALU PDF for further information about ALU implementation.

Timing issue in Verilog

I am new to verilog and I am working on verilg code that defines two modules.
The first module calculates the mod of 2 numbers and the second uses the result to do some operation on it.
The result was wrong and has alot of don't care values because the same clk was used in both modules. Any suggestion please for synchronisation.
The mod module
module mod(m,a,b);
input [15:0] a,b;
output [15:0] m;
reg [31:0] mod;
reg [31:0] mul;
integer i;
always #* begin
mul = a*b;
mod = 32'h80008000;
for(i=0;i<16;i=i+1) begin
if(mul > mod) begin
mul = mul - mod;
mod = mod >> 1;
end
else begin
mod = mod >> 1;
end
end
assign m=mul[15:0];
endmodule
Part of the top module:
initial begin
keyp <= 2'b10;
shift <= 1'b0;
end
always #(posedge clk) begin
if(load)
case (keyp)
2'b10: begin
key[127:64] <= {k1,k0};
keyp <= 2'b01;
end
2'b01: begin
key[63:0] <= {k1,k0};
keyp <= 2'b00;
shift <= 1'b1;
end
//default: keyp <=2'b00;
endcase
else if (shift) begin
//shift key for first round
temp[24:0] <= key[127:103];
key[127:25] <= key[102:0];
key [24:0] <= temp [24:0];
shift <= 1'b0;
end
end
assign w1[2*SIZE-1:SIZE] = d1+key[2*SIZE-1:SIZE];
assign w1[3*SIZE-1:2*SIZE] = d2+key[3*SIZE-1:2*SIZE];
mod mod1( w1[SIZE-1:0], d0, key[SIZE-1:0] );
mod mod2( w1[4*SIZE-1:3*SIZE], d3, key[4*SIZE-1:3*SIZE]);
Assigning to the same value multiple times with blocking assignments is perfectly valid Verilog. Even having the same term appear on both sides is fine, provided it's been assigned at least once prior to that.
The code here is incomplete but the problem appears to be that the code is assigning to 'key' in multiple places. Both as the output of the mod instances and inside the clocked block. Anytime these two 'disagree' about the value of key it's going to been seen as an X. X in addition to representing unknown also reflects contention where two different assignments conflict.
Since I'm not sure what this code is meant to do (seems to be some sort of encryption) I can't offer a fix but you need to separate the assignments to key.
x's are referred to as do not cares in casex statements or Karnaugh maps, here they represent unknown values. Unknown values can come from a value not being initialised (reset) or multiple (conflicting) drivers.
The mod module contains this section of code:
always #* begin
mul = a*b;
mod = 32'h80008000;
for(i=0;i<16;i=i+1) begin
if(mul > mod) begin
mul = mul - mod;
mod = mod >> 1;
end
else begin
mod = mod >> 1;
end
end
always #* is a combinatorial block, you assign mul multiple times only the last assignment will have any effect.
The use of a for loop here makes it look like you are trying to reuse variables, as you would in c. Remember that we are describing hardware and that the value is intended to exist somewhere as flip flops or wires between modules and can only hold a single value in any given clock cycle.
In the combinatorial block you have mul = mul - mod; that is mul defining itself this will not work, you need to add a flip flop to break the loop.

Resources