Hierarchical Modeling Concepts

  • Modules are Building blacks
  • You can either have top down where you break a model to it’s smallest primitives and bottom up where you start building from primitives
  • Modules : Now modules are basic building blocks of Verilog
module MyModule ([parameters]);
     inputs ...
     outputs ...
     internal variables ...
     ...
     Module Code ...
endmodule
  • Instance
wire w, x, y, z; 
AND A1(w, x, y); 
AND A2(w, y, z); 
AND A3(z, x, w);

Reference

Hierarchical Modeling Concepts: VLSI

second chapter from  Verilog HDL: A Guide to Digital Design and Synthesis, Second Edition. By Samir Palnitkar.

Modules

Now modules are basic building blocks of Verilog. I think of modules like an object in C++ (This is a crude correlation but it helps me clear up my thoughts a bit)

Learning is always easier when you try to learn by correlating new things with the information you already have.

module MyModule ([parameters]);
     inputs ...
     outputs ...
     internal variables ...
     ...
     Module Code ...
endmodule

Things To Note:

  • Starts with module ends with endmodule
  • inputs and outputs are both taken in as [parameters]
    • No specific order for input and output in [parameters]
  • MODULE NESTING IS ILLEGAL

input and output here are ports, MyModule is an identifier (terminology is important if you want to score in exam)

Instances

Instance of a Module is instance. To make it more clear, think of this as an object to a class in Java or C++

You can have instances of modules in definition of another module, but you cannot have declaration of the new module.

module AND(a, b, c);
   input a, b;
   output c;
   assign c = a & b;
endmodule

wire w, x, y, z; 
AND A1(w, x, y); 
AND A2(w, y, z); 
AND A3(z, x, w);

Reference

Connection by Ordered List

This is pretty straightforward. You remember the list of things that you wanted to be connected and create instance with the same order.

full_adder(a, b, c_in, sum, c_out);

Connection by Port Names

This might not really work when there are like a hundred ports and many of them are optional. Here we use port names.

full_adder fa_byname(.carry(C_OUT)), .a(A), .b(B), .c_in(C_IN), .sum(SUM);

Lexical Conventions

  • Keywords, e. g., module, are reserved and in all lower case letters. Verilog is case sensitive •
  • Spaces are important in that they delimit tokens in the language.
  • String: is a sequence of characters enclosed in double quotes. “this is a string”
  • Operators (some examples:)
    • – Arithmetic: +, – ! ~ * /
    • – Shift: << >>
    • – Relational: < <= > >= == != === !==
    • – Logical && ||.
  • Identifier: Equivalent to variable names: Identifiers can be up to 1024 characters.
  • Reference : http://class.ece.iastate.edu/arun/Cpre305/lectures/verilog.pdf

Data Types

  • Register variables store the last value that was procedurally
    assigned to them
  • wire variables represent physical connections between structural entities such as gates – does not store anything, only a label on a wire

System Tasks and Complier Directives

System Tasks and Functions
These are tasks and functions that are used to generate input and output during simulation. Their names begin with a dollar sign ($). 

$display, $strobe, $monitor, $time, $stime, $realtime, $reset, $stop, $finish

Compiler Directives
Compiler directives are special commands, beginning with ‘, that affect the operation of the Verilog simulator

Syntax
     `timescale time_unit / time_precision;
 `define macro_name text_string;
     `include file_name;

Verilog Constructs and Modeling Styles

You can write module at four levels of abstractions

  • Behavioural (Algorithmic like C)
  • Dataflow (How data flows between resistors)
  • Gate Level (Logic gate circuits)
  • Switch Level (1s and 0s)

Behavioural vs Dataflow

Dataflow modeling in Verilog allows a digital system to be designed in terms of it’s function. Dataflow modeling utilizes Boolean equations, and uses a number of operators that can acton inputs to produce outputs operators like + – && & ! ~ || | << >> {} so if i want to describe a 2 to 4 decoder in dataflow modeling i would be like this

module decoder2to4 ( e , a, b, do, dl, d2, d3);
input e, a, b;
output do, dl, d2, d3;
assign dO = ( e & ~a & ~b); //00
assign dl = (e & ~a & b);   //01
assign d2 = (e & a & ~b);   //10
assign d3 = ( e & a & b);   //11
endmodu1e

on the other hand The Behavioral modeling in Verilog is used to describe the function of a design in an algorithmic manner so if i want to describe a 2 to 4 decoder in dataflow modeling i would be like this

module decoder2to4 (e, i, d);
output [3:0] d;
input [l:0]i;
input e;
reg [3:0] d;
    always @ (i or e) begin
            if (e==l) begin
                case (i)
                       0: d = 4'b 0001;
                       1: d = 4'b 0010;
                       2: d = 4'b 0100;
                       3: d = 4'b 1000;
                      default d = 4'b xxxx;
               endcase
            end
            else
               d = 4'b0000;
    end
endmodule

Reference Difference between behavioral and dataflow in verilog

Continuous Assignment

Rules First

  • Left hand of the assignment must always be a scalar or vector net.
    • It cannot be a scalar or vector register
  • Continuous assignments are always active
    • Eval ASA right hand operand changes and value is assigned.
  • Right hand can be register or nets or function calls, they can also be scalars or vectors
assign addr[15:0] = addr1_bits[15:0] ^ addr2_bits[15:0]

Remember delays that we did last time, if you want to have delay in the assignment the same thing can be done here. Thus, now there will be a time delay when the right hand changes and the value is assigned to the lefthand.

assign #(10) addr[15:0] = addr1_bits[15:0] ^ addr2_bits[15:0] #adds 10 second delay

There are three of these delays.

Regular Assignment delay

assign #(10) b = a ^ b; 

Implicit Continuous Assignment Delay

wire #(10) b= a^b;

Net Declaration Delay

wire #(10) b;
b = a^b;

Reference :Verilog: Dataflow Modeling

Procedural Assignment

Procedural assignment changes the state of a register

Blocking assignment statement (= operator) acts much like
in traditional programming languages.

Non-blocking (<= operator) evaluates all the right-hand sides for the current time unit and assigns the left-hand sides at the end of the time unit.

Operators in Verilog

OperatorDescription
+ ba plus b
 ba minus b
* ba multiplied by b
/ ba divided by b
% ba modulo b
** ba to the power of b
OperatorDescription
< ba less than b
> ba greater than b
<= ba less than or equal to b
>= ba greater than or equal to b
OperatorDescription
=== ba equal to b, including x and z
!== ba not equal to b, including x and z
== ba equal to b, result can be unknown
!= ba not equal to b, result can be unknown
OperatorDescription
&& bevaluates to true if a and b are true
|| bevaluates to true if a or b are true
!aConverts non-zero value to zero, and vice versa
  • Logical shift operators     : <<  and >>
  • Arithmetic shift operators : <<< and >>>
  • bitwise and &
  • bitwise or |

Functions

function [automatic] [return_type] name ([port_list]);
    [statements]
  endfunction

Function rules

  • A function cannot contain any time-controlled statements like #@waitposedgenegedge
  • A function cannot start a task because it may consume simulation time, but can call other functions
  • A function should have atleast one input
  • A function cannot have non-blocking assignments or force-release or assign-deassign
  • A function cannot have any triggers
  • A function cannot have an output or inout

Reference : https://www.chipverify.com/verilog/verilog-functions

Tasks

// Style 1
  task [name];
    input  [port_list];
    inout  [port_list];
    output [port_list];
    begin
      [statements]
    end
  endtask
 
  // Style 2
  task [name] (input [port_list], inout [port_list], output [port_list]);
    begin
      [statements]
    end
  endtask
 

Difference between function and task

FunctionTask
Cannot have time-controlling statements/delay, and hence executes in the same simulation time unitCan contain time-controlling statements/delay and may only complete at some other time
Cannot enable a taskCan enable other tasks and functions
Should have atleast one input argument and cannot have output or inout argumentsCan have zero or more arguments of any type
Can return only a single valueCannot return a value, but can achieve the same effect using output arguments

Reference : https://www.chipverify.com/verilog/verilog-task

Gate Delays

Gate Level Modeling

Every kind of delay in verilog

You can add delay using #(number) after the gate keyword.

add #(5) a1(out, a, b); //5sec delay for and gate

Annotates notes on Chapter 5: Gate Level Modeling

Sequential and Parallel Blocks

Adder

Revision : Full Adder

Image result for fulladder
Full Adder is basically two half adders. ref
Image result for fulladder
Ref
Image result for 4 bit ripple carry adder

ALU

module alu(a, b, s, out);
  input a, b, s;
  output out;
  reg temp; 
  always @(*)
    case(s)
      3'b000: temp = a+b;
      3'b001: temp = a-b;
      3'b010: temp = a*b;
      3'b011: temp = a/b;
      3'b100: temp = a&&b;
      3'b101: temp = a||b;
      3'b110: temp = a^b;
      3'b111: temp = a~^b;
      default: temp = 1'bz;
    endcase
  assign out = temp;
endmodule
      

You know, this might be a little probalamatic

module alu_tb; 
  reg a, b, s;
  wire out; 
  alu a1(
    a, 
    b, 
    s, 
    out
  );
  initial 
    begin
      a=5; b=3;s=3'b001;
      #10;
      $display(" out = %b " , out);
    end
endmodule

https://www.edaplayground.com/x/4X3q#

Multiplexer

Gate Level Multiplexer

2:1 mux using bufif

Counter

https://www.edaplayground.com/x/2FWR

Let’s get to it

module counter(q, clock, clear);
  input clock, clear; 
  output [3:0]q;
  reg [3:0]q;
  always @(posedge clear or negedge clock)
    begin
      if(clear)
        q= 4'd0;
      else
        q = (q+1)%16;
    end
endmodule

Writing the testbench for this one is difficult

module counter_tb;
  reg clock, clear; 
  wire [3:0] q; 
  counter c(q, clock, clear); 
  initial 
    begin 
    clock=0;
    forever #5 clock=~clock;
    end
  
  initial 
    begin
      forever #5 $display("q %b", q);
    end
  
  initial 
    begin
      clear=1;
      #20;
      clear=0;
    end
endmodule 

Let’s see what’s happening in the testbench. Clock toggles every 5 seconds. Then you toggle clear at #20

Parity Checker

module parity_generator(a, parity);
  input [7:0]a; 
  output parity;
  reg parity;
  
  always @(*)
    begin
      if (~^a)
      	parity<=1'b1;
      else
        parity<=1'b0;
    end
endmodule
module test;
  reg [7:0]a;
  wire out;
  parity_generator p(a, out);
  
  initial 
    begin
    a=8'b11100110;
      #10;
    $display("parity %b", out);
  	end
endmodule

https://www.edaplayground.com/x/2Jas

Comparator

module comp(a, b, e, g, l);
  input a, b;
  output e, g, l; 
  
  reg e, g, l;
  
  always @(*)
    begin
      if(a===b)
        begin
          e=1'b1;
          g=1'b0;
          l=1'b0;
        end
      else if(a>b)
        begin
          g=1'b1;
          e=1'b0;
          l=1'b0;
        end
      else if(a<b)
        begin
          l=1'b1;
          g=1'b0;
          e=1'b0;
        end
    end
endmodule
module test;
  reg a, b;
  wire e, g, l;
  comp c(a, b, e, g,l);
  initial 
    begin
      a=1'b1; b=1'b0;
      #10;
      $display("e %b g %b l %b", e, g, l);
    end
endmodule

Shift Register SISO

module shift(sin, sout, clk);
  input sin, clk;
  output sout;
  reg bit0;
  reg bit1;
  reg bit2;
  reg bit3;

  assign sout = bit3;
  always @(posedge clk) 
    begin
      bit3 <= bit2;
      bit2 <= bit1;
      bit1 <= bit0;
      bit0 <= sin;

    end
endmodule
  
module test; 
  reg sin, clk; 
  wire sout; 
  shift s1(sin, sout, clk);
  initial 
    begin
    	sin = 1; 
      	clk = 0; 
  	end
  
  initial 
    forever #5 clk = ~clk;
  
  initial 
    forever #10 sin = ~sin;
  
  initial 
    forever #5 $display("sout = %b", sout);
      
endmodule

D- Flip Flop

https://www.edaplayground.com/x/9

// Design
// D flip-flop
module dff (clk, reset,
  d, q, qb);
  input      clk;
  input      reset;
  input      d;
  output     q;
  output     qb;

  reg        q;

  assign qb = ~q;

  always @(posedge clk or posedge reset)
  begin
    if (reset) begin
      // Asynchronous reset when reset goes high
      q <= 1'b0;
    end else begin
      // Assign D to Q on positive clock edge
      q <= d;
    end
  end
endmodule

T-Flip Flop

https://www.edaplayground.com/x/Xfg

module tff(input reset, input clk, output reg q);
  always @(posedge clk) 
     if (reset) q<=1'b0; 
     else q<=~q;
endmodule

Finite State Machine

There are two types of finite state machines

  • Mealy State Machine : Its output depends on current state and current inputs.
  • Moore State Machine : Its output depends on current state only.

Leave a Reply

%d bloggers like this: