Verilog Assignments
Verilog Assignments
- continuous assignments
- procedural assignments
The difference between continuous and procedural assignment is, continuous assignments take
place in parallel while procedural assignments take place one after the other. Continuous
assignment can model only Combinational logic while procedural assignment can model both
Combinational and Sequential logic.
Continuos Statements:
Continuous assignment can only drive wire or tri data type. Which means left-side data type
should be net data type.
Continuous assignments should appear outside procedures(always, initial, functions, tasks, etc)
It executes each time the right hand side expression changes. It overrides any procedural
assignment.
A wire should be assigned only once using continuous assignment.
Only combinational logic can be modeled using Continuous Assignment.
This assignments occurs whenever the value of the right-hand side changes.
Executes in parallel
Continuously active
Order independent
The left-hand side of an assignment is a variable to which the right-side value is to be assigned
and must be a scalar or vector net or concatenation of both. The right-hand side of an
assignment, separated from the left-hand side by the equal (=) character, can be a net, a reg or
any expression that evaluates a value including function calls.
Continuous assignments drive values into the nets whenever the right-hand side value changes,
this means continuous assignments are always active and assignments occur whenever the right-
hand side operands changes. It drives both vector and scalar.
Continuous assignments can be used in two ways: as the net declaration statement and as the
continuous assignment statement.
In a continuous assignment statement, after the assign keyword (Example 1) the net is declared
as the left-hand side and after the equal (=) character, the right-hand side is declared as an
expression. The value of out changes whenever the values of operands In_1 or In_2 change.
Example 2 shows how to use continuous assignments with vectors. The left-hand side of an
assignment is a vector net, while the right-hand side operands are vector registers.
The left-hand side of an assignment can also be a concatenation of nets. Example 3 describes this
use.
Instead of the continuous assignment statement, the net declaration assignment can be used. This
means that in the net declaration statement we can assign expressions that occur whenever right-
hand side operands change. In this case, assign keyword is not used. Example 1can be described
as shown in Example 4. In this case a net can be declared only once, therefore only one net
declaration assignment can be made to a net.
An optional delay given to a continuous assignment specifies the time duration between the
right-hand side operand value change and the assignment to the left-hand side. Delay
specification can be used both in the continuous assignment statement and the net declaration
statement (see Example 5 and Example 6).
Examples
Example 1
wire out;
assign out = In_A & In_B ;
Continuous assignment 'out' is a net. Both In_1 and In_2 are nets.
Example 2
Continuous assignment with range specification. Address_1 and address_2 are 8-bit vector
registers.
Example 3
Example 4
Example 6
Example 7
Ex : wire x,y,z;
assign x=a&b;
assign y=a^b;
assign z=b||c;
Ex :
wire x,y,z;
assign z=b||c;
assigny=a^b;
assign x=a&b
assigned to LHS
Ex : wire x,y,z;
Reg a,b,c;
assign x=a&b;
values to regs.
Procedural Assignments :
Verilog behavioral code is inside procedure blocks, but there is an exception: some behavioral
code also exist outside procedure blocks. We can see this in detail as we make progress.
initial : initial blocks execute only once at time zero (start execution at time zero).
always : always blocks loop to execute over and over again; in other words, as the name
suggests, it executes always.
if(sel==0)
z=a;
else
z=b;
end
Initial Block:
Initial block may contain if conditions, loops, assignment statements etc., but not continuous
assignments. You can have any number of initial blocks in a module. All initial blocks execute
simultaneously.
Initial blocks are very useful in testbenches. Consider a code for counter. Actually in a
chip, initially counter will have a unpredicted value. But after sometimes, value will increase to
its maximum value, where all the bits are zero. Then it will start counting through 0 to maximum
value. But in the simulation, initially value will be 'x', and if we don't initialize, it will remain 'x'
only. So, we can use initial blocks to initialize all the signals to a valid value.
Syntax :
initial
begin
imperative statements
end
Ex : module tb_top();
reg a,b;
initial
begin
a=1b0;
b=1b0;
#10 a=1b1;
#10 b=1b1;
end
initial
#300 $finish;
endmodule
Ex : module tb_top();
reg a,b;
initial
begin
a=1b0;
b=1b0;
#10 a=1b1;
#10 b=1b1;
end
initial
#300 $finish;
Endmodule
Always Block :
Syntex : always
begin
imperative statements
End
Always blocks execute always. We can use delay or sensitivity list to control the execution of
always block. Syntax is as follows:
always @ ( sencitivity_list )
statements;
Sensitivity list may contain signal names as follows:
Ex :
always
Begin
Assignments
end
- If an always construct has no control for simulation time to advance , it will create a simulation
deadlock condition
initial begin
#10 a = 1; b = 0;
#10 a = 0; b = 1;
End
q = d;
always begin
wait(i);
a = 0;
wait(~i);
a = 1;
end
Event Control :
In Verilog the @ character specifies an edge-sensitive event control that blocks until there is a
transition in value (an edge) for one of the identifiers in the event expression. Ive encountered a
misconception that edge events are queued and then serviced by @() guards, rather than
@() being a guard that waits on edge events, blocking until an edge event happens.
Ive needed to remind people more than once that the only edge events that matter to an @()
guard are those that happen while it is waiting. Edge events that happen before reaching the
guard are irrelevant to the guard.
For example,
@(a or b)
will block until there is a change in the value of a or b. posedge and negedge just mean to be
sensitive only to a posedge (0 to 1 transition) or negedge (1 to 0 transition).
For example,
@(posedge clk)
will block until clk transitions from 0 to 1.
A possible reason for the misunderstanding? In traditional Verilog synthesis, event expressions
with posedge/negedge qualifiers get more serious treatment than ones without.
For example, consider the following example
Ex :
always(@(triggering_signal)
begin
begin
if(reset)
q<=1b0;
else
q<=d;
end
Execution trigged on
begin
if(reset)
q<=1b0;
else
q<=d;
end
Sensitivity list:
Without sensitivity list ,the always block will loop continuously without waiting for a
triggering event.
always@(a or b or sel)
begin
if(sel==1)
z=a;
else
z=b;
end
begin
if(reset==1)
z<=1b0;
else
z<=a|c;
end
All net and Variable identifiers which appears in the statement will be automatically added to the
event expression
module ev_exp_check(a,b,c,d,f,y);
input [1:0]a,b,c,d,f;
output y;
reg[1:0] y;
endmodule
Verilog:
Blocking statements
Non-blocking statements.
Blocking Assignments :
Blocking assignment are represented with the sign=.
these are executed sequentially, i.e. one statement is executed then the next statement is
executed.
any delay attached is also got added to delay in execution of next statements.
reg a,b;
intial begin
c=b;
b=a;
$display(a=%b,b=%b,a,b);
end
end module
simulation results:
A=1, b=1
Non Blocking Assignments :
For all the non-blocking assignments in a block, the right- hand sides are evaluated first.
Resulted values are stored in temporary variables and assigned to all the outputs
Simultaneously, at the end of execution of the block.
initial
Begin
a=1b1;
b=1b0;
The order of the execution of distinct non blocking assignments to a given variable shall be
preserved
module check_nonblock();
reg i;
initial
i=1;
initial begin
endmodule
Module blocking(D,clock,Q1,Q2);
input D,Clock;
reg Q1;
Begin
Q1=D;
Q2=Q1;
end
end module
Module non_black(D,Clock,Q1,Q2);
input D,Clock;
always@(posedge Clock)
Begin
Q1<=D;
Q2<=Q1;
end
end module
Looping Statements ;
If else Statements :
If-else statements check a condition to decide whether or not to execute a portion of code. If a
condition is satisfied, the code is executed. Else, it runs this other portion of code.
always@(.....) begin
assignment1;
if(condition)
begin//alternative1
assignment2;
end
else
begin //alternative 2
assignment3;
end
Assignment4;
End
if(hex == 1'b1)
else
Multiway Braching :
always@(sel)
begin
if(sel[0]==0)
z=a;
else if(sel[2:1]==2b01)
z=b;
else if(sel[2:1]==2b10)
z=c;
else if(sel[2:1]==2b11)
z=d
else
z=a;
end
Case Statements :
Multi way decision statement that tests whether an expression matches one of a number of other
expression and branches accordingly
Syntax:
case(expression)
.....
Ex :
reg[0:3] a,b,c,z;
integer x;
always@(a,b,c,x)
case(x)
0:z=a;
1:z=b;
endcase otherPossible
values
Ex :
reg[0:3] a,b,c,z;
integer x;
always@(a,b,c,x)
case(x)
1,3:z=b; conditions
default :z=c;
endcase
For Loop :
Evaluates an expression if the result is zero, the loop exits, and if it is not zero, the for-loop
executes its associated statements(s) and then perform step c.
Executes an assignment, normally modifies the value of the loop control variable, then repeats
step b.
end
This code will print the numbers from 0 to 15 in order. Be careful when using for loops for
register transfer logic (RTL) and make sure your code is actually sanely implementable in
hardware... and that your loop is not infinite.
While Loop :
count =0;
tempreg = rega;
begin
count = count+1;
end place
end
always@(a,b,sel)
begin
if(sel)
y=b;
else
y=a;
end
begin
if(reset)
q<=1b0;
else
q<=d;
end
When combining combinational and sequential code into a single always block, code the always
block as a sequential always block with non blocking assignments
module mix_blk_nblk(q,a,b,clk,rst);
output q;
input clk,rst,a,b;
reg q;
begin
if(!rst_n)
q<=1b0;
else
q<=a|b;
end
module mix_blk_nblk(q,a,b,clk,rst);
output q;
input clk,rst,a,b;
reg q,y;
always@(a or b)
Y=a|b;
if(!rst_n)
q<=1b0;
else
q<=y;
end