Behavioral Modeling

>> 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:

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.
When the RHS evaluates to fewer bits than the LHS, then if the right-hand side is signed, it will be sign-extended to the size of the left-hand side.

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.
Sequential block: The sequential block is defined using the keywords begin and end. The procedural statements in sequential block will be executed sequentially in the given order. In sequential block delay values for each statement shall be treated relative to the simulation time of the execution of the previous statement. The control will pass out of the block after the execution of last statement.

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:
  1. Executes an assignment, normally used to initialize a variable that controls the number of times the for block is executed.
  2. 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.
  3. Executes an assignment normally used to modify the value of the loop-control variable and then repeats with second step.
Note that the first step is executed only once.

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

 

6 Comments:

Anonymous said...

Thanks for your information.
But it will be useful if you can provide why when it comes to synthesis for must be avoidable.
i mean provide the information regarding loops synthesis.

if you don't mind tell me whether function and task are synthesizable or not? if so why?

Things to do in Manali said...

Thank you for your post. I like it very much. Keep sharing like these.

Anonymous said...

Nice post.
Thank u :)

Anonymous said...

very useful post.It helped me a lot in understanding the concept of behavioral modelling.

harinathreddy said...

Its helped very much to me.. thanks for posting

Anonymous said...

Thanks for giving nice information...it helped very much..

 Save and Share: Digg del.icio.us Reddit Facebook Mixx Google YahooMyWeb blogmarks Blue Dot StumbleUpon Bumpzee Furl Sphinn Ma.gnolia MisterWong Propeller Simpy TwitThis Wikio BlinkList NewsVine