In this style of modeling, the internal working of an entity can be implemented using set of statements.
It contains: • Process statements • Sequential statements • Signal assignment statements • Wait statements
Process statement is the primary mechanism used to model the behavior of an entity. It contains sequential statements, variable assignment (:=) statements or signal assignment (<=) statements etc. It may or may not contain sensitivity list. If there is an event occurs on any of the signals in the sensitivity list, the statements within the process is executed. Inside the process the execution of statements will be sequential and if one entity is having two processes the execution of these processes will be concurrent. At the end it waits for another event to occur.
library IEEE; use IEEE.STD_LOGIC_1164.all; entity ha_beha_en is port( A : in BIT; B : in BIT; S : out BIT; C : out BIT ); end ha_beha_en; architecture ha_beha_ar of ha_beha_en is begin process_beh:process(A,B) begin S<= A xor B; C<=A and B; end process process_beh; end ha_beha_ar; Here whenever there is a change in the value of a or b the process statements are executed.
Verilog provides designers the ability to describe design functionality in an algorithmic manner. In other words, the designer describes the behavior of the circuit. Thus, behavioral modeling represents the circuit at a very high level of abstraction. Design at this level resembles C programming more than it resembles digital circuit design. Behavioral Verilog constructs are similar to C language constructs in many ways. Verilog is rich in behavioral constructs that provide the designer with a great amount of flexibility.
Procedural Blocks
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.
Example – initial
module initial_example();
reg clk,reset,enable,data;
initial begin
clk = 0;
reset = 0;
enable = 0;
data = 0;
end
endmodule
In the above example, the initial block execution and always block execution starts at time 0. Always block waits for the event, here positive edge of clock, whereas initial block just executed all the statements within begin and end statement, without waiting.
Example – always
module always_example();
reg clk,reset,enable,q_in,data;
always @ (posedge clk)
if (reset)begin
data <= 0;
end else if (enable) begin
data <= q_in;
end
endmodule
In an always block, when the trigger event occurs, the code inside begin and end is executed; then once again the always block waits for next event triggering. This process of waiting and executing on event is repeated till simulation stops.
Procedural Assignment Statements
Procedural assignment statements assign values to reg, integer, real, or time variables and cannot assign values to nets (wire data types)
You can assign to a register (reg data type) the value of a net (wire), constant, another register, or a specific value.
Example - Bad procedural assignment
module initial_bad();
reg clk,reset;
wire enable,data;
initial begin
clk = 0;
reset = 0;
enable = 0;
data = 0;
end
endmodule
Example - Good procedural assignment
module initial_bad();
reg clk,reset;
wire enable,data;
initial begin
clk = 0;
reset = 0;
enable = 0;
data = 0;
end
endmodule
Procedural Assignment Groups
If a procedure block contains more than one statement, those statements must be enclosed within
Sequential begin - end block
Parallel fork - join block
When using begin-end, we can give name to that group. This is called named blocks.
Example - "begin-end"
module initial_begin_end();
reg clk,reset,enable,data;
initial begin
$monitor(
"%g clk=%b reset=%b enable=%b data=%b",
$time, clk, reset, enable, data);
#1clk = 0;
#10 reset = 0;
#5enable = 0;
#3data = 0;
#1 $finish;
end
endmodule
Begin : clk gets 0 after 1 time unit, reset gets 0 after 11 time units, enable after 16 time units, data after 19 units. All the statements are executed sequentially.
Example - "fork-join"
module initial_fork_join();
reg clk,reset,enable,data;
initial begin
$monitor("%g clk=%b reset=%b enable=%b data=%b",
$time, clk, reset, enable, data);
fork
#1clk = 0;
#10 reset = 0;
#5enable = 0;
#3data = 0;
join
#1 $display ("%g Terminating simulation", $time);
$finish;
end
endmodule
Fork: clk gets its value after 1 time unit, reset after 10 time units, enable after 5 time units, data after 3 time units. All the statements are executed in parallel.
Sequential Statement Groups
The begin - end keywords:
Group several statements together.
Cause the statements to be evaluated sequentially (one at a time)
-> Any timing within the sequential groups is relative to the previous statement.
-> Delays in the sequence accumulate (each delay is added to the previous delay)
-> Block finishes after the last statement in the block.
Example – sequential
module sequential();
reg a;
initial begin
$monitor ("%g a = %b", $time, a);
#10 a = 0;
#11 a = 1;
#12 a = 0;
#13 a = 1;
#14 $finish;
end
endmodule
Parallel Statement Groups
The fork - join keywords:
Group several statements together.
Cause the statements to be evaluated in parallel (all at the same time).
-> Timing within parallel group is absolute to the beginning of the group.
-> Block finishes after the last statement completes (Statement with highest delay, it can be the first statement in the block).\
Blocking assignments are executed in the order they are coded, hence they are sequential. Since they block the execution of next statement, till the current statement is executed, they are called blocking assignments. Assignment are made with "=" symbol.
Example a = b;
Nonblocking assignments are executed in parallel. Since the execution of next statement is not blocked due to execution of current statement, they are called nonblocking statement. Assignments are made with "<=" symbol.
Example a <= b;
Note: Correct way to spell 'nonblocking' is 'nonblocking' and not 'non-blocking'.
Example - blocking and nonblocking
module blocking_nonblocking();
reg a,b,c,d;
// Blocking Assignment
initial begin
#10 a = 0;
#11 a = 1;
#12 a = 0;
#13 a = 1;
end
initial begin
#10 b <= 0;
#11 b <= 1;
#12 b <= 0;
#13 b <= 1;
end
initial begin
c = #10 0;
c = #11 1;
c = #12 0;
c = #13 1;
end
initial begin
d <= #10 0;
d <= #11 1;
d <= #12 0;
d <= #13 1;
end
initial begin
$monitor("TIME = %g A = %b B = %b C = %b D = %b",$time, a, b, c, d);
#50 $finish;
end
endmodule
assign and deassign
The assign and deassign procedural assignment statements allow continuous assignments to be placed onto registers for controlled periods of time. The assign procedural statement overrides procedural assignments to a register. The deassign procedural statement ends a continuous assignment to a register.
force and release
Another form of procedural continuous assignment is provided by the force and release procedural statements. These statements have a similar effect on the assign-deassign pair, but a force can be applied to nets as well as to registers.
One can use force and release while doing gate level simulation to work around reset connectivity problems. Also can be used insert single and double bit errors on data read from memory.
Conditional Statements
The Conditional Statement if-else
if - else statement controls the execution of other statements. In programming language like c, if - else controls the flow of program. When more than one statement needs to be executed for an if condition, then we need to use begin and end as seen in earlier examples.
Syntax : if
if (condition)
statements;
Syntax : if-else
if (condition)
statements;
else
statements;
Syntax : nested if-else-if
if (condition)
statements;
else if (condition)
statements;
................
................
else
statements;
Example- simple if
module simple_if();
reg latch;
wire enable,din;
always @ (enable or din)
if (enable) begin
latch <= din;
end
endmodule
Example- if-else
module if_else();
reg dff;
wire clk,din,reset;
always @ (posedge clk)
if (reset) begin
dff <= 0;
end elsebegin
dff <= din;
end
endmodule
Example-nested-if-else-if
module nested_if();
reg [3:0] counter;
reg clk,reset,enable, up_en, down_en;
always @ (posedge clk)
// If reset is asserted
if (reset == 1'b0) begin
counter <= 4'b0000;
// If counter is enable and up count is asserted
end else if (enable == 1'b1 && up_en == 1'b1) begin
counter <= counter + 1'b1;
// If counter is enable and down count is asserted
end else if (enable == 1'b1 && down_en == 1'b1) begin
counter <= counter - 1'b1;
// If counting is disabled
end else begin
counter <= counter; // Redundant code
end
The Case Statement
The case statement compares an expression to a series of cases and executes the statement or statement group associated with the first matching case:
case statement supports single or multiple statements.
Group multiple statements using begin and end keywords.
Syntax of a case statement is given below,
case ()
<> : <>
<> : <>
.....
default : <>
endcase
Example- case
module mux (a,b,c,d,sel,y);
input a, b, c, d;
input [1:0] sel;
output y;
reg y;
always @ (a or b or c or d or sel)
case (sel)
0 : y = a;
1 : y = b;
2 : y = c;
3 : y = d;
default : $display("Error in SEL");
endcase
endmodule
Example- case without default
module mux_without_default (a,b,c,d,sel,y);
input a, b, c, d;
input [1:0] sel;
output y;
reg y;
always @ (a or b or c or d or sel)
case (sel)
0 : y = a;
1 : y = b;
2 : y = c;
3 : y = d;
2'bxx,2'bx0,2'bx1,2'b0x,2'b1x,
2'bzz,2'bz0,2'bz1,2'b0z,2'b1z : $display("Error in SEL");
endcase
endmodule
Example- case with x and z
module case_xz(enable);
input enable;
always @ (enable)
case(enable)
1'bz : $display ("enable is floating");
1'bx : $display ("enable is unknown");
default : $display ("enable is %b",enable);
endcase
endmodule
The casez and casex statement
Special versions of the case statement allow the x ad z logic values to be used as "don't care":
casez : Treats z as don't care.
casex : Treats x and z as don't care.
Example- casez
module casez_example();
reg [3:0] opcode;
reg [1:0] a,b,c;
reg [1:0] out;
always @ (opcode or a or b or c)
casez(opcode)
4'b1zzx : begin // Don't care about lower 2:1 bit, bit 0 match with x
out = a;
$display("@%0dns 4'b1zzx is selected, opcode %b",$time,opcode);
end
4'b01?? : begin
out = b; // bit 1:0 is don't care
$display("@%0dns 4'b01?? is selected, opcode %b",$time,opcode);
end
4'b001? : begin// bit 0 is don't care
out = c;
$display("@%0dns 4'b001? is selected, opcode %b",$time,opcode);
end
default : begin
$display("@%0dns default is selected, opcode %b",$time,opcode);
end
endcase
Example- casex
module casex_example();
reg [3:0] opcode;
reg [1:0] a,b,c;
reg [1:0] out;
always @ (opcode or a or b or c)
casex(opcode)
4'b1zzx : begin // Don't care2:0 bits
out = a;
$display("@%0dns 4'b1zzx is selected, opcode %b",$time,opcode);
end
4'b01?? : begin // bit 1:0 is don't care
out = b;
$display("@%0dns 4'b01?? is selected, opcode %b",$time,opcode);
end
4'b001? : begin // bit 0 is don't care
out = c;
$display("@%0dns 4'b001? is selected, opcode %b",$time,opcode);
end
default : begin
$display("@%0dns default is selected, opcode %b",$time,opcode);
end
endcase
Looping Statements
Looping statements appear inside procedural blocks only; Verilog has four looping statements like any other programming language.
forever
repeat
while
for
The forever statement
The keyword forever is used to express this loop. The loop does not contain any expression and executes continually, until the $finish task is encountered. Normally we use forever statements in initial blocks.
Syntax: forever <>
One should be very careful in using a forever statement: if no timing construct is present in the forever statement, simulation could hang. The code below is one such application, where a timing construct is included inside a forever statement.
Example
module forever_example ();
reg clk;
initial begin
#1 clk = 0;
forever begin
#5 clk = !clk;
end
end
initial begin
$monitor ("Time = %dclk = %b",$time, clk);
#100 $finish;
end
endmodule
The repeat statement
The keyword repeatis used for thi sloop. The repeat construct executes the loop a fixed number of times. A repeat construct cannot be used to loop on a general logical expression. The repeat loop executes <> a fixed <> of times.
Syntax: repeat (<>) <>
Example- repeat
module repeat_example();
reg[3:0] opcode;
reg[15:0] data;
regtemp;
always @ (opcode or data)
begin
if (opcode == 10) begin
// Perform rotate
repeat (8) begin
#1 temp = data[15];
data = data <<>
data[0] = temp;
end
end
end
// Simple test code
initial begin
$display (" TEMPDATA");
$monitor (" %b%b ",temp, data);
#1 data = 18'hF0;
#1 opcode = 10;
#10 opcode = 0;
#1 $finish;
end
endmodule
The while loop statement
The keyword while is used to specify this loop. The while loop executes as long as an <> evaluates as true. If the loop is entered when the while-expression is false, the loop is not executed at all. This is the same as in any other programming language.
Syntax: while (<>) <>
Example- while
module while_example();
reg [5:0] loc;
reg [7:0] data;
always @ (data or loc)
begin
loc = 0;
// If Data is 0, then loc is 32 (invalid value)
if (data == 0) begin
loc = 32;
end else begin
while (data[0] == 0) begin
loc = loc + 1;
data = data >> 1;
end
end
$display ("DATA = %bLOCATION = %d",data,loc);
end
initial begin
#1 data = 8'b11;
#1 data = 8'b100;
#1 data = 8'b1000;
#1 data = 8'b1000_0000;
#1 data = 8'b0;
#1 $finish;
end
endmodule
The for loop statement
The for loop is the same as the for loop used in any other programming language.
Executes an <> once at the start of the loop.
Executes the loop as long as an <> evaluates as true.
Executes a <> at the end of each pass through the loop.
Syntax: for (<>; <>, <>) <>
Note: Verilog does not have ++ operator as in the case of C language.