Verilog _3(Verilog assignments)
We have two types of 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.
Assign values to nets
This assignments occurs whenever the value of the right-hand side changes.
Executes in parallel
Continuously active
Order independent
Syntax : assign assign_statement;
Continuous assignments provide a way of modeling combinational logic at a higher level of
abstraction than Gate-Level logic. It allows the use of Boolean logic rather than gate
connections.
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).
Also optional is strength specification. Example 7 shows a way to specify strength in a
continuous assignment. For more information about strength see the "Strength" chapter.
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
assign address[7:0] = address_1[7:0] ^ address_2[7:0] ;
Continuous assignment with range specification. Address_1 and address_2 are 8-bit vector
registers.
Example 3
assign {c_out, sum[7:0]} = Data_A[7:0]+Data_B[7:0]+c_in;
Continuous assignment with concatenation.
Example 4
wire out = In_A & In_B ;
The net declaration assignment. Equivalent to Example 1.
Example 5
assign #25 out = In_A & In_B ;
Delay specification in the continuous assignment statement.
Example 6
wire #25 out = In_A & In_B ;
Delay specification in the net declaration assignment.
Example 7
assign (strong1, pull0) out = Data_A | Data_B ;
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
Ex: wire c,a,b;
Assign #2 c=a&b; //RHS will be computed after 2
time Unit delay hen result will be
assigned to LHS
Ex : wire x,y,z;
Reg a,b,c;
assign x=a&b;
assignb=a^c; // wrong statement can not assign
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.
There are two types of procedural blocks in Verilog:
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.
Update the value of variables under the control of the
procedural flow constructs that surround them.
Each procedure represent a separate activity flow in
Verilog ,all of which run in parallel.
Ex : begin
if(sel==0)
z=a;
else
z=b;
end
Initial Block:
Runs when simulation starts.
Terminates when control reaches the end.
Good for providing stimulus.
Execution stops when the last statement is executed.
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 :
Repeats continuously throughout the duration of the simulation.
Runs when simulation starts.
Restarts when control reaches the end.
Good for modeling / specifying hardware.
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:
always @ ( signal1 or signal2 )
statement;
Above statement will execute whenever signal1 or signal2 changes. we can have 1 to any
number of signals in sensitivity list.
always @ ( posedge signal )
statement;
Above statement executes at the positive edge of signal. Similarly we can use negedge for
negative edge of the signal.
Without sensitivity list, always block will look like this:
always
#5 clk = ~clk;
This will toggle the signal clk for every 5 nanoseconds.
Ex :
always
Begin
procedural statements and // loops continuously
Assignments
end
- If an always construct has no control for simulation time to advance , it will create a simulation
deadlock condition
Run until they encounter a delay.
initial begin
#10 a = 1; b = 0;
#10 a = 0; b = 1;
End
or a wait for an event
always @(posedge clk)
q = d;
always begin
wait(i);
a = 0;
wait(~i);
a = 1;
end
Event Control :
Event- a change in value on a register or net.
A negedge is detected on thetransition from 1 to
x,z, or 0, and from x or z to 0
A posedge is detected on the transition from 0 to
x,z, or 1, and from x or z to 1
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
module test(input in, output reg previous_in);
reg temp;
always @(in) begin
previous_in = temp;
temp = in;
end
endmodule
An always procedure is an infinite loop. Usually, as here, its flow is punctuated by one or more
event controls. In this example, each time the input changes value, the infinite loop
resumes. Then previous_in is updated with the value of temp, which has saved the previous
value of in. Then temp is updated with the new value of in. And then the loop is again blocked
by the @(in) until the input changes again, and so on.
In traditional Verilog synthesis, however, this example yields the same netlist as the very
different
module test(input in, output reg previous_in);
reg temp;
always @(in) begin
previous_in = in;
end
endmodule
Ex :
always(@(triggering_signal)
begin
.. //Execution is triggered each
end time triggering_signal changes
Execution trigged on positive edge of the clock
always @(posedge clk)
begin
if(reset)
q<=1b0;
else
q<=d;
end
Execution trigged on
negative edge of the clock
always @(negedge clk)
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
always@(posedge clk or posedge reset)
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;
always@(*) //equivalent to @(a or b or c or d or f)
y=(a &b)|(c & d)|f;
endmodule
Blocking and Non Blocking Assignments :
There are two types of assignment statements are there in
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.
one statement blocks the execution of other statements until it is executed.
any delay attached is also got added to delay in execution of next statements.
module blk_assign(); // order is importent
reg a,b;
intial begin
a=1b0; //a initialized
b=1b1; //b initialized
c=b;
b=a;
$display(a=%b,b=%b,a,b);
end
end module
simulation results:
A=1, b=1
Non Blocking Assignments :
A non blocking assignment is represented with the sign<=
Its execution is concurrent with that of the following assignment or activity.
For all the non-blocking assignments in a block, the right- hand sides are evaluated first.
Subsequently the specified assignments are scheduled.
It is illegal to use a non-blocking assignment in a continuous ssignment statement or in a net
declaration
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;
b<=#10a; //B is scheduled to get 1after 10 time units
c<=b; //C will get 0 at the end of first time step, as
end b is not Yet assigned zero
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
i<=#5 1b0; //Schedules i=0 at time 5
i<=#5 1b1; //Schedules i=1 at time 5 Over rides
end previous Assignment of same time step
endmodule
Blocking Vs Non Blocking assignments :
Module blocking(D,clock,Q1,Q2);
input D,Clock;
output reg Q2;
reg Q1;
always@(pose edge Clock)
Begin
Q1=D;
Q2=Q1;
end
end module
Module non_black(D,Clock,Q1,Q2);
input D,Clock;
output reg Q1, Q2;
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)
data <= 4'b1101;
else
data <= 4'hd;
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)
case_item1:statement1; //Possible values for
case_item2:statement 2; the case expression
.....
Default : default _ statement; //Optional default statement
endcase
Ex :
reg[0:3] a,b,c,z;
integer x;
always@(a,b,c,x)
case(x)
0:z=a;
1:z=b;
default :z=c; //Covers all
endcase otherPossible
values
Ex :
reg[0:3] a,b,c,z;
integer x;
always@(a,b,c,x)
case(x)
0,2:z=a; //Covers multiple
1,3:z=b; conditions
default :z=c;
endcase
For Loop :
Its execution is a 3 step process as follows
Initialize a variable that controls the number of loops executed.
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.
for (i = 0; i < 16; i = i +1) begin
$display ("Current value of i is %d", i);
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 :
Executes a statement until an expression becomes false.
If the expression starts out false , the statement does not executes at all.
//Example counts the number of logic 1 value in reg a
begin reg[7:0] tempreg;
count =0;
tempreg = rega;
while(tempreg) //While tempreg is not all 0
begin
if(tempreg[0]) //If 0th bit is 1,count is incremented
count = count+1;
tempreg = tempreg>>1; //tempreg is shifted Right by one
end place
end
Coding Guide Lines :
It is best to use blocking assignment when describing combinational circuits, so as to avoid
accidentally creating a sequential circuit.
always@(a,b,sel)
begin
if(sel)
y=b;
else
y=a;
end
Use non-blocking assignments when describing sequential circuits.
always@(posedge clk or posedge reset)
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
Combinational and sequential logic in a single always block
module mix_blk_nblk(q,a,b,clk,rst);
output q;
input clk,rst,a,b;
reg q;
always@(posedge clk or posedge rst)
begin
if(!rst_n)
q<=1b0;
else
q<=a|b;
end
Combinational and sequential logic in two always blocks
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;
always@(posedge clk or posedge rst) begin
if(!rst_n)
q<=1b0;
else
q<=y;
end