Showing posts with label Behavioral Modeling. Show all posts
Showing posts with label Behavioral Modeling. Show all posts

Behavioral Modeling


Behavioral modeling:

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.


Behavioral Modeling


BEHAVIORAL MODELING

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

#1 clk = 0;

#10 reset = 0;

#5 enable = 0;

#3 data = 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
   #1  clk = 0;
   #10 reset = 0;
   #5  enable = 0;
   #3  data = 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).\

Example – Parallel

module parallel();
 
reg a;
 
initial 
fork
  $monitor ("%g a = %b", $time, a);
  #10 a = 0;
  #11 a = 1;
  #12 a = 0;
  #13 a = 1;
  #14 $finish;
join
 
endmodule

Blocking and Nonblocking assignment


Blocking and Nonblocking assignment

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 else  begin
  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 care  2: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 = %d  clk = %b",$time, clk);
  #100 $finish;
end
 
endmodule
 

The repeat statement

The keyword repeat is 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;
reg        temp;
 
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 (" TEMP  DATA");
   $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 = %b   LOCATION = %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.

Example – For

module for_example();
integer i;
reg [7:0] ram [0:255];
initial begin
  for (i = 0; i < i =" i">
    #1 $display(" Address = %g  Data = %h",i,ram[i]);
    ram[i] <= 0; // Initialize the RAM with 0
    #1 $display(" Address = %g  Data = %h",i,ram[i]);
  end
  #1 $finish;
end
 
endmodule