>> Introduction
>> The initial Construct
>> The always Construct
>> Procedural Assignments
>> Block Statements
>> Conditional (if-else) Statement
>> Case Statement
>> Loop Statements
>> Examples
Introduction
Behavioral modeling is the highest level of abstraction in the Verilog HDL. The other modeling techniques are relatively detailed. They require some knowledge of how hardware, or hardware signals work. The abstraction in this modeling is as simple as writing the logic in C language. This is a very powerful abstraction technique. All that designer needs is the algorithm of the design, which is the basic information for any design.
Most of the behavioral modeling is done using two important constructs: initial and always. All the other behavioral statements appear only inside these two structured procedure constructs.
The initial Construct
The statements which come under the initial construct constitute the initial block. The initial block is executed only once in the simulation, at time 0. If there is more than one initial block. Then all the initial blocks are executed concurrently. The initial construct is used as follows:
In the first initial block there are more than one statements hence they are written between begin and end. If there is only one statement then there is no need to put begin and end.
The always Construct
The statements which come under the always construct constitute the always block. The always block starts at time 0, and keeps on executing all the simulation time. It works like a infinite loop. It is generally used to model a functionality that is continuously repeated.
The above code generates a clock signal clk, with a time period of 10 units. The initial blocks initiates the clk value to 0 at time 0. Then after every 5 units of time it toggled, hence we get a time period of 10 units. This is the way in general used to generate a clock signal for use in test benches.
In the above example, the always block will be executed whenever there is a positive edge in the clk signal, or there is negative edge in the reset signal. This type of always is generally used in implement a FSM, which has a reset signal.
In the above example, whenever there is a change in b, c, or d the always block will be executed. Here the list b, c, and d is called the sensitivity list.
In the Verilog 2000, we can replace always @(b,c,d) with always @(*), it is equivalent to include all input signals, used in the always block. This is very useful when always blocks is used for implementing the combination logic.
Procedural Assignments
Procedural assignments are used for updating reg, integer, time, real, realtime, and memory data types. The variables will retain their values until updated by another procedural assignment. There is a significant difference between procedural assignments and continuous assignments.
Continuous assignments drive nets and are evaluated and updated whenever an input operand changes value. Where as procedural assignments update the value of variables under the control of the procedural flow constructs that surround them.
The LHS of a procedural assignment could be:
There are two types of procedural assignments: blocking and non-blocking assignments.
Blocking assignments: A blocking assignment statements are executed in the order they are specified in a sequential block. The execution of next statement begin only after the completion of the present blocking assignments. A blocking assignment will not block the execution of the next statement in a parallel block. The blocking assignments are made using the operator =.
In the above example, a is assigned value 1 at time 0, and b is assigned value 2 at time 5, and c is assigned value 3 at time 7.
Non-blocking assignments: The nonblocking assignment allows assignment scheduling without blocking the procedural flow. The nonblocking assignment statement can be used whenever several variable assignments within the same time step can be made without regard to order or dependence upon each other. Non-blocking assignments are made using the operator <=.
Note: <= is same for less than or equal to operator, so whenever it appears in a expression it is considered to be comparison operator and not as non-blocking assignment.
In the above example, a is assigned value 1 at time 0, and b is assigned value 2 at time 5, and c is assigned value 3 at time 2 (because all the statements execution starts at time 0, as they are non-blocking assignments.
Block Statements
Block statements are used to group two or more statements together, so that they act as one statement. There are two types of blocks:
Parallel block: The parallel block is defined using the keywords fork and join. The procedural statements in parallel block will be executed concurrently. In parallel block delay values for each statement are considered to be relative to the simulation time of entering the block. The delay control can be used to provide time-ordering for procedural assignments. The control shall pass out of the block after the execution of the last time-ordered statement.
Note that blocks can be nested. The sequential and parallel blocks can be mixed.
Block names: All the blocks can be named, by adding : block_name after the keyword begin or fork. The advantages of naming a block are:
Conditional (if-else) Statement
The condition (if-else) statement is used to make a decision whether a statement is executed or not. The keywords if and else are used to make conditional statement. The conditional statement can appear in the following forms.
Conditional (if-else) statement usage is similar to that if-else statement of C programming language, except that parenthesis are replaced by begin and end.
Case Statement
The case statement is a multi-way decision statement that tests whether an expression matches one of the expressions and branches accordingly. Keywords case and endcase are used to make a case statement. The case statement syntax is as follows.
If there are multiple statements under a single match, then they are grouped using begin, and end keywords. The default item is optional.
Case statement with don't cares: casez and casex
casez treats high-impedance values (z) as don't cares. casex treats both high-impedance (z) and unknown (x) values as don't cares. Don't-care values (z values for casez, z and x values for casex) in any bit of either the case expression or the case items shall be treated as don't-care conditions during the comparison, and that bit position shall not be considered. The don't cares are represented using the ? mark.
Loop Statements
There are four types of looping statements in Verilog:
Forever Loop
Forever loop is defined using the keyword forever, which Continuously executes a statement. It terminates when the system task $finish is called. A forever loop can also be ended by using the disable statement.
In the above example, a clock signal with time period 10 units of time is obtained.
Repeat Loop
Repeat loop is defined using the keyword repeat. The repeat loop block continuously executes the block for a given number of times. The number of times the loop executes can be mention using a constant or an expression. The expression is calculated only once, before the start of loop and not during the execution of the loop. If the expression value turns out to be z or x, then it is treated as zero, and hence loop block is not executed at all.
In the above example the loop block is executed only 50 times, and not 100 times. It calculates (a*b) at the beginning, and uses that value only.
While Loop
The while loop is defined using the keyword while. The while loop contains an expression. The loop continues until the expression is true. It terminates when the expression is false. If the calculated value of expression is z or x, it is treated as a false. The value of expression is calculated each time before starting the loop. All the statements (if more than one) are mentioned in blocks which begins and ends with keyword begin and end keywords.
In the above example the loop executes for 10 times. ( observe that a is decrementing by one and i is incrementing by one, so loop terminated when both i and a become 10).
For Loop
The For loop is defined using the keyword for. The execution of for loop block is controlled by a three step process, as follows:
The above example produces the same result as the example used to illustrate the functionality of the while loop.
Examples
1. Implementation of a 4x1 multiplexer.
2. Implementation of a full adder.
3. Implementation of a 8-bit binary counter.
Implementation of a 8-bit counter is a very good example, which explains the advantage of behavioral modeling. Just imagine how difficult it will be implementing a 8-bit counter using gate-level modeling.
In the above example the incrementation occurs on every positive edge of the clock. When count becomes 8'hFF, the next increment will make it 8'h00, hence there is no need of any modulus operator. Reset signal is active low.
>> The initial Construct
>> The always Construct
>> Procedural Assignments
>> Block Statements
>> Conditional (if-else) Statement
>> Case Statement
>> Loop Statements
>> Examples
Introduction
Behavioral modeling is the highest level of abstraction in the Verilog HDL. The other modeling techniques are relatively detailed. They require some knowledge of how hardware, or hardware signals work. The abstraction in this modeling is as simple as writing the logic in C language. This is a very powerful abstraction technique. All that designer needs is the algorithm of the design, which is the basic information for any design.
Most of the behavioral modeling is done using two important constructs: initial and always. All the other behavioral statements appear only inside these two structured procedure constructs.
The initial Construct
The statements which come under the initial construct constitute the initial block. The initial block is executed only once in the simulation, at time 0. If there is more than one initial block. Then all the initial blocks are executed concurrently. The initial construct is used as follows:
initial
begin
reset = 1'b0;
clk = 1'b1;
end
or
initial
clk = 1'b1;
In the first initial block there are more than one statements hence they are written between begin and end. If there is only one statement then there is no need to put begin and end.
The always Construct
The statements which come under the always construct constitute the always block. The always block starts at time 0, and keeps on executing all the simulation time. It works like a infinite loop. It is generally used to model a functionality that is continuously repeated.
always
#5 clk = ~clk;
initial
clk = 1'b0;
The above code generates a clock signal clk, with a time period of 10 units. The initial blocks initiates the clk value to 0 at time 0. Then after every 5 units of time it toggled, hence we get a time period of 10 units. This is the way in general used to generate a clock signal for use in test benches.
always @(posedge clk, negedge reset)
begin
a = b + c;
d = 1'b1;
end
In the above example, the always block will be executed whenever there is a positive edge in the clk signal, or there is negative edge in the reset signal. This type of always is generally used in implement a FSM, which has a reset signal.
always @(b,c,d)
begin
a = ( b + c )*d;
e = b | c;
end
In the above example, whenever there is a change in b, c, or d the always block will be executed. Here the list b, c, and d is called the sensitivity list.
In the Verilog 2000, we can replace always @(b,c,d) with always @(*), it is equivalent to include all input signals, used in the always block. This is very useful when always blocks is used for implementing the combination logic.
Procedural Assignments
Procedural assignments are used for updating reg, integer, time, real, realtime, and memory data types. The variables will retain their values until updated by another procedural assignment. There is a significant difference between procedural assignments and continuous assignments.
Continuous assignments drive nets and are evaluated and updated whenever an input operand changes value. Where as procedural assignments update the value of variables under the control of the procedural flow constructs that surround them.
The LHS of a procedural assignment could be:
- reg, integer, real, realtime, or time data type.
- Bit-select of a reg, integer, or time data type, rest of the bits are untouched.
- Part-select of a reg, integer, or time data type, rest of the bits are untouched.
- Memory word.
- Concatenation of any of the previous four forms can be specified.
There are two types of procedural assignments: blocking and non-blocking assignments.
Blocking assignments: A blocking assignment statements are executed in the order they are specified in a sequential block. The execution of next statement begin only after the completion of the present blocking assignments. A blocking assignment will not block the execution of the next statement in a parallel block. The blocking assignments are made using the operator =.
initial
begin
a = 1;
b = #5 2;
c = #2 3;
end
In the above example, a is assigned value 1 at time 0, and b is assigned value 2 at time 5, and c is assigned value 3 at time 7.
Non-blocking assignments: The nonblocking assignment allows assignment scheduling without blocking the procedural flow. The nonblocking assignment statement can be used whenever several variable assignments within the same time step can be made without regard to order or dependence upon each other. Non-blocking assignments are made using the operator <=.
Note: <= is same for less than or equal to operator, so whenever it appears in a expression it is considered to be comparison operator and not as non-blocking assignment.
initial
begin
a <= 1;
b <= #5 2;
c <= #2 3;
end
In the above example, a is assigned value 1 at time 0, and b is assigned value 2 at time 5, and c is assigned value 3 at time 2 (because all the statements execution starts at time 0, as they are non-blocking assignments.
Block Statements
Block statements are used to group two or more statements together, so that they act as one statement. There are two types of blocks:
- Sequential block.
- Parallel block.
Parallel block: The parallel block is defined using the keywords fork and join. The procedural statements in parallel block will be executed concurrently. In parallel block delay values for each statement are considered to be relative to the simulation time of entering the block. The delay control can be used to provide time-ordering for procedural assignments. The control shall pass out of the block after the execution of the last time-ordered statement.
Note that blocks can be nested. The sequential and parallel blocks can be mixed.
Block names: All the blocks can be named, by adding : block_name after the keyword begin or fork. The advantages of naming a block are:
- It allows to declare local variables, which can be accessed by using hierarchical name referencing.
- They can be disabled using the disable statement (disable block_name;).
Conditional (if-else) Statement
The condition (if-else) statement is used to make a decision whether a statement is executed or not. The keywords if and else are used to make conditional statement. The conditional statement can appear in the following forms.
if ( condition_1 )
statement_1;
if ( condition_2 )
statement_2;
else
statement_3;
if ( condition_3 )
statement_4;
else if ( condition_4 )
statement_5;
else
statement_6;
if ( condition_5 )
begin
statement_7;
statement_8;
end
else
begin
statement_9;
statement_10;
end
Conditional (if-else) statement usage is similar to that if-else statement of C programming language, except that parenthesis are replaced by begin and end.
Case Statement
The case statement is a multi-way decision statement that tests whether an expression matches one of the expressions and branches accordingly. Keywords case and endcase are used to make a case statement. The case statement syntax is as follows.
case (expression)
case_item_1: statement_1;
case_item_2: statement_2;
case_item_3: statement_3;
...
...
default: default_statement;
endcase
If there are multiple statements under a single match, then they are grouped using begin, and end keywords. The default item is optional.
Case statement with don't cares: casez and casex
casez treats high-impedance values (z) as don't cares. casex treats both high-impedance (z) and unknown (x) values as don't cares. Don't-care values (z values for casez, z and x values for casex) in any bit of either the case expression or the case items shall be treated as don't-care conditions during the comparison, and that bit position shall not be considered. The don't cares are represented using the ? mark.
Loop Statements
There are four types of looping statements in Verilog:
Forever Loop
Forever loop is defined using the keyword forever, which Continuously executes a statement. It terminates when the system task $finish is called. A forever loop can also be ended by using the disable statement.
initial
begin
clk = 1'b0;
forever #5 clk = ~clk;
end
In the above example, a clock signal with time period 10 units of time is obtained.
Repeat Loop
Repeat loop is defined using the keyword repeat. The repeat loop block continuously executes the block for a given number of times. The number of times the loop executes can be mention using a constant or an expression. The expression is calculated only once, before the start of loop and not during the execution of the loop. If the expression value turns out to be z or x, then it is treated as zero, and hence loop block is not executed at all.
initial
begin
a = 10;
b = 5;
b <= #10 10;
i = 0;
repeat(a*b)
begin
$display("repeat in progress");
#1 i = i + 1;
end
end
In the above example the loop block is executed only 50 times, and not 100 times. It calculates (a*b) at the beginning, and uses that value only.
While Loop
The while loop is defined using the keyword while. The while loop contains an expression. The loop continues until the expression is true. It terminates when the expression is false. If the calculated value of expression is z or x, it is treated as a false. The value of expression is calculated each time before starting the loop. All the statements (if more than one) are mentioned in blocks which begins and ends with keyword begin and end keywords.
initial
begin
a = 20;
i = 0;
while (i < a)
begin
$display("%d",i);
i = i + 1;
a = a - 1;
end
end
In the above example the loop executes for 10 times. ( observe that a is decrementing by one and i is incrementing by one, so loop terminated when both i and a become 10).
For Loop
The For loop is defined using the keyword for. The execution of for loop block is controlled by a three step process, as follows:
- Executes an assignment, normally used to initialize a variable that controls the number of times the for block is executed.
- Evaluates an expression, if the result is false or z or x, the for-loop shall terminate, and if it is true, the for-loop shall execute its block.
- Executes an assignment normally used to modify the value of the loop-control variable and then repeats with second step.
initial
begin
a = 20;
for (i = 0; i < a; i = i + 1, a = a - 1)
$display("%d",i);
end
The above example produces the same result as the example used to illustrate the functionality of the while loop.
Examples
1. Implementation of a 4x1 multiplexer.
module 4x1_mux (out, in0, in1, in2, in3, s0, s1);
output out;
// out is declared as reg, as default is wire
reg out;
// out is declared as reg, because we will
// do a procedural assignment to it.
input in0, in1, in2, in3, s0, s1;
// always @(*) is equivalent to
// always @( in0, in1, in2, in3, s0, s1 )
always @(*)
begin
case ({s1,s0})
2'b00: out = in0;
2'b01: out = in1;
2'b10: out = in2;
2'b11: out = in3;
default: out = 1'bx;
endcase
end
endmodule
2. Implementation of a full adder.
module full_adder (sum, c_out, in0, in1, c_in);
output sum, c_out;
reg sum, c_out
input in0, in1, c_in;
always @(*)
{c_out, sum} = in0 + in1 + c_in;
endmodule
3. Implementation of a 8-bit binary counter.
module ( count, reset, clk );
output [7:0] count;
reg [7:0] count;
input reset, clk;
// consider reset as active low signal
always @( posedge clk, negedge reset)
begin
if(reset == 1'b0)
count <= 8'h00;
else
count <= count + 8'h01;
end
endmodule
Implementation of a 8-bit counter is a very good example, which explains the advantage of behavioral modeling. Just imagine how difficult it will be implementing a 8-bit counter using gate-level modeling.
In the above example the incrementation occurs on every positive edge of the clock. When count becomes 8'hFF, the next increment will make it 8'h00, hence there is no need of any modulus operator. Reset signal is active low.
<< Previous | Home | Next >> |
Comments
In the example of implementing full adder in behavioral model, How it works
always @(*)
{c_out, sum} = in0 + in1 + c_in;
Python Training in Chennai
Python Training in Tambaram
Big data training in chennai
JAVA Training in Chennai
Selenium Training in Chennai
Software testing training in chennai
Python Training in Annanagar