Showing posts with label HDL. Show all posts
Showing posts with label HDL. Show all posts

Friday, June 15, 2018

HDL

 VHDL

 

Initiated by US Government’s VHSIC   Program in 1980.IBM, TI and Intermetrics started the development of VHDL in 1983

•          VHDL Ver. 7.2 released in 1985

•          IEEE standard 1076-1987 in 1987

•          IEEE 1076-1993 - revision in 1993

•          VHDL is a product of VHSIC program of US Department of Defense (DoD).

 

      VHDL

 

•          Very High Speed Integrated Circuit Hardware Description Language.

 

•          VHDL is an industry standard HDL for the Description, Modeling and Synthesis of digital circuits and systems.

 

•          Can model a digital system at many levels of abstraction  in VHDL.

 

•          The algorithmic or functional level

 

•          Data flow

 

•          Gate level

 

•          Can verify design functionality early in the design process and simulate a design written as a VHDL description.

 

•          Logic Synthesis and optimization converts a VHDL description to a gate level implementation in a given technology.

 

•          Reduces circuit design time and errors.

•          VHDL descriptions provide technology independent documentation for a design and its functionality.

 

•          Power and Flexibility

•          Powerful constructs to write complex logic

•          It has multiples levels of design descriptions

•          It supports design libraries and the creation of reusable components

•          It provides for design hierarchies to create module design

•          Device independent design

•          VHDL permits to create a design without first choosing the device for implementation

•          Portability

•          VHDL is an IEEE standard.

•          Libraries of VHDL models of components can be shared across platforms,tools organization and technical group

•          ASIC Migration

•          Quick time to market and low cost

 

•          VHDL supports design hierarchies

–        A digital system can be modeled as a set of interconnected components

•          It supports flexible design methodologies

–        Top-down , Bottom-up or mixed.

•          VHDL is not technology specific. It can support various hardware technologies

•          It supports both synchronous and asynchronous timing models

•          Various modeling techniques such as FSM, algorithmic and Boolean equations can be modeled  using VHDL.

•          Any large design can be modeled using VHDL

–        No limitation imposed by the size of a design

•          Test benches can be written in VHDL to test other models.

•          Propagation delays, set-up and hold time timing constraints can be described in VHDL

•          Generics and attributes are useful in describing parameterized design

•          Models written in VHDL can be verified by Simulation

•          Behavioral models are capable of being synthesized to gate- level description

 What is the difference between VHDL and Verilog?

Ans:Fundamentally speaking, not a lot. You can produce robust designs and comprehensive test environments with both languages, for both ASIC and FPGA. However, the two languages approach the task from different directions; VHDL, intended as a specification language, is very exact in its nature and hence very verbose. Verilog, intended as a simulation language, it much closer to C in style, in that it is terse and elegant to write but requires much more care to avoid nasty bugs. VHDL doesn't let you get away with much; Verilog assumes that whatever you wrote was exactly what you intended to write. If you get a VHDL architecture to compile, it's probably going to approximate to the function you wanted. For Verilog, successful compilation merely indicates that the syntax rules were met, nothing more. VHDL has some features that make it good for system-level modeling, whereas Verilog is much better than VHDL at gate-level simulation.

 

VHDL   Design units

 

•          Entity

•          Package

•          Configuration

•          Architecture

•          Package body

 

 

  Packages in VHDL

 

•          A package is collection of commonly used subprograms declarations and definitions of objects, function, procedures, components, attributes.

•          Can be shared across designs

•          Package declaration - interface to package

•          Package body - to contain the full code for any functions or procedures which have been declared in the associated package.

•          example of a package is std_logic_1164

•          Package is a collection of 

•          types, constants, subprograms, functions etc.

•          to group a set of

•          related items

•          global information

•          can be shared by many designs

•          A package is made visible with a ‘use ‘clause of the form

 

 

Use lib_name.package_name.item ;

 

 

package is split into declaration and optional body

–        only the declaration  interface is visible to user

 

Package declaration

 

  • Type and subtype declarations
  • Constant declarations
  • Global signal declarations
  • Function and procedure declarations
  • File declarations
  • Component declarations
  • Alias declarations
  • Use clauses

Package declaration

 

Syntax is

 

package package_name is

 constant, procedure, function,

     component declarations

  end package_name ;

 

Package Body

 

•          Associated with a package declaration of the same name

•          Contains the subprogram bodies of functions and procedures declared in the package declaration.

•          Each package can have only one package body. Contain  behavior of the subprograms

•          values of constants etc (deferred)

•          contain the algorithm for any functions or procedures

•          Items in the package body are not visible to other design units

 

Syntax is

 

package body package_name is

   declarations

              constant,procedure,

 function,

component

definitions

            end package_name ;

 

Package

 

Package my_info is

     type prime is (3,5,7,11);

     subtype address is bit_vector(15 downto 0)

     type MVL is(‘U’, ‘0’, ‘1’, ‘z’);

 

end my_info

 

•          package body describe the  behavior

•          clause use is used to access the package

•          items in package is refereed by package name.item name

•          Example

use  my_info.all

 

 

Standard Package

 

•          The STANDARD package

–        Predefines a number of  data types, subtypes and functions which are visible to all design units.

•          It is a part of the language specification.

 

 

Package standard

 

 

Package  STANDARD  is

type BOOLEAN  is ( FALSE, TRUE);

type  BIT  is ( ‘0’ , ‘1’);

type SEVERITY_LEVEL is ( NOTE,WARNING, ERROR , FAILURE );

type INTEGER is range -2147483648    to   + 2147483648  ;

type BIT_VECTOR is array ( Natural range <> ) of BIT;

 type STRING is array  (POSITIVE range <> ) of CHARACTER;

subtype POSITIVE

subtype NATURAL

end  STANDARD;

 

 

Std_logic_1164 package

 

 

•          It is not a part of VHDL standard definition.

•          It contains definitions of  data types, subtypes, and functions which extended VHDL into a multi value logic.

•          IEEE standard # 1164 logic types package.

•          defines types and operations on types for 9 valued logic.

•          Nine valued logic - H, L, Z, X, and other permutation of hard / soft high and low logic levels).

 

 

Std_logic_1164

 

type std_ulogic

–        unresolved logic type of 9 values

type std_ulogic_vector

–         vector of std_ulogic

function resolved

–        resolving a std_ulogic to   std_logic

Subtype std_logic

–         a resolved version of std_ulogic

subtype std_logic_vector

–         a  resolved vector  of std_logic.

•          Conversion functions

–        From std_ulogic   and bit, std_logic_vector and bit_vector  etc.

•          Functions rising edge  and falling edge

–        For edge detection of signals

 

 

Synopyss Packages

 

 

•          Std_logic_1164 Package

•          std_logic_misc Package.

•          std_logic_arith Package

•          Represents numeric values as arrays of numeric values

 

 

Std_logic_arith Package

 

 

•          Contains type conversion functions

•          Allows us to perform arithmetic operations and numeric comparisons on array data types

•          Defines two major data types UNSIGNED and SIGNED.

•          Can use the package for both synthesis and simulation.

•          Can make the std_logic_vector synonymous with either SIGNED or UNSIGNED.

 

 

 use of this package in a VHDL source file

 

 

library IEEE;

use IEEE.std_logic_arith.all;

use IEEE.std_logic_1164.all;

Type definitions for signed and unsigned.

Type unsigned is array ( natural range <> ) of std_logic;

Type signed is array(natural range <> ) of std_logic;

 

 

Unsigned

 

 

•          Represents an unsigned numeric value.

•          Decimal number 8 can be represented as UNSIGNED’(“1000”)

•          A larger vector holds a larger number

•          A four bit vector holds value up to 15

•          A eight bit vector holds value up to 255.

•          Negative numbers cannot be represented in an unsigned variable.

•          Zero is the smallest value that can be represented.

•          MSB is the farthest left array bound.

•          Variable  a : unsigned ( 1 to 10) ;

 signal s1 : unsigned ( 5 downto 0);

 

 

Signed

 

•          Represents a signed numeric value

•          A 2 s complement binary number with the farthest left bit as the sign bit.

•          SIGNED’ (“0101”) --represents +5

•          SIGNED’ (“1101”) --represents - 5

•          A variable or signal can be declared as signed.

•          A large vector holds a large number

•          A four bit variable holds from - 8 to 7

•          A 8 bit variable holds value from -128 to 127

•          variable  v1 : signed( 1to 10 );

•          signal     s1 : signed ( 5 downto 0);

 

 

Std_logic_arith

•          Functions

•          Conversion functions

•          Three sets of  Conversion functions to convert values between UNSIGNED and SIGNED data type and integer.

•          The conv_Integer functions

•          The conv_unsigned and conv_signed

•          Arithmetic Functions

•          For use with combinations of unsigned and signed and the predefined types std_ulogic and integer.

 

 

Functions

 

 

•          Comparison Functions

•          Functions to compare unsigned and signed data types to each other and to predefined data type integer.

•          Shift Functions

•          For shifting the bits in signed and unsigned numbers

•          SHL --shift left logical

•          SHR - -shift right logical.

 

Numeric packages

 

•          Numeric_bit

–        Based on arrays with elements of type bit .

•          Numeric_std

–        Based on arrays with elements of type std_logic.

•          Making the packages visible

library IEEE;

use IEEE.numeric_std.all;

use IEEE.std_logic_1164.all;

 

 

numeric-std

 

•          Package defines two  data types

Signed,unsigned

•          Are arrays of element type std_logic.

•          Type signed represents 2’S complement signed numbers

•          Type unsigned represents unsigned magnitudes

•          Range of a number is defined by the number of bits used in the array representation

 

Signed and Unsigned

 

•          Signal a :signed ( 7 downto 0);

•          signal b : unsigned ( 7 downto 0 );

•          Both declarations create 8 bit buses

•          First Declaration will be interpreted as a signed number with the range -128 to 127.

•          Second declaration will be interpreted as an unsigned number with the range 0 to 255.

•          Arrays are read from left to right , with the MSB on the left.

 

Package Declaration

 

•          Package part_list is

component xor2

generic prop_delay : time := 2 ns;

port (a,b : in bit ; c : out bit) ;

end component;

component  and2

port (a,b : in bit ; c : out bit) ;

end component;

end part_list

•          compile this package to work library

 

Package Example

 

Package  example  is

   procedure mux2to1(signal select   :  in bit;

        signal din0    :  in bit;

        signal din1   :  in bit;

        signal d_out :  out bit);

 end example ;

Package body example is

   procedure mux2to1( signal select   :  in bit;

        signal din0 :  in bit;

        signal din1 :  in bit;

        signal d_out :  out bit) is

 

Package body

 

begin

    case select  is

          when ‘0’ =>

                 d_out <= din0;

          when others =>

                 d_out <= din1;

     end case;

   end mux2to1;

end example;

 

 

VHDL Language elements

 

•          Comments

•          Comments are useful for documentation

•          Give suitable comments wherever needed

“ - - ” comments starts with two hyphens

           extends to the end of line or “CR”

     --    This is a VHDL comment ended with a  CR

            -- VHDL do not support block comments

Example:comments

entity dff  is                              --entity name

port(din ,clk : in bit;     -- inputs

                 q  : out bit);                         --output

end dff;

architecture behv of dff is

begin

process(clk) begin        -- process is executed when CLK changes

if(clk’event and clk =‘1’) then        --rising edge of clock

q<= din;

end if;

end process

end behv;

 

VHDL Language elements

 

 

•          Identifier

–         reserved words/ keywords

–        user defined names - basic identifier &

                                         extended identifier

Identifier

 

•          should start with a letter

•          can have underscore and digits- but last

 character can  not be “ _”

•          Identifiers are case insensitive

 

•          Examples

Data, data, daTa  represent  same identifier

1data , -data _data are data_ are wrong identifiers

mysignal and my_signal are different identifiers

 

 

Extended Identifier

 

•          Identifier between two backslashes

•          extended  identifier is case sensitive

•          Examples

\Myvhdl\ and \MyVHDL\ are different identifier

\-35\, \_cs17\ , \cs17_\ are valid identifiers

\$@!-- \\ __\ supported

Count and \Count\ are different identifiers

 

Keywords

 

•          Keywords are special identifiers reserved to define the language constructs.

•          A list of some keywords in VHDL is as follows

•          entity   case                 if                    else

•          when    loop                 process            nor

•          xnor     nand                or                    and

•          exit      alias                 block              array

•          begin    after                 generic architecture

 

Non legal identifiers

 

_tx_clk            identifier must start with a letter

 8b10b identifier must start with a letter

Large#number  letters, digits & under scores

Link_bar__      2 under scores in succession                            are       not allowed

Select             VHDL reserved words              

RXclk_          Last character cannot be an  _

 

VHDL General syntax

 

•          VHDL is  case insensitive.

•          The semicolon is used to indicate termination of a statement.

•          Two dashes (--) are used to indicate the start of a comment.

•          Identifiers must begin with a letter, subsequent characters must be alphanumeric or’_’ underscore.

•          VHDL is a strongly typed language.

 

 

Number System

 

•          Literal numbers in the base of

10  - decimal

 2  - binary

16 - hexadecimal

•          a point represents a real number

•          Examples  - decimal literal numbers

default base is  10

0, 1, 123_456_789, 98E5- integer

0.0, 233.5, 3.74, 98E-5 - real                                                                                  

1.23E-11,1.0E+4,3.024E+23   -real literal with exponent      

 

 

Based literal

 

•          Base is explicitly indicated

•          base and exponent are decimal numbers

•          alphabets are case insensitive

•          Examples

2#1000_0001#, 16#81#

2#1.1111_1111_1111#E+11, 16#F.Ff#E2

16#fc#, 16#6#E1

 

 

Character and string literals

 

•          Literal characters by single quote

•          Examples

‘A’  ‘a’ ‘#’  ‘q’

 

String Literals

 

•          Strings by double quotes

•          Example

“This is a String”

“Is this string “” quoted””?”

•          Examples for Bit strings

b”1000_0001” o”123”  x”3E”

 

 

Architecture in VHDL

 

 

Syntax

 

•           architecture architecture_name of entity_name is

 [arch_item declarative_part]

begin

[arch_statement_part]

end [architecture_name];

 

•          Declarative part - items for construction as

–        signals

–        components

–        data types

–        subprograms.

 

Concurrent statements define the relationship between the inputs and outputs.

 

•               Concurrent signal assignment

•               Process statement

•               Component instantiation

•               Concurrent procedure call

•               Generate  statement

 

Dataflow:

Example

architecture data_flow of ha_add is

begin

  sum   <=  x  xor  y;

  carry <=  x  and  y ;

end  data_flow;

 

architecture data_flow  of   full_add   is

begin

sum   <= x  xor y  xor z ;

carry <=(x and y)or(x and z)or (y and z );

end  data_flow;

 

VHDL Structural description

 

supports hierarchical  design

supports top down and bottom to top design flow

supports mixed mode

defines a system as collection of hierarchical modules

Structural designs consists of VHDL netlists.

Components are instantiated and connected together with signals

 

architecture structural of ha_add is

begin

x1:xorg port map(x,y, sum );

a2:andg port map(x,y,carry);

end structural;

 

 

Library:

 

•          A library is a place to which design units may be complied.

•          Entity declaration and architecture body pairs may be complied  into a library.

Design units  within a library may be used with other entities, provided that the library and design unit are visible.

 

 

Predefined libraries:

 

•          STD

–         Contains standard packages

•          Components:

–        STANDARD and  TEXTIO.

–        Automatically included in every design   unit

•          WORK

–        User  specified packages are                            stored in    WORK    library.

IEEE library;

•          Is a storage place for IEEE standard design units such as the packages std_logic_1164, numeric_std and numeric_bit.

•          The library must be made visible by way of a library clause.  library IEEE ;

•          The components, packages, declarations, functions and procedures within a library must be made visible via a use clause

    Use IEEE. Std_logic_1164. all ;

 

 

Components

 

•          A component represents an entity architecture pair.

•          Components are design entities that can be instantiated in another architecture leading to hierarchical description.

•          A component must be declared before it is instantiated

 

 Component declaration:

 

 Component component_name[is]

      generic( generic_list);

       port ( port_list);

 end component_name;

•          The component can be defined in a Package, design entity , architecture or block declarations.

•          Components can be declared in the declaration portion of the architecture.

•          Components can be declared in a package.

 

 

Component instantiation

 

 

•          Introduces a subsystem declared elsewhere, either as a component or as an entity_architecture pair.

•          The name of the instantiated component must match the name of the declared component.

•          The instantiated component is called with actual parameters for generics & ports.

 

Configuration

 

•          A configuration declaration is  used to bind entity statements to particular architecture body to form components of a design.

•          Configuration allows the late binding of components after multiple architecture bodies have been written and complied.

•          A configuration declaration (identified with the configuration keyword) specifies which architectures are to be bound to the entity.

•          It allows you to change how components are connected in your design description at the time of simulation

 

 

Default configuration

 

•          Configuration declarations are always optional.

•          The VHDL standard specifies  a default configuration .

•          In the case where there are more than one architecture for an entity, the last architecture complied will take precedence, and will be bound to the entity.

 

 

 

Configuration syntax

 

Configuration configuration_name of   entity_name is

         -- configuration declarations

 for architecture_name

      for instance_label :  component_name

         use entity library_name. entity_name                                                                 (arch_name);

             end for;

-- other for clauses

end for;

Syntax:

Configuration configuration_name of                         entity_name is

    -- configuration declarations

 for architecture_name

    for instance_label :  component_name

      use configuration  library_name.                                                               config_name;

             end for;

end for;

 

Configuration rsffcon2  of rsff   is

    for  behave

    end  for;

end  rsffcon2;

 

                       

Entity in VHDL

 

 

•          Provides the port information

–        Describes the interface of the design entity.

•          The interface includes all inputs, outputs and bi-directional signals and generics.

•          Declares the design  name.

•          A declarative part to declare Subprograms, types and constants .

–         Declarations are visible to all the architectures assigned to the entity.

•          An entity may contain its own passive statements.

 

 

Entity syntax:

 

 

Entity  entity_name is

[generic;]

[port;]

[begin]

[entity statements;]

end [entity_name];

 

 

Ports:

 

 

•          Each I/O signal in an entity declaration is a port.

•          Must have a name , a direction (mode) and a data type.

•          A port is a data object(signal).

•          It can be assigned values and used in expressions.

 

 

Port Data Types

  

•          Pre defined 

–        Boolean

–         bit

–         bit_vector

–         integer.

•          IEEE std_logic_1164 

–        std_ulogic , std_logic              

–        std_logic_vectors.

 

 

Modes:

 

•          In  - input port,  read only

•          out - output port , write only

•          inout - bi-directional port, read/write,

multiple drivers

•          buffer - read and update,  single driver

 

 

Modelling the behavioura way;

 

•          Architecture body

–        describes an implementation of an entity

–        may be several per entity

•          Behavioral architecture

–        describes the algorithm performed by the module

–        contains

•          process statements, each containing

–        sequential statements, including

•          signal assignment statements and

•          wait statements

 

 

 Modelling the structural way:

 

 

•          Structural architecture

–        implements the module as a composition of subsystems

–        contains

•          signal declarations, for internal interconnections

–        the entity ports are also treated as signals

•          component instances

–        instances of previously declared entity/architecture pairs

•          port maps in component instances

–        connect signals to component ports

 

 

Mixed behavior and structure

 

 

•          An architecture can contain both behavioral and structural parts

–        process statements and component instances

•          collectively called concurrent statements

–        processes can read and assign to signals

•          Example: register-transfer-level (RTL) Model

–        data path described structurally

–        control section described behaviorally

 

 

Testbench

 

 

•          Testing a design by simulation

•          Use a test bench model

–        a Model that uses your Model

–        apply test sequences to your inputs

–        monitors values on output signals

•          either using simulator

•          or with a process that verifies correct operation

•          or logic analyzer

 

 

 

entity declaration

 

 

           entity  add4  is

           port

           ( a     :   in  std_logic_vector(3 downto 0);

             b     :    in  std_logic_vector(3 downto 0);

             ci    :    in  std_logic;

           sum  : out  std_logic_vector(3 downto 0);

            co    :   out  std_logic);

           end add4;

 

           entity and 2 is         --and gate

             port (a,b    :  in bit;

                              y  : out bit);

           end and2;

           architecture dataflow of and2 is

           Begin

           y<=a and b;

           end dataflow;

 

Generics:

 

•          Part of entity header

•          generic are constants

•          passed to entity during simulation

•          used to control the behavior of entity

•          Generics are inputs. It is read only

•          Generic values can be overridden

 

 

Use:

To specify the size of ports.

The number of sub components within a   block.

The timing characteristics of a block.

Physical characteristics of a design

The width of the vectors

 

Syntax:

•              Generic ( generic_interface_list);

 

Where do you declare Generics?

 

 

                Generics can be declared in entities and component declarations.

The value of a generic constant can be specified using the generic map ( ) when the component is instantiated.

The value can also be specified when the component is declared.

  Component xor2

     generic ( gate_delay : time  := 6 ns);

If both are specified , then the value provided by the generic map ( ) takes precedence

 

 

Entity gen_gates is

 

     generic ( delay :  time := 10 ns );

     port ( in1 , in2  :  in std_logic;

              output      :  out std_logic);

end gen_gates;

Architecture gates of gen_gates is

  begin

     output <= in1 or in2 after delay;

  end gates;

 

 

Examples

 

 

generic rise_time : time;     -- not specified

generic count : natural := 10;

generic prop-delay : time := 5 nS;

•          use keyword generic map to assign value while instantiation

 

Parameterized model

Architecture generic_delay of half_adder is

component xor2

 generic( gate_delay : time);

 port  ( a ,b : in std_logic ;   c     : out std_logic);

end component;

component and2

generic ( gate_delay : time );

port ( a, b : in std_logic;   c :   out std_logic);

end component;

begin

x : xor2  generic map( gate_delay => 6 ns)  port map ( a ,b, sum);

a1 : and2 generic map ( gate_delay => 6 ns) port map ( a ,b , carry);

end generic_delay;

 

 

 

Passing values of generics through multiple levels of hierarchy

 

 

entity half_adder is

 generic ( gate_delay : time := 3 ns);

  port ( a ,b  :  in std_logic;

          sum , carry :  out  std_logic’ );

end half_adder;

Architecture gen_delay2  of  half_adder  is

component  xor2

  generic( gate_delay : time);

  port  ( a ,b : in  std_logic ;    c     : out   std_logic);

end component;

component and2

  generic ( gate_delay : time );

  port ( a, b : in std_logic;       c :   out std_logic);

end component

 

Concurrent statements

 

•          Concurrent signal assignment

•          Conditional signal assignment

•          Selected signal assignment.

•          Component Instantiation

•          Process statements

•          Generate statement

•          Block statement

•          Concurrent procedure and function calls.

•          Data flow model the functionality

•          Use concurrent signal assignment statements

•          An architecture body can have any number of concurrent statements

•          Ordering of statements are unimportant

•          Are activated whenever any of the signals in the RHS of the <= changes their value.

 

•          Multiple assignments to the same signal  create multiple drivers.The type of the signal must be of resolved type

 

Data flow modeling

 

•          Example    2 input AND gate

 

entity and2 is

port (a, b : in bit; c : out bit);

end and2;

architecture and2 of and2 is

begin

     c <= a and b after 2 ns;

end and2;

•          Example  Full Adder

entity FA is

port( a_in, b_in , cy_in : in bit;

         sum_out, cy_out : out bit);

end FA;

architecture FA of FA is

begin

     sum_out <= a_in xor b-in xor cy_in;

     cy_out <= (a_in and b_in) or (b_in and cy_in) or (a_in and cy_in);

end Fa;

 

•          Select from different values based the expression

•          Sensitive to expression and signals

•          Expression are not evaluated in sequence

•          All possible values of the expression must be covered

•          Use others for uncovered values

•          Similar to case in process

     Selected signal assignment

 

     With choice_expression select     target <= expression when choices,   expression when choices;

           entity mux421 is

 

            port( a,b,c,d : in  std_logic_vector(3 downto 0);

                     s : in  std_logic_vector(1 downto 0);

                     o : out  std_logic_vector(3 downto 0));

           end  mux421;

           Architecture mux_a of mux421 is

           begin

                with s select

                         o <=  a  when”00”,

                                   b when”01”,

                                   c when”10”,

                                   d when others;

            end mux_a;

selective signal aasignment

Architecture buf_a  of  tri_state_buf  is

begin

with en select

buf_out <= buf_in when ‘1’ ,

                   ‘Z’ when others;

end buf_a;

Conditional signal assignment

 

•          Select from different values based on conditions

•          Sensitive to signals or  conditions

•          Conditions are checked one by one

•          Output is assigned based on the first true condition

•          Equivalent if elsif else end if in  process

When_else

•          Conditional signal assignment

•          A signal is assigned a value based on a condition being TRUE.

signal_name <=

               value_ a when condition1  else

               value_b when condition2   else

               value_X;

 

Conditional signal assignment

 

architecture conditional of tri_state_buf is

begin

buf_out  <=  buf_in  when( en = ‘1’) else                                  ‘Z’;

end  conditional;

A conditional signal assignment must end with an unconditional else expression.

           architecture mux421_a of mux421 is

           begin

                 o  <=   a   when (s  = “00”) else

                            b   when (s  = “01”) else

                            c   when (s  = “10”) else

                            d;

           end mux421_a;

 

  Data objects in VHDL

 

•          Hold values of specific type.

•          There are three  classes of data objects.

                         Constants

                         Signals

                         Variables .

They must be declared before they are used

 

Constant

 

 

 

•          Can hold a single value type

•          Assigned during simulation start

•          Can not be altered during simulation run

•          Used to improve the readability of the code.

•          Constants may be declared in package, entity, architecture or process declarative regions.

•          Make it easier to modify the code.

•          Deferred constant- missing initial value

•          Constant   constant_name    :    type :=  value;

Examples

constant pi : real := 3.1417;

constant delay : time := 5 nS;

constant max_width : integer := 64;

constant width:integer  :=31;

constant   period  : time   := 50 ns;

 

Variable

 

•          A data  object with a single current  value.

•          Variable   variable_name  :   type;

•          Variable   variable_name  :  type  :=  initial_value;

•          Value of variable can be modified by assignment statement

•          Must be declared  only in the declarative regions of a process or sub program.

•          Scope of the variable is limited to the process or subprogram they are defined in.

 

Examples

 

1. Variable count : natural := 0;

2. Variable status : bit_vector(0 to 7);

3. Variable no_error : boolean := true;

Note : -

in 2- the default value is 0

in 3 false if not specified

 

Signals

 

•          An object with a past history of value.

•          Holds a list of values

•          Includes the current value

•          A set of possible future values

•          Future values assigned using signal assignment statement

•          Signals are equivalent to wires and are used to inter connect components.

•           Entity Ports are signals .

•          Can represent the state of memory elements.

•          Signals do not change instantaneously

 

Signal declaration

 

•          signal  signal_name  : type;

•          signal signal_name : type  :=  initial_value;

•          Signal   temp  :   std_logic;

•          signal   count  :   bit_vector( 2 downto 0 )  := “000”;

•          type      state is ( idle ,s0, s1);

•          signal  present_state , next_state  :  state;

 

Signal declaration

 

•          Can be explicitly declared in the declarative part of

•          Package   are visible in all design entities using the package

•          Architecture-    signals are visible inside the architecture only

•          Block–        signals  are restricted to the block

•          A port declaration in an entity is an implicit signal declaration.

–        Signal is visible to all architectures assigned to that entity.

•          Signal declared as ports have modes.

•          But locally declared signals can be read and written.

 

Alias

 

•          Declare an alternative name for 

–        full object or  part of object

•          The object can be constant, signal, variable , file.

•          Example

signal path : bit_vector (15 downto 0);

alias command :bit_vector(2 downto 0) is path(15 downto 13);

alias reg_adr : bit_vector(4 downto 0) is path(12 downto 8);

alias reg_data : bit_vector(7 downto 0) is path(7 downto 0);

 

Variable assignment

 

•          Replaces the current value of the variable by a new value determined by an expression.

                        Variable_name := expression;

•          Variable assignment is instantaneous.

•          :=  delimiter is used to define variable assignment.

                Current_state := s4;

 

Example:Variable

entity dummy is

end dummy;

architecture var of dummy is

  signal trigger, sum: integer:=0;

begin

  process

  variable var1: integer:=1;

  variable var2: integer:=2;

  variable var3: integer:=3;

  begin

    wait on trigger;

    var1 := var2 + var3;

    var2 := var1;

    var3 := var2;

    sum <= var1 + var2 + var3;

  end process;

end var ;

 

Signal Assignment

 

 

•          Schedules a new value for a signal to occur at some future time.

•          The current value of a signal is never changed.

•          Signal assignment statements can appear inside

–        a process(Sequential signal assignment) or

–        directly in an architecture(Concurrent signal assignment).

•          Signal assignments are delayed.

            X1 <= ‘1’ after 5 ns;

     d2  <=  ‘1’;  -- Delta delay.

•          <= indicates signal assignment.

Example:signal

entity dummy is

end dummy;

architecture sig of dummy is

  signal trigger, sum: integer:=0;

  signal sig1: integer:=1;

  signal sig2: integer:=2;

  signal sig3: integer:=3;

begin

  process

  begin

    wait on trigger;

    sig1 <= sig2 + sig3;

    sig2 <= sig1;

    sig3 <= sig2;

    sum <= sig1 + sig2 + sig3;

  end process;

end sig;

 

Signals vs Variables

 

•          Variables are declared within process,subprograms.

•          Signals are declared within architecture bodies,packages and block declaration. They are used as ports for VHDL entities.

•          Signal assignment  <=

•          Variable assignment  :=

•          Variable assignment is immediate;

•          Signal assignments are delayed.

 

Expressions and operators

 

•          Expression are  similar to  C expressions

•          Formula combining  primaries and operators

•          Primaries are

»        objects,

»        literal,

»        functions

•          Operators are

»        logical

»        relational

»        shift

»        arithmetic

 

VHDL Operators

 

•          Logical           and       or       nand       nor       xor          xnor

•          Relational        =        /=           <           <=        >              >=

•          Shift                sll         srl       sla          sra       rol           ror

•          Addition           +          -          &      

•          Unary               +           -

•          Multiplying      *           /           mod       rem

•          Miscellaneous  **        abs       not

 

Logical operators

 

•          AND, OR, NAND, NOR, XOR, XNOR

•          Predefined for the types bit or Boolean and

   for one dimensional arrays of bits and Boolean of equal length.

•          Arrays

•          Operation is applied between corresponding elements

•          Result is an array of same length

•          Operators AND .OR and XOR are associative

•          Operator NAND and NOR are not associative

•          Example

 NAND   NAND c  ; --  is illegal

signal  a,b,c : bit_vector( 2 downto 0);

signal d,e,f,g : bit_vector( 1 downto 0);

signal h,I,j,k : bit; signal l,m,n,o,p : Boolean

a <= b and c;

d <= e or f or g;

h <= (I nand j) nand k;

l <= (m xor n) and (o xor p);

•          Identify the common errors

–        1)  h <= I and j or k

–        2) L <= m nand n nand o nand p;

•          Parenthesis is required.

–        3) a <= b and e;

•          Operands must be of same size.

 

Relational operators

 

= Equality        /= Inequality

< Less                          <= less  than or equal to

> greater     >= greater  than or equal to

–        Result of relational operator  is Boolean - (true or false)

–        Both operands should be same type

–        = /= operates on any type except files

–        Other  operands work on Scalar or one dimensional arrays

–        The comparison starts from left to right

–        Smaller operands are patched with 0   to match the size

–        Examples

bit_vector (‘1’, ‘0’,’1’) > bit_vector (‘1’,’0’,’0’);

string “We” <  “Our”;

‘X’ > ‘Z’ ;

type atod is (‘A’, ‘B’, ‘C’, ‘D’);

 then atod` ‘A’ < atod`‘D’;

                          atod`’C’ > atod`’B’;

Shift operators

 

•          Sll  Shift left logical

•          srl  Shift right logical

•          sla  Shift left arithmetic

•          sra Shift right arithmetic

•          rol  rotate left logical

•          ror rotate right logical

•          Syntax is

•          b <= a SLL 1;

–        The left operand type is a one dimensional array whose element type is of BIT or Boolean.

–        The right operand is of type integer representing the shift distance.

–        The result type is same as that of the left operand type.

All left operands are bit_vectors.

“1001010”SLL 2

 0101000 --shifted bits are filled with 0

“1001010”SRL 3

“0001001”.

“1001010” SLA 2

“0101000” --filled with right most bit

“1001010” SRA 3

“1111001” --filled with ‘1’ which is the left most bit.

“1001010” ROL 2

“0101010”

“1001010” ROR3

“0101001”

 

Arithmetic operators

 

•          +  Addition  of same numeric type

•          - Subtraction of same numeric type

•          The left operand , the right operand and the result will be of the same numeric data type

•          * Multiplication -- integer multiplication

•          / Division

•          Work on integers, physical and floating point

•          Mod ( Modulus)  works on integers

•          The result will have the sign of second operand

•          rem works on integers

The result will have the sign of first operand

Unary operators

•          Has only one operand

•          Operators + and - are predefined for all integer data types.

•          The operator (-) negates its operand.

•          Signal a,b : integer range -8 to 6;

•          A <= -b;

 

Example:

entity example is

port( x,y  :  in bit_vector( 3 downto 0);

                q1 :  out bit_vector(4 downto 0)

           q2,q3 : out bit_vector(3 downto 0);

              q4 : out bit_vector(7 downto 0);

end example ;

architecture behv of example is

begin

process(x,y) begin

q1<= (‘0’ & x ) + ( ‘0’ &  y);             --addition

q2<= x-y;                                       --subtraction

q3<=x/y;                                        --division

q4<=x*y;                                       --multiplication

end process;

end behv ;

 

Concentanation

 

•          Predefined adding operator for any one dimensional array type.

•          & Concatenation operator  works on one-dimensional arrays.

–        The right array is appended to the left array to form a new array

•          Examples

‘0’ & ‘1’  will result “01”

“BA” & “LL”  will result “BALL”

Examples:

Signal a,d : bit_vector( 3 downto 0);

signal b,c,g : bit_vector( 1 downto 0);

signal e : bit_vector(2 downto 0);

signal f,h,I :bit;

signal j,k,l : integer range 0 to 3;

a <= not b  &  not c;-- array & array

d <= not e &not f; -- array & element

g <= h & I; -- element & element

j <= k + l -- addition.

 

Miscellaneous operators

 

•          abs  absolute - works on any numeric type

•          Not is a miscellaneous operator

–        ‘0’ is treated as false

–        ‘1’ is treated as true

•          **  Exponential

•          Integer or floating point as the left operand

•          integer as the right operand

•          Integer can not have negative right operand

 

                                           Data types in VHDL

 

VHDL allows data to be represented in terms of high-level data types.These data types can represent individual wire in a circuit, or can represent collections of wires using a concept called an array.

 

A data type is a named set of values.

The data type of an object specifies what values the object may have and limits the kinds of operation that may be performed on objects of that type.

VHDL is a strongly typed language ie data objects of different base types cannot be assigned to one another without the use of a type conversion function.

Every data type in VHDL has a defined set of values, and a defined set of valid operations. Scalar data types have simple, single values. 

Scalar data types include enumeration data types  numeric data types ( integer and real) and physical data types.

Scalar types have an order, which allows relational operators to be used with them.Data objects of scalar types can only hold  one value at the current simulation time.Floating point type and physical types are not supported by synthesis tools.

 

                  BIT

 

It can be used in any VHDL specification without any additional declarations.

Signal  s1 , s2  : bit;

     ……..

   s1  <= ‘1’;

   s2 <=  not s1;

      ……..

Any additional  assignment to s1 or s2 is illegal.

 

STD_ULOGIC

A nine value unresolved logic is not a part of VHDL standard.It is defined in IEEE std_logic_1164 package.

 

It is not permitted to specify two value assignments to a signal of type std_ulogic.The values 0, 1 , L, H, Z & don’t care are supported for synthesis.The IEEE 1164 standard defines arrays of std_logic as std_logic_vector.VHDL also provides subtypes, which are defined as subsets of other types.

 

Anywhere a type definition can appear, a subtype definition can also appear.

 

The difference between a type and a subtype is that a subtype is a subset of a previously defined parent (or basetype or subtype.

 

All operators and functions defined for std_ulogic can be applied to std_logic.Std_logic is the industry standard type and in practice it is recommended to declare signals to be of type std_logic.A resolution function in the form of a look up table determines the values of multiple driven signals.

 

   Data type;Integer

 

The integer type is a scalar type whose set of values includes integer numbers of the specified range.

Type type_name is  range integer_left_bound  to                    integer_right_bound;

type type_name is  range integer_left_bound  downto             integer_right_bound;

All integer types have the same set of arithmetic operators defined in the package STANDARD.

Both the operands and the result are of integer type

Relational operations can also be checked on integer operands.

For logic synthesis, signals or variables of integer type should be constrained with a range.

 

  Integer;sub type

 

VHDL also provides subtypes, which are defined as subsets of other types.Anywhere a type definition can appear, a subtype definition can also appear. The difference between a type and a subtype is that a subtype is a subset of a previously defined parent (or basetype or subtype.Sub type is a type with a constraint.

 

Positive is a integer data type whose values are a set of positive integers ( from 1 to maximum positive integer).

 

Natural is a integer data type whose values are a set of natural integers ( from 0 to maximum positive integer).Are defined in package standard.

 

Floating point

 

Floating point type values are used to approximate real numbers.Floating point types can be constrained. The only pre-defined floating type is real which included the range –1.0E 38 to + 1.0E 38.All floating point types have the same set of arithmetic operators namely addition , subtraction, multiplication, division, ABS and exponentiation.Floating point types are not often supported in synthesis tools.

 

 

    Data types:Physical

 

A physical type is a numeric scalar that represents some quantity like length, time,pressure, resistance etc.The range defines the minimum and maximum values of a given quantity expressed in the base units.

The primary unit(um) serves as the base unit  for representing values of the specified type.The secondary units  are defined as multiplicity of primary units.Their declarations may contain only integer literals.Only relational and arithmetic operators can be used with objects of physical data type.

Physical types are not synthesizable. The VHDL standard predefines only one physical type TIME in the STANDARD package.The  primary unit is femto seconds (fs).All the other secondary units are specified in terms of the base unit.

 

Data type: Arrays

 

Array is a composite object whose elements are of the same type.VHDL supports N-dimensional arrays. Array elements can be of any type. An array has an index whose value selects each element. The index range determines how many elements are in the array and their ordering (low to high, or high downto low). An index can be of any integer type.

 

can declare multidimensional arrays by building one-dimensional arrays where the element type is another one-dimensional array.Each of the element is indexed by one or more indices.An array may be either constrained  or unconstrained.The difference between these two arrays comes from the index range in the array type definition. The array is constrained if the size of the array is constrained

A constrained array’s index range is explicitly defined; for example, an integer range (0 to 7).

Define an unconstrained array’s index range as a type, for example, INTEGER. This definition implies that the index range can consist of any contiguous subset of that type’s values.

When you declare an array variable or signal of this type, you also define its actual index range. Different declarations can have different index ranges.

 

There are two predefined array data types.Data type string is an array of character elements. It is used for creating text for printing.

Data type bit_vector is an array of bits. It is used to describe the data stored in a register or the data being  transmitted over a parallel bus.

Type String is array ( positive range < > ) of character ;

Type bit_vector is array (natural range < > ) of bit ;

The index range is placed within parenthesis following the reserved word array. The notation < > means that the range is unconstrained.

 

Bit-vector

 

The bit_vector type is an unconstrained vector of elements of type bit.The size of a particular vector is specified during its declaration.The index can be either a ascending or descending range.

Bit_vector is an unresolved type and there can be only one assignment to an object of bit_vector type in an architecture.

 

Assignments to an object of bit_vector type can be performed using single element assignments, concatenation, aggregates , slices or any combination of them.Logical values for objects of the bit_vector type must be written in double quotes.

 

Data Type-Record

 

Record types are composite types in which the elements may have different types. The elements form an ordered list.An object of a record type has multiple elements of different types. Individual fields of a record can be referenced by element name.

 

Individual Assignments to elements

Each element id referenced by the record object name followed by a dot and elements name.Expression assigned to an element of a record must result in a value of the same type as the element.Constants in VHDL of type record are not supported for synthesis.(the initialization of records is not supported).

 

 PROCEDURAL MODELLING





INITIAL

initial $display(“Hello Verilog");

ALWAYS

always $display("Hello Verilog");

Example:


module three_initial;
initial $display("Initial Statement 1");
initial $display("Initial Statement 2");
initial $display("Initial Statement 3");
endmodule

       creates a race condition at time 0. If it is important to
       have the statements run in a particular order, you can introduce delays to control the order in which the statements are executed.


module three_initial_with_delay;
initial #1 $display("Initial Statement 1");
initial $display("Initial Statement 2");
initial #2 $display("Initial Statement 3");
endmodule


BEGIN END BLOCKS


module initial_begin;
initial
begin
$display("Statement 1");
$display("Statement 2");
$display("Statement 3");
end
endmodule


BEGIN END BLOCKS WITH DELAY


module initial_begin_with_delay;
initial
begin
#1 $display("Statement 1");
$display("Statement 2");
#2 $display("Statement 3");
end
endmodule


MULTIPLE BEGIN-END


module initial_two_begin;
initial
begin
#1 $display("Statement 1");
$display("Statement 2");
#2 $display("Statement 3");
end
initial
begin
$display("Block 2 Statement 1");
#2 $display("Block 2 Statement 2");
#2 $display("Block 2 Statement 3");
end
endmodule


FORK-JOIN


       The fork-join block is similar to the begin-end block: It is also used to group statements.
       In begin-end blocks, the statements are sequential, and the delays are additive.
        In fork-join blocks, the statements are concurrent, and the delays are independent, or absolute from the time the fork-join block starts.

module  f;
initial
fork
#1 $display("Statement 1");
$display("Statement 2");
#2 $display("Statement 3");
join
initial
fork
$display("Block 2 Statement 1");
#2 $display("Block 2 Statement 2");
#2 $display("Block 2 Statement 3");
join

         endmodule

 I am citing some of the books that I used during my learning, at my RTL design internship. I think any editions of the books will be good enough.


1.  A VHDL Primer by Jairam Bhaskar
2. Beginner's guide to VHDL by Peter J. Ashenden  (Keep in mind that there is also book called designer's guide to VHDL)
3. VHDL: Programming by Example, Douglas L. Perry
4. VHDL Handbook by Hardi Electronics
5. Digital Design: Principles and Practices by John F. Wakerly (Actually, this book gives good comparisons and examples on HDLs - VHDL, Verilog and ABEL)
6. VHDL Tutorial by Peter J. Ashenden
https://surf-vhdl.com/vhdl-syntax-web-course-surf-vhdl/

There are two types of HDL Languages are VHDL and Verilog HDL. One must be good at the concepts of Digital Logic Design before start learning the HDL.

Follow the lectures Electronics-Digital Circuits and Systems by Prof. Srinivasan, IIT Madras to become familiar with the Digital Logic Design.

Then go for the Hardware Description Language, For VHDL follow the book A VHDL Primer by J.Bhasker to learn all the basic concepts in VHDL. Additionally one can go through the Lectures Eectronics-Digital System Design by Prof. Kuruvilla Varghes, IISc, Bangalore. Refer Lecture (Lec-09 to Lec-22) for VHDL. He will cover most of the topics in VHDL with some examples.

IF you are a basic learners then try to implement the following design examples using Vhdl/verilog:

Combinational circuit examples:

-Implement basic logic gates, simulate and verify the behavior using vhdl/Verilog

-Implement half-adder circuit, simulate and verify the behavior using vhdl/Verilog

-Implement full-adder circuit, simulate and verify the behavior using vhdl/Verilog

-Implement subtractor circuit, simulate and verify the behavior using vhdl/Verilog

-Implement multiplexer, de-multiplexer, simulate and veriry the behavior using vhdl/Verilog

-Implement encoder and decoder circuit, simulate and veriry the behavior using vhdl/Verilog

-Implement binary to grey, and vice-versa, simulate and verify the behavior using vhdl/Verilog

-Implement comparator circuit, simulate and verify the behavior using vhdl/Verilog

-Implement ALU unit, simulate and verify the behavior using vhdl/Verilog

-Implement multiplier/divider, simulate and verify the behavior using vhdl/verilog

-Implement tri-state buffer, simulate and verify the behavior using vhdl/verilog

Sequential circuits examples:

-Implement D-FF circuit with synchronous reset, simulate and verify the behavior using vhdl/verilog,

* Implement D-FF circuit with asynchronous reset, simulate and verify the behavior using vhdl/verilog,

-Implement counter circuit with load, simulate and verify the behavior using vhdl/verilog,

-Implement shift register (SISO, SIPO, PISO, PIPO) using shift operator & concatenation operator, simulate and verify the behavior using vhdl/verilog,

-Implement application of shift-register, simulate and verify the behavior using vhdl/verilog,

Follow the below blogs/forums for more details:

VHDL Syntax Web-Course - Surf-VHDL

Verilog  is a language used for describing a digital system .It means, by using a HDL we can describe any digital hardware at any level. 

Designs, which are described in HDL are independent of technology, very easy for designing and debugging, and are normally more useful than schematics, particularly for large circuits.


Verilog HDL is one of the two most common Hardware Description Languages (HDL) used by integrated circuit (IC) designers. The other one is VHDL.

HDL’s allows the design to be simulated earlier in the design cycle in order to correct errors or experiment with different architectures.

 Designs described in HDL are technology-independent, easy to design and debug, and are usually more readable than schematics, particularly for large circuits.

Verilog can be used to describe designs at four levels of abstraction:

(i) Algorithmic level (much like c code with if, case and loop statements).

(ii) Register transfer level

(iii) Gate level (interconnected AND, NOR etc.).

(iv) Switch level (the switches are MOS transistors inside gates).

The language also defines constructs that can be used to control the input and output of simulation.


  RTL CODING GUIDES

Avoid mixed clock edges
Avoid clock buffers
Avoid gated clocks
Avoid internally generated clocks
Gated clocks and low power designs
Avoid internally generated resets
The preferred clocking structure is
􀃂 A single global clock, and
􀃂 Positive edge-triggered flops as the only sequential devices.

Avoid mixed clock edges


Avoid using both positive-edge and negative-edge triggered flip-flops.
Mixed clock edges can be used for very aggressive timing goals, such as DDR (double data rate).The cares must be taken.
The duty cycle is critical, since it is a critical issue in timing analysis in addition to frequency.
Scan-based testing requires separate handing of positive and negative triggered flops.

Avoid clock buffers

Avoid hand instantiating clock buffers in RTL code.
Clock buffers are morally inserted after synthesis as port of the physical design.
In synthesizable RTL code, clock nets are normally considered ideal nets, with no delays.
During place and route, the clock tree insertion tool inserts the appropriate structure for creating as close to an ideal, balanced clock distribution network as possible.

Avoid Gated clock


Avoid coding gated clocks in RTL,since clock gating circuits tend to be
technology specific and timingdependent.
Improper timing of a gate clock can cause
A false clock or glitch,
Set-up and hold time violation.

Gated clocks and low power designs

Keep the clock and/or reset generation circuitry (for a gate clock,an internally generated clock or reset) as a separate module at the top level.
Partition the design so that all the logic in a single module uses a single clock and a single reset.
Isolating clock and reset generation logic in a separate module enables
to use the standard timing analysis and scan insertion techniques.

Avoid internally generated resets


Avoid internally generated,conditional reset if possible.
 Generally, all the registers in the macro should be reset at the same time.
If a conditional reset is required, create a separate signal for the
reset signal, and isolate the conditional reset logic in a separate module.

module better_style (rst_out, rst_in, a, b);
output rest_out;
input rst_in;
input a, b;
wire rst_out = rst_in | a | b;
endmodule
module better_style (clk, rst);
input clk, rst;
reg [7:0] my_reg;
always @ (posedge clk or rst) begin
if (rst == 1) my_reg = 8’b0;
else begin
end
end
endmodule


Coding for Synthesis

In order to create code that achieves the best compile times and synthesis results.
Testability
Performance
Simplification of static timing analysis
Gate-level circuit behavior that matches that of the original RTLcode

Infer registers
Avoid latches
Avoid combinational feedback
Specify complete sensitivity lists
Blocking and non-blocking assignments
Case statements v.s. if-then-else statements
Coding state machines


  State machine model

  • Values stored in registers are the state of the circuit
  • Combinational logic computes:
    • next state
    • outputs
      • function of current state and inputs (Mealy machine)
      • function of current state only (Moore machine)

State diagram into a logic

  • counter
    • flip-flops to hold state
    • logic to compute next state
    • clock signal controls when flip-flop memory can change
      • wait just long enough for combinational logic to compute new value


  • FSM Design procedure


  • Describe FSM behavior, e.g. state diagram
    • Inputs and Outputs
    • States (symbolic)
    • State transitions

  • State diagram to state transition table, i.e. truth table
    • Inputs: inputs and current state
    • Outputs: outputs and next state

  • State encoding
    • decide on representation of states
    • lots of choices

  • Implementation
    • flip-flop for each state bit
    • synthesize combinational logic from encoded state table

  • Implement simple count sequence: 000, 010, 011, 101, 110
  • Derive the state transition table from the state transition diagram

  • Start-up states
    • at power-up, FSM may be in an used or invalid state
    • design must guarantee that it (eventually) enters a valid state

  • Self-starting solution
    • design FSM so that all the invalid states eventually
    • transition to a valid state may limit exploitation of don't cares
  • Moore:  outputs depend on current state only
  • Mealy:  outputs may depend on current state and current inputs

Design of sequential circuit can be composed of designing combinational circuit and state register. Sequential circuits are implemented in two different ways:
  1. Mealy Machine
  2. Moore Machine

Mealy Machine
In case of Mealy machine, output is a function of not only the present inputs but also past inputs. In other words we can say; in case of Mealy, both output and the next state depends on the present input and the present state.

Moore Machine
In case of Moore machine, present output is not a function of present inputs but is a function of past inputs. The next state is a function of both the present input and the present state.

In this case the output is not associated with the transition but are associated with the state unlike the Mealy machine. This is because the output “O” is a function of present state (PS) and independent of present input “I”.

Of-course present input I influences the next state (NS) and that’s how it is going to influence the output but there is a time lag between the input and output. The present inputs are going to influence the outputs that are going to come after the next clock.

        



FINITE STATE MACHINES


Moore machines are useful because their output signals are synchronized with the clock.

No matter when input signals reach the Moore Machine, its output signals will not change until the rising
edge of the next clock cycle. This is very important to avoid setup timing violations.


For example, if a Mealy machine’s input signal(s) changes sometime in the middle of a clock cycle, one or more of its outputs and next state signals may change some time later. “Some time later” might come after the setup time threshold for the next rising edge.


If this happens, the registers that will hold the FSMs next state may receive garbage, or just incorrect inputs. Obviously, this amounts to a bug(s) in  FSM


The tradeoff in using the Moore machine is that sometimes the Moore machine will require more states to specify its function than the Mealy machine. This is because in a Moore machine, output signals are only dependent on the current state.

 In a Mealy machine, outputs are dependent on both the current state and the inputs.

The Mealy machine allows you to specify different output behavior for a single state.


We will need a way to express the following in Verilog:

1. A state encoding for each state.
2. A mechanism for keeping track of the current state.
3. Transitions from state to state.
4. Output values based on the current state.

We will construct the FSM one step at a time.


1.     Creating a State Encoding

     We will create our state encoding with Verilog parameters. Parameters are symbolic constants with
either global (given by the Verilog keyword parameter) or module (localparam) scope.

Because we only want our state encoding to be visible to the module in which we will write the FSM, we will use the latter: localparam.

localparam STATE_Initial = 3’d0 ,
 STATE_1 = 3’d1 ,
STATE_2 = 3’d2 ,
STATE_3 = 3’d3 ,
 STATE_4 = 3’d4;


In Program 1, the 3’d notation indicates that the number specified is in the decimal radix. If we were
to use 3’b, the encoding would look like that shown in Program 2. Both implementations are equivelent.
Base 10, or 3’d, is typically easier to read.

Because this FSM has 5 total states, we must allocate 3 bits to specify the encoding (hence 3’d
as opposed to 2’d or 4’d. This is extremely important. If you specify too few bits for your state
encoding, Verilog will not warn you. In fact, when synthesized, each state will only get as many bits as you provide. For example, if STATE_4 was specified like this: STATE_4 = 2’d4, STATE_4 would be specified as 00, the bottem 2 bits of what was intended, namely 100.

PROGAM2


localparam STATE_Initial = 3’b000 ,
STATE_1 = 3’b001 ,
STATE_2 = 3’b010 ,
STATE_3 = 3’b011 ,
STATE_4 = 3’ b100 ;


As 3 bits can specify a total of 8 states (0-7), our encoding specifies 3 potential states not specified
as being actual states.


There are several ways of dealing with this problem:


1. Ignore it, and always press Reset as a way of initializing the FSM.
2. Specify these states, and make non-conditional transitions from them to the STATE_Initial.
To reduce ambiguity, we will choose the second option, which makes our final state encoding that
shown in Program 3.

localparam STATE_Initial = 3’d0 ,
STATE_1 = 3’d1 ,
STATE_2 = 3’d2 ,
STATE_3 = 3’d3 ,
STATE_4 = 3’d4 ,
STATE_5_PlaceHolder = 3’d5 ,
STATE_6_PlaceHolder = 3’d6 ,
STATE_7_PlaceHolder = 3’d7;



This is a simple encoding: STATE_Initial is assigned 0, STATE_1 is assigned 1, etc. This is not optimal if state minimization can be performed on the FSM .

We do not recommend applying state minimization techniques by hand, however. They have the tendancy to introduce bugs and create cryptic FSMs that cannot be easily understood by human readers. This defeats one of the large pros of Verilog: human readability. Furthermore, the Synthesis tools that ‘compile’ an FSM, written in Verilog, perform state minimization automatically. Only perform state minimization manually to the extent that the function of the FSM remains clear.

The first option is to instantiate a module that acts as a register and use its output value as our current state. Alternatively, we can create a reg element of the appropriate width and use its value as our current state. We will use the second method for the remainder of this tutorial, out of personal preference. As such, we will store the current state as depicted reg [2:0] CurrentState ;


Module instantiation


Register #( . Width ( ...) )
SentReg (. Clock ( ...) , // Input port
 Reset ( ...) , // Input port
Set( ...) , // Input port
Enable (...) , // Input port
In( ...) , // Input port
Out( ...) ); // OUTPUT port

Module declaration

module MyModule (In , Out);

 parameter Width = 32;

 input [Width -1:0] In , Out;

endmodule

wire elements are simple wires (or busses/bit-vectors of arbitrary width) in Verilog designs.

The following are syntax rules when using wires:

1. wire elements are used to connect input and output ports of a module instantiation together with
some other element in your design.
2. wire elements are used as inputs and outputs within an actual module declaration.
3. wire elements must be driven by something, and cannot store a value without being driven. In
other words, wire elements are a stateless way of connecting two peices in a Verilog-based design.
4. wire elements cannot be used as the left-hand side of an = or <= sign in an always@ block.
5. wire elements are the only legal type on the left-hand side of an assign statement.
6. wire elements can only be used to model combinational logic.

Legal uses of the wire element


wire A, B, C, D, E; // simple 1-bit wide wires
wire [8:0] Wide ; // a 9-bit wide wire
 reg I;

 assign A = B & C; // using a wire with an assign statement

always @(B or C) begin
I = B | C; // using wires on the right - hand side of an always@
// assignment
end

mymodule MyModule (. In (D), // using a wire as the input of a module
Out(E)); // using a wire as the output of a module

reg Elements (Combinational and Sequential logic)

reg are similar to wires, but can be used to store information (‘state’) like registers. The following are
syntax rules when using reg elements.

1. reg elements can be connected to the input port of a module instantiation. Note that reg cannot
connect to the output port of a module instantiation.
2. reg elements can be used as outputs within an actual module declaration. Note that reg cannot
be used as inputss within an actual module declaration.
3. reg is the only legal type on the left-hand side of an always@ block = or <= sign.
4. reg is the only legal type on the left-hand side of an initial block = sign (used in Test Benches).
5. reg cannot be used on the left-hand side of an assign statement.
6. reg can be used to create registers when used in conjunction with always@(posedge Clock) blocks.
7. reg can, therefore, be used to create both combinational and sequential logic.


wire A, B;
reg I, J, K; // simple 1-bit wide reg elements
reg [8:0] Wide ; // a 9-bit wide reg element

always @(A or B) begin
 I = A | B; // using a reg as the left - hand side of an always@
// assignment
end
initial begin // using a reg in an initial block
J = 1’b1;
#1
J = 1’b0;
end

 always @( posedge Clock ) begin
K <= I; // using a reg to create a positive -edge - triggered register
end


wire and reg elements can be used interchangably in certain situations:

1. Both can appear on the right-hand side of assign statements and always@ block = or <= signs.
2. Both can be connected to the input ports of module instantiations.



Transitioning from State to State

After we have established our state encoding and a means of storing the current state value (which will henceforth be referred to as CurrentState), our next task is to create a way for the FSM to actually change state, and for it to choose how to change state. This material requires that you be comfortable with always@ blocks

always@ Blocks

always@ blocks are used to describe events that should happen under certain conditions. always@ blocks are always followed by a set of parentheses, a begin, some code, and an end. Program 9 shows a skeleton always@ block.

always @( ... sensitivity list ... ) begin
 elements ...
end

Elements in an always@ block are set/updated in sequentially and in parallel, depending on the type
of assignment used. There are two types of assignments: <= (non-blocking) and = (blocking).

Non-blocking assignments happen in parallel. In other words, if an always@ block contains multiple <=
assignments, which are literally written in Verilog sequentially, you should think of all of the assignments being set at exactly the same time

always @( ... sensitivity list ... ) begin
B <= A;
 C <= B;
 D <= C;
 end

                             specifies a circuit that reads “when the sensitivity list is satisfied, B gets A’s value, C gets B’s old value, and D gets C’s old value.” The key here is that C gets B’s old value, etc (read: think OLD value!. This ensures that C is not set to A, as A is B’s new value, at the instant of the always@ block’s
execution. Non-blocking assignments are used when specifying sequential2 logic

Blocking assignments happen sequentially. In other words, if an always@ block contains multiple =
assignments, you should think of the assignments being set one after another.


always @( ... sensitivity list ... ) begin
B = A;
C = B;
D = C;
end

“when the sensitivity list is satisfied, B gets A, C gets B, and D gets C.” But, by the time C gets B, B has been set to A. Likewise, by the time D gets C, C has been set to B, which, as we stated above, has been set to A. This always@ block turns B, C, and D into A. Blocking assignments are used when specifying combinational logic

always@(posedge Clock) (“always at the positive edge of the clock”) or always@(negedge Clock) (“always
at the negative edge of the clock”) blocks are used to describe Sequential Logic, or Registers.

Only <= (non-blocking) assignments should be used in an always@(posedge Clock) block. Never use =
(blocking) assignments in always@(posedge Clock) blocks.

Only use always@(posedge Clock) blocks when you want to infer an element(s) that changes its value at the positive or negative edge of the clock.


always @( posedge Clock ) begin
B <= A;
 C <= B;
D <= C;
 end


always@( * ) blocks are used to describe Combinational Logic, or Logic Gates. Only = (blocking)
assignments should be used in an always@( * ) block. Never use <= (non-blocking) assignments in
always@( * ) blocks. Only use always@( * ) block when you want to infer an element(s) that changes
its value as soon as one or more of its inputs change.

Always use ‘*’ (star) for your sensitivity list in always@( * ) blocks. The sensitivity list specifies
which signals should trigger the elements inside the always@ block to be updated.


“when A or B change values, update the value of every element inside the always@( * ) block. In this case, the only element inside the always@( * ) block is C, which in this case is assigned the and of A and B. A very common bug is to introduce an incomplete sensitivity list. In other words, ‘*’ sets the sensitivity list to any values that can have an impact on a value(s) determined by the always@( * ) block. ‘*’ provides a bug-free shorthand for creating complete sensitivity lists.

The following are some easy-to-make mistakes in Verilog that can have a dramatic [and undesired]
effect on a circuit

Consider the shift register from Figure .

 If you place = assignments inside of an always@(posedge Clock) block to produce the shift register, you instead get the parallel registers shown in Figure and Program .

we might also get one register, whose output is tied to B, C and D. Both possible outcomes are equivelent. These circuit make sense, but don’t create shift registers! (As shift registers are common construct, we assume that you wanted to create a shift register)


  
always @( posedge Clock ) begin
B = A;
C = B;
D = C;
 end


We place <= assignments inside of always@(* ) is less pronounced. In this case, just consider what type of circuit you want to create: do you want all statements to be executed in parallel or in ‘sequence.

In the always@( * ), the distinction between <= and = is sometimes very subtle, as the point of always@
( * ) is to trigger at indefinite times (unlike the very definite posedge Clock).

We recommend =in conjunction with always@( * ) to establish good convention (as = was originally meant to be associated with combinational logic).

always @( * ) begin
B <= A;
 C <= B;
 D <= C;
end


An always@( * ) block that will not generate latches



 wire Trigger , Pass ;
 reg A, C;

 always @( * ) begin
 A = 1’b0;
C = 1’b1;
if ( Trigger ) begin
A = Pass ;
C = Pass ;
 end

FINITE STATE MACHINES


Moore machines are useful because their output signals are synchronized with the clock.

No matter when input signals reach the Moore Machine, its output signals will not change until the rising
edge of the next clock cycle. This is very important to avoid setup timing violations.


For example, if a Mealy machine’s input signal(s) changes sometime in the middle of a clock cycle, one or more of its outputs and next state signals may change some time later. “Some time later” might come after the setup time threshold for the next rising edge.


If this happens, the registers that will hold the FSMs next state may receive garbage, or just incorrect inputs. Obviously, this amounts to a bug(s) in  FSM


The tradeoff in using the Moore machine is that sometimes the Moore machine will require more states to specify its function than the Mealy machine. This is because in a Moore machine, output signals are only dependent on the current state. In a Mealy machine, outputs are dependent on both the current state and the inputs.

The Mealy machine allows you to specify different output behavior for a single state.


We will need a way to express the following in Verilog:

1. A state encoding for each state.
2. A mechanism for keeping track of the current state.
3. Transitions from state to state.
4. Output values based on the current state.

We will construct the FSM one step at a time.


1.     Creating a State Encoding

We will create our state encoding with Verilog parameters. 

Parameters are symbolic constants with either global (given by the Verilog keyword parameter) or module (localparam) scope. Because we only want our state encoding to be visible to the module in which we will write the FSM, we will use the latter: localparam.

localparam STATE_Initial = 3’d0 ,
 STATE_1 = 3’d1 ,
STATE_2 = 3’d2 ,
STATE_3 = 3’d3 ,
 STATE_4 = 3’d4;


In Program 1, the 3’d notation indicates that the number specified is in the decimal radix. If we were
to use 3’b, the encoding would look like that shown in Program 2. Both implementations are equivelent.

Base 10, or 3’d, is typically easier to read.

Because this FSM has 5 total states, we must allocate 3 bits to specify the encoding (hence 3’d
as opposed to 2’d or 4’d. This is extremely important. If you specify too few bits for your state
encoding, Verilog will not warn you. In fact, when synthesized, each state will only get as many bits as
you provide. For example, if STATE_4 was specified like this: STATE_4 = 2’d4, STATE_4 would be specified
as 00, the bottem 2 bits of what was intended, namely 100.

PROGAM2


localparam STATE_Initial = 3’b000 ,
STATE_1 = 3’b001 ,
STATE_2 = 3’b010 ,
STATE_3 = 3’b011 ,
STATE_4 = 3’ b100 ;


As 3 bits can specify a total of 8 states (0-7), our encoding specifies 3 potential states not specified
as being actual states.


There are several ways of dealing with this problem:


1. Ignore it, and always press Reset as a way of initializing the FSM.
2. Specify these states, and make non-conditional transitions from them to the STATE_Initial.
To reduce ambiguity, we will choose the second option, which makes our final state encoding that
shown in Program 3.

localparam STATE_Initial = 3’d0 ,
STATE_1 = 3’d1 ,
STATE_2 = 3’d2 ,
STATE_3 = 3’d3 ,
STATE_4 = 3’d4 ,
STATE_5_PlaceHolder = 3’d5 ,
STATE_6_PlaceHolder = 3’d6 ,
STATE_7_PlaceHolder = 3’d7;



This is a simple encoding: STATE_Initial is assigned 0, STATE_1 is assigned 1, etc. This is not optimal if state minimization can be performed on the FSM .

We do not recommend applying state minimization techniques by hand, however. They have the tendancy to introduce bugs and create cryptic FSMs that cannot be easily understood by human readers. This defeats one of the large pros of Verilog: human readability. Furthermore, the Synthesis tools that ‘compile’ an FSM, written in Verilog, perform state minimization automatically. Only perform state minimization manually to the extent that the function of the FSM remains clear.

The first option is to instantiate a module that acts as a register and use its output value as our current state. Alternatively, we can create a reg element of the appropriate width and use its value as our current state. We will use the second method for the remainder of this tutorial, out of personal preference. As such, we will store the current state as depicted reg [2:0] CurrentState ;


Module instantiation


Register #( . Width ( ...) )
SentReg (. Clock ( ...) , // Input port
 Reset ( ...) , // Input port
Set( ...) , // Input port
Enable (...) , // Input port
In( ...) , // Input port
Out( ...) ); // OUTPUT port

Module declaration

module MyModule (In , Out);

 parameter Width = 32;

 input [Width -1:0] In , Out;

endmodule

wire elements are simple wires (or busses/bit-vectors of arbitrary width) in Verilog designs.

The following are syntax rules when using wires:

1. wire elements are used to connect input and output ports of a module instantiation together with
some other element in your design.
2. wire elements are used as inputs and outputs within an actual module declaration.
3. wire elements must be driven by something, and cannot store a value without being driven. In
other words, wire elements are a stateless way of connecting two peices in a Verilog-based design.
4. wire elements cannot be used as the left-hand side of an = or <= sign in an always@ block.
5. wire elements are the only legal type on the left-hand side of an assign statement.
6. wire elements can only be used to model combinational logic.

Legal uses of the wire element


wire A, B, C, D, E; // simple 1-bit wide wires
wire [8:0] Wide ; // a 9-bit wide wire
 reg I;

 assign A = B & C; // using a wire with an assign statement

always @(B or C) begin
I = B | C; // using wires on the right - hand side of an always@
// assignment
end

mymodule MyModule (. In (D), // using a wire as the input of a module
Out(E)); // using a wire as the output of a module

reg Elements (Combinational and Sequential logic)

reg are similar to wires, but can be used to store information (‘state’) like registers. The following are
syntax rules when using reg elements.

1. reg elements can be connected to the input port of a module instantiation. Note that reg cannot
connect to the output port of a module instantiation.
2. reg elements can be used as outputs within an actual module declaration. Note that reg cannot
be used as inputss within an actual module declaration.
3. reg is the only legal type on the left-hand side of an always@ block = or <= sign.
4. reg is the only legal type on the left-hand side of an initial block = sign (used in Test Benches).
5. reg cannot be used on the left-hand side of an assign statement.
6. reg can be used to create registers when used in conjunction with always@(posedge Clock) blocks.
7. reg can, therefore, be used to create both combinational and sequential logic.


wire A, B;
reg I, J, K; // simple 1-bit wide reg elements
reg [8:0] Wide ; // a 9-bit wide reg element

always @(A or B) begin
 I = A | B; // using a reg as the left - hand side of an always@
// assignment
end
initial begin // using a reg in an initial block
J = 1’b1;
#1
J = 1’b0;
end

 always @( posedge Clock ) begin
K <= I; // using a reg to create a positive -edge - triggered register
end


wire and reg elements can be used interchangably in certain situations:

1. Both can appear on the right-hand side of assign statements and always@ block = or <= signs.
2. Both can be connected to the input ports of module instantiations.



Transitioning from State to State

After we have established our state encoding and a means of storing the current state value (which will
henceforth be referred to as CurrentState), our next task is to create a way for the FSM to actually
change state, and for it to choose how to change state. This material requires that you be comfortable
with always@ blocks

always@ Blocks

always@ blocks are used to describe events that should happen under certain conditions. always@ blocks
are always followed by a set of parentheses, a begin, some code, and an end. Program 9 shows a skeleton always@ block.

always @( ... sensitivity list ... ) begin
 elements ...
end

Elements in an always@ block are set/updated in sequentially and in parallel, depending on the type
of assignment used. There are two types of assignments: <= (non-blocking) and = (blocking).

Non-blocking assignments happen in parallel. In other words, if an always@ block contains multiple <=
assignments, which are literally written in Verilog sequentially, you should think of all of the assignments
being set at exactly the same time

always @( ... sensitivity list ... ) begin
B <= A;
 C <= B;
 D <= C;
 end

                             specifies a circuit that reads “when the sensitivity list is satisfied, B gets A’s value, C gets B’s old value, and D gets C’s old value.” The key here is that C gets B’s old value, etc (read: think OLD value!. This ensures that C is not set to A, as A is B’s new value, at the instant of the always@ block’s
execution. Non-blocking assignments are used when specifying sequential2 logic

Blocking assignments happen sequentially. In other words, if an always@ block contains multiple =
assignments, you should think of the assignments being set one after another.


always @( ... sensitivity list ... ) begin
B = A;
C = B;
D = C;
end

“when the sensitivity list is satisfied, B gets A, C gets B, and D gets C.” But, by the time C gets B, B has been set to A. Likewise, by the time D gets C, C has been set to B, which, as we stated above, has been set to A. This always@ block turns B, C, and D into A. Blocking assignments are used when specifying combinational logic

always@(posedge Clock) (“always at the positive edge of the clock”) or always@(negedge Clock) (“always
at the negative edge of the clock”) blocks are used to describe Sequential Logic, or Registers.

Only <= (non-blocking) assignments should be used in an always@(posedge Clock) block. Never use =
(blocking) assignments in always@(posedge Clock) blocks.

Only use always@(posedge Clock) blocks when you want to infer an element(s) that changes its value at the positive or negative edge of the clock.


always @( posedge Clock ) begin
B <= A;
 C <= B;
D <= C;
 end


always@( * ) blocks are used to describe Combinational Logic, or Logic Gates. Only = (blocking)
assignments should be used in an always@( * ) block. Never use <= (non-blocking) assignments in
always@( * ) blocks. Only use always@( * ) block when you want to infer an element(s) that changes
its value as soon as one or more of its inputs change.

Always use ‘*’ (star) for your sensitivity list in always@( * ) blocks. The sensitivity list specifies
which signals should trigger the elements inside the always@ block to be updated.


“when A or B change values, update the value of every element inside the always@( * ) block. In this case, the only element inside the always@( * ) block is C, which in this case is assigned the and of A and B. A very common bug is to introduce an incomplete sensitivity list. In other words, ‘*’ sets the sensitivity list to any values that can have an impact on a value(s) determined by the always@( * ) block. ‘*’ provides a bug-free shorthand for creating complete sensitivity lists.

The following are some easy-to-make mistakes in Verilog that can have a dramatic [and undesired]
effect on a circuit

Consider the shift register 

 If you place = assignments inside of an always@(posedge Clock) block to produce the shift register, you instead get the parallel registers shown in Figure and Program .

we might also get one register, whose output is tied to B, C and D. Both possible outcomes are equivelent. These circuit make sense, but don’t create shift registers! (As shift registers are common construct, we assume that you wanted to create a shift register)



always @( posedge Clock ) begin
B = A;
C = B;
D = C;
 end


We place <= assignments inside of always@(* ) is less pronounced. In this case, just consider what type of circuit you want to create: do you want all statements to be executed in parallel or in ‘sequence.

In the always@( * ), the distinction between <= and = is sometimes very subtle, as the point of always@
( * ) is to trigger at indefinite times (unlike the very definite posedge Clock).

We recommend =in conjunction with always@( * ) to establish good convention (as = was originally meant to be associated with combinational logic).

always @( * ) begin
B <= A;
 C <= B;
 D <= C;
end


An always@( * ) block that will not generate latches



 wire Trigger , Pass ;
 reg A, C;

 always @( * ) begin
 A = 1’b0;
C = 1’b1;
if ( Trigger ) begin
A = Pass ;
C = Pass ;
 end






72Hz clock generation in verilog
------------------------------------

It depends on whether you’re trying to create a simulated circuit or one for actual synthesis, say, in an FPGA.

For a simulated circuit, it’s as easy as declaring a register, and then toggling it (e.g. x = ~x), followed by a delay of 27778 microseconds, which is half the period of a 72 hz rate ( i.e. “#27777” after having previously declared ‘timescale 1us) in a loop. The key is that the simulator uses the timescale as units for the specified delays, and does the hard work for you of deciding exactly when the next statement should execute.

However, creating real delays in a circuit requires understanding of the hardware. The typical way to create Verilog that would produce a 72hz signal in this case would be to take a clock signal of a known (likely higher) frequency coming from an external source or onboard clock generator, and then create a counter to divide down that clock. When the count reaches the right number, toggle the output and there’s your 72hz clock. For example, let’s assume clk is 1Mhz:

reg (14:0) count; //Need 15 bits to count this high
reg out;

always @(posedge clk)
begin
if (count == 27776) //since started at zero...
  begin
    count <= 0;
    out <= ~out;
  end
else
  begin
    count <= count + 1;
    out <= out;
  end
end
--------------------------------------------------------------------------------------------------------------------------


Verilog code for Clock domain crossing


module clk_2_cross ( clock1, clock2, rst_n, data_in, data_out);
input clock1;
input clock2;
input rst_n;
output data_out;
input  data_in;
reg data_out_meta;
reg [1:0] data_out_reg;
// Assign statements
assign data_out = data_out_reg[1];
// Always block to declare  synchronous logic from source clock domain 
always @ (posedge clock1)
begin
 data_out_meta <= data_in;
end
// Always block to declare synchronous logic in destination clock domain

always @ (posedge clock2 or negedge rst_n)
begin
 if (! rst_n)
     data_out_reg <= 'b0;
 else
  // Implement shift register for two flops.   
  data_out_reg <= {data_out_reg[0], data_out_meta};
end
endmodule
// Note: Above shift register can also be implemented // like below:
// data_out_reg[0] <= data_out_meta;
// data_out_reg[1] <= data_out_reg[0];

====================================================================


 Verilog code for flip-flop with a positive-edge clock.

        module flop (clk, d, q);
        input  clk, d;
        output q;
        reg    q;
               always @(posedge clk)
        begin
           q <= d;
        end
        endmodule
 
       
Verilog code for a flip-flop with a negative-edge clock and asynchronous clear.

        module flop (clk, d, clr, q);
        input  clk, d, clr;
        output q;
        reg    q;
        always @(negedge clk or posedge clr)
        begin
           if (clr)
              q <= 1’b0;
           else
              q <= d;
        end
        endmodule
       
Verilog code for the flip-flop with a positive-edge clock and synchronous set.
        module flop (clk, d, s, q);
        input  clk, d, s;
        output q;
        reg    q;
        always @(posedge clk)
        begin
           if (s)
              q <= 1’b1;
           else
              q <= d;
        end
        endmodule
       
Verilog code for the flip-flop with a positive-edge clock and clock enable.
        module flop (clk, d, ce, q);
        input  clk, d, ce;
        output q;
        reg    q;
        always @(posedge clk)
        begin
           if (ce)
              q <= d;
        end
        endmodule
       
Verilog code for a 4-bit register with a positive-edge clock, asynchronous set and clock enable.
        module flop (clk, d, ce, pre, q);
        input        clk, ce, pre;
        input  [3:0] d;
        output [3:0] q;
        reg    [3:0] q;
        always @(posedge clk or posedge pre)
        begin
           if (pre)
              q <= 4’b1111;
           else if (ce)
              q <= d;
        end
        endmodule
       
 Verilog code for a latch with a positive gate.
        module latch (g, d, q);
        input  g, d;
        output q;
        reg    q;
        always @(g or d)
        begin
           if (g)
              q <= d;
        end
        endmodule
       
Verilog code for a latch with a positive gate and an asynchronous clear.

        module latch (g, d, clr, q);
        input  g, d, clr;
        output q;
        reg    q;
        always @(g or d or clr)
        begin
           if (clr)
              q <= 1’b0;
           else if (g)
              q <= d;
        end
        endmodule
  
Verilog code for a 4-bit latch with an inverted gate and an asynchronous preset.
        module latch (g, d, pre, q);
        input        g, pre;
        input  [3:0] d;
        output [3:0] q;
        reg    [3:0] q;
        always @(g or d or pre)
        begin
           if (pre)
              q <= 4’b1111;
           else if (~g)
              q <= d;
        end
        endmodule
       
Following is Verilog code for a tristate element using a combinatorial process and always block.
        module three_st (t, i, o);
        input  t, i;
        output o;
        reg    o;
        always @(t or i)
        begin
           if (~t)
              o = i;
           else
              o = 1’bZ;
        end
        endmodule
       
Following is the Verilog code for a tristate element using a concurrent assignment.
        module three_st (t, i, o);
        input  t, i;
        output o;
           assign o = (~t) ? i: 1’bZ;
        endmodule
       
Following is the Verilog code for a 4-bit unsigned up counter with asynchronous clear.
        module counter (clk, clr, q);
        input        clk, clr;
        output [3:0] q;
        reg    [3:0] tmp;
        always @(posedge clk or posedge clr)
        begin
           if (clr)
              tmp <= 4’b0000;
           else
              tmp <= tmp + 1’b1;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for a 4-bit unsigned down counter with synchronous set.
        module counter (clk, s, q);
        input        clk, s;
        output [3:0] q;
        reg    [3:0] tmp;
        always @(posedge clk)
        begin
           if (s)
              tmp <= 4’b1111;
           else
              tmp <= tmp - 1’b1;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for a 4-bit unsigned up counter with an asynchronous load from the primary input.
        module counter (clk, load, d, q);
        input        clk, load;
        input  [3:0] d;
        output [3:0] q;
        reg    [3:0] tmp;
        always @(posedge clk or posedge load)
        begin
           if (load)
              tmp <= d;
           else
              tmp <= tmp + 1’b1;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for a 4-bit unsigned up counter with a synchronous load with a constant.
        module counter (clk, sload, q);
        input        clk, sload;
        output [3:0] q;
        reg    [3:0] tmp;
        always @(posedge clk)
        begin
           if (sload)
              tmp <= 4’b1010;
           else
              tmp <= tmp + 1’b1;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for a 4-bit unsigned up counter with an asynchronous clear and a clock enable.
        module counter (clk, clr, ce, q);
        input        clk, clr, ce;
        output [3:0] q;
        reg    [3:0] tmp;
        always @(posedge clk or posedge clr)
        begin
           if (clr)
              tmp <= 4’b0000;
           else if (ce)
              tmp <= tmp + 1’b1;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for a 4-bit unsigned up/down counter with an asynchronous clear.
        module counter (clk, clr, up_down, q);
        input        clk, clr, up_down;
        output [3:0] q;
        reg    [3:0] tmp;
        always @(posedge clk or posedge clr)
        begin
           if (clr)
              tmp <= 4’b0000;
           else if (up_down)
              tmp <= tmp + 1’b1;
           else
              tmp <= tmp - 1’b1;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for a 4-bit signed up counter with an asynchronous reset.
        module counter (clk, clr, q);
        input               clk, clr;
        output signed [3:0] q;
        reg    signed [3:0] tmp;
        always @ (posedge clk or posedge clr)
        begin
           if (clr)
              tmp <= 4’b0000;
           else
              tmp <= tmp + 1’b1;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for a 4-bit signed up counter with an asynchronous reset and a modulo maximum.
        module counter (clk, clr, q);
        parameter MAX_SQRT = 4, MAX = (MAX_SQRT*MAX_SQRT);
        input                 clk, clr;
        output [MAX_SQRT-1:0] q;
        reg    [MAX_SQRT-1:0] cnt;
        always @ (posedge clk or posedge clr)
        begin
           if (clr)
              cnt <= 0;
           else
              cnt <= (cnt + 1) %MAX;
        end
           assign q = cnt;
        endmodule
       
Following is the Verilog code for a 4-bit unsigned up accumulator with an asynchronous clear.
        module accum (clk, clr, d, q);
        input        clk, clr;
        input  [3:0] d;
        output [3:0] q;
        reg    [3:0] tmp;
        always @(posedge clk or posedge clr)
        begin
           if (clr)
              tmp <= 4’b0000;
           else
              tmp <= tmp + d;
        end
           assign q = tmp;
        endmodule
       
Following is the Verilog code for an 8-bit shift-left register with a positive-edge clock, serial in and serial out.
        module shift (clk, si, so);
        input        clk,si;
        output       so;
        reg    [7:0] tmp;
        always @(posedge clk)
        begin
           tmp    <= tmp << 1;
           tmp[0] <= si;
        end
           assign so = tmp[7];
        endmodule
       
Following is the Verilog code for an 8-bit shift-left register with a negative-edge clock, a clock enable, a serial in and a serial out.
        module shift (clk, ce, si, so);
        input        clk, si, ce;
        output       so;
        reg    [7:0] tmp;
        always @(negedge clk)
        begin
           if (ce) begin
              tmp    <= tmp << 1;
              tmp[0] <= si;
           end
        end
           assign so = tmp[7];
        endmodule
       
Following is the Verilog code for an 8-bit shift-left register with a positive-edge clock, asynchronous clear, serial in and serial out.
        module shift (clk, clr, si, so);
        input        clk, si, clr;
        output       so;
        reg    [7:0] tmp;
        always @(posedge clk or posedge clr)
        begin
           if (clr)
              tmp <= 8’b00000000;
           else
              tmp <= {tmp[6:0], si};
        end
           assign so = tmp[7];
        endmodule
       
Following is the Verilog code for an 8-bit shift-left register with a positive-edge clock, a synchronous set, a serial in and a serial out.
        module shift (clk, s, si, so);
        input        clk, si, s;
        output       so;
        reg    [7:0] tmp;
        always @(posedge clk)
        begin
           if (s)
              tmp <= 8’b11111111;
           else
              tmp <= {tmp[6:0], si};
        end
           assign so = tmp[7];
        endmodule
       
Following is the Verilog code for an 8-bit shift-left register with a positive-edge clock, a serial in and a parallel out.
        module shift (clk, si, po);
        input        clk, si;
        output [7:0] po;
        reg    [7:0] tmp;
        always @(posedge clk)
        begin
           tmp <= {tmp[6:0], si};
        end
           assign po = tmp;
        endmodule
       
Following is the Verilog code for an 8-bit shift-left register with a positive-edge clock, an asynchronous parallel load, a serial in and a serial out.
        module shift (clk, load, si, d, so);
        input        clk, si, load;
        input  [7:0] d;
        output       so;
        reg    [7:0] tmp;
        always @(posedge clk or posedge load)
        begin
           if (load)
              tmp <= d;
           else
              tmp <= {tmp[6:0], si};
        end
           assign so = tmp[7];
        endmodule
       
Following is the Verilog code for an 8-bit shift-left register with a positive-edge clock, a synchronous parallel load, a serial in and a serial out.
        module shift (clk, sload, si, d, so);
        input        clk, si, sload;
        input  [7:0] d;
        output       so;
        reg    [7:0] tmp;
        always @(posedge clk)
        begin
           if (sload)
              tmp <= d;
           else
              tmp <= {tmp[6:0], si};
        end
           assign so = tmp[7];
        endmodule
       
Following is the Verilog code for an 8-bit shift-left/shift-right register with a positive-edge clock, a serial in and a serial out.
        module shift (clk, si, left_right, po);
        input        clk, si, left_right;
        output       po;
        reg    [7:0] tmp;
        always @(posedge clk)
        begin
           if (left_right == 1’b0)
              tmp <= {tmp[6:0], si};
           else
              tmp <= {si, tmp[7:1]};
        end
           assign po = tmp;
        endmodule
       
Following is the Verilog code for a 4-to-1 1-bit MUX using an If statement.
        module mux (a, b, c, d, s, o);
        input        a,b,c,d;
        input  [1:0] s;
        output       o;
        reg          o;
        always @(a or b or c or d or s)
        begin
           if (s == 2’b00)
              o = a;
           else if (s == 2’b01)
              o = b;
           else if (s == 2’b10)
              o = c;
           else
              o = d;
        end
        endmodule
       
Following is the Verilog Code for a 4-to-1 1-bit MUX using a Case statement.
        module mux (a, b, c, d, s, o);
        input        a, b, c, d;
        input  [1:0] s;
        output       o;
        reg          o;
        always @(a or b or c or d or s)
        begin
           case (s)
              2’b00   : o = a;
              2’b01   : o = b;
              2’b10   : o = c;
              default : o = d;
           endcase
        end
        endmodule
       
Following is the Verilog code for a 3-to-1 1-bit MUX with a 1-bit latch.
        module mux (a, b, c, d, s, o);
        input        a, b, c, d;
        input  [1:0] s;
        output       o;
        reg          o;
        always @(a or b or c or d or s)
        begin
           if (s == 2’b00)
              o = a;
           else if (s == 2’b01)
              o = b;
           else if (s == 2’b10)
              o = c;
        end
        endmodule
       
Following is the Verilog code for a 1-of-8 decoder.
        module mux (sel, res);
        input  [2:0] sel;
        output [7:0] res;
        reg    [7:0] res;
        always @(sel or res)
        begin
           case (sel)
              3’b000  : res = 8’b00000001;
              3’b001  : res = 8’b00000010;
              3’b010  : res = 8’b00000100;
              3’b011  : res = 8’b00001000;
              3’b100  : res = 8’b00010000;
              3’b101  : res = 8’b00100000;
              3’b110  : res = 8’b01000000;
              default : res = 8’b10000000;
           endcase
        end
        endmodule
       
Following Verilog code leads to the inference of a 1-of-8 decoder.
        module mux (sel, res);
        input  [2:0] sel;
        output [7:0] res;
        reg    [7:0] res;
        always @(sel or res) begin
           case (sel)
              3’b000  : res = 8’b00000001;
              3’b001  : res = 8’b00000010;
              3’b010  : res = 8’b00000100;
              3’b011  : res = 8’b00001000;
              3’b100  : res = 8’b00010000;
              3’b101  : res = 8’b00100000;
              // 110 and 111 selector values are unused
              default : res = 8’bxxxxxxxx;
           endcase
        end
        endmodule
       
Following is the Verilog code for a 3-bit 1-of-9 Priority Encoder.
        module priority (sel, code);
        input  [7:0] sel;
        output [2:0] code;
        reg    [2:0] code;
        always @(sel)
        begin
           if (sel[0])
              code = 3’b000;
           else if (sel[1])
              code = 3’b001;
           else if (sel[2])
              code = 3’b010;
           else if (sel[3])
              code = 3’b011;
           else if (sel[4])
              code = 3’b100;
           else if (sel[5])
              code = 3’b101;
           else if (sel[6])
              code = 3’b110;
           else if (sel[7])
              code = 3’b111;
           else
              code = 3’bxxx;
        end
        endmodule
       
Following is the Verilog code for a logical shifter.
        module lshift (di, sel, so);
        input  [7:0] di;
        input  [1:0] sel;
        output [7:0] so;
        reg    [7:0] so;
        always @(di or sel)
        begin
           case (sel)
              2’b00   : so = di;
              2’b01   : so = di << 1;
              2’b10   : so = di << 2;
              default : so = di << 3;
           endcase
        end
        endmodule
       
Following is the Verilog code for an unsigned 8-bit adder with carry in.
        module adder(a, b, ci, sum);
        input  [7:0] a;
        input  [7:0] b;
        input        ci;
        output [7:0] sum;
       
           assign sum = a + b + ci;

        endmodule
       
Following is the Verilog code for an unsigned 8-bit adder with carry out.
        module adder(a, b, sum, co);
        input  [7:0] a;
        input  [7:0] b;
        output [7:0] sum;
        output       co;
        wire   [8:0] tmp;

           assign tmp = a + b;
           assign sum = tmp [7:0];
           assign co  = tmp [8];

        endmodule
       
Following is the Verilog code for an unsigned 8-bit adder with carry in and carry out.
        module adder(a, b, ci, sum, co);
        input        ci;
        input  [7:0] a;
        input  [7:0] b;
        output [7:0] sum;
        output       co;
        wire   [8:0] tmp;

           assign tmp = a + b + ci;
           assign sum = tmp [7:0];
           assign co  = tmp [8];

        endmodule
       
Following is the Verilog code for an unsigned 8-bit adder/subtractor.
        module addsub(a, b, oper, res);
        input        oper;
        input  [7:0] a;
        input  [7:0] b;
        output [7:0] res;
        reg    [7:0] res;
        always @(a or b or oper)
        begin
           if (oper == 1’b0)
              res = a + b;
           else
              res = a - b;
        end
        endmodule
       
Following is the Verilog code for an unsigned 8-bit greater or equal comparator.
        module compar(a, b, cmp);
        input  [7:0] a;
        input  [7:0] b;
        output       cmp;

           assign cmp = (a >= b) ?  1’b1 : 1’b0;

        endmodule
       
Following is the Verilog code for an unsigned 8x4-bit multiplier.
        module compar(a, b, res);
        input  [7:0]  a;
        input  [3:0]  b;
        output [11:0] res;

           assign res = a * b;

        endmodule
       
Following Verilog template shows the multiplication operation placed outside the always block and the pipeline stages represented as single registers.
        module mult(clk, a, b, mult);
        input         clk;
        input  [17:0] a;
        input  [17:0] b;
        output [35:0] mult;
        reg    [35:0] mult;
        reg    [17:0] a_in, b_in;
        wire   [35:0] mult_res;
        reg    [35:0] pipe_1, pipe_2, pipe_3;

           assign mult_res = a_in * b_in;

        always @(posedge clk)
        begin
           a_in   <= a;
           b_in   <= b;
           pipe_1 <= mult_res;
           pipe_2 <= pipe_1;
           pipe_3 <= pipe_2;
           mult   <= pipe_3;
        end
        endmodule
       
Following Verilog template shows the multiplication operation placed inside the always block and the pipeline stages are represented as single registers.
        module mult(clk, a, b, mult);
        input         clk;
        input  [17:0] a;
        input  [17:0] b;
        output [35:0] mult;
        reg    [35:0] mult;
        reg    [17:0] a_in, b_in;
        reg    [35:0] mult_res;
        reg    [35:0] pipe_2, pipe_3;
        always @(posedge clk)
        begin
           a_in     <= a;
           b_in     <= b;
           mult_res <= a_in * b_in;
           pipe_2   <= mult_res;
           pipe_3   <= pipe_2;
           mult     <= pipe_3;
        end
        endmodule
       
Following Verilog template shows the multiplication operation placed outside the always block and the pipeline stages represented as single registers.
        module mult(clk, a, b, mult);
        input         clk;
        input  [17:0] a;
        input  [17:0] b;
        output [35:0] mult;
        reg    [35:0] mult;
        reg    [17:0] a_in, b_in;
        wire   [35:0] mult_res;
        reg    [35:0] pipe_1, pipe_2, pipe_3;

           assign mult_res = a_in * b_in;

        always @(posedge clk)
        begin
           a_in   <= a;
           b_in   <= b;
           pipe_1 <= mult_res;
           pipe_2 <= pipe_1;
           pipe_3 <= pipe_2;
           mult   <= pipe_3;
        end
        endmodule
       
Following Verilog template shows the multiplication operation placed inside the always block and the pipeline stages are represented as single registers.
        module mult(clk, a, b, mult);
        input         clk;
        input  [17:0] a;
        input  [17:0] b;
        output [35:0] mult;
        reg    [35:0] mult;
        reg    [17:0] a_in, b_in;
        reg    [35:0] mult_res;
        reg    [35:0] pipe_2, pipe_3;
        always @(posedge clk)
        begin
           a_in     <= a;
           b_in     <= b;
           mult_res <= a_in * b_in;
           pipe_2   <= mult_res;
           pipe_3   <= pipe_2;
           mult     <= pipe_3;
        end
        endmodule
       
Following Verilog template shows the multiplication operation placed outside the always block and the pipeline stages represented as shift registers.
        module mult3(clk, a, b, mult);
        input         clk;
        input  [17:0] a;
        input  [17:0] b;
        output [35:0] mult;
        reg    [35:0] mult;
        reg    [17:0] a_in, b_in;
        wire   [35:0] mult_res;
        reg    [35:0] pipe_regs [3:0];

           assign mult_res = a_in * b_in;

        always @(posedge clk)
        begin
           a_in <= a;
           b_in <= b;
           {pipe_regs[3],pipe_regs[2],pipe_regs[1],pipe_regs[0]} <=
           {mult, pipe_regs[3],pipe_regs[2],pipe_regs[1]};
        end
        endmodule
       
Following templates to implement Multiplier Adder with 2 Register Levels on Multiplier Inputs in Verilog.
        module mvl_multaddsub1(clk, a, b, c, res);
        input         clk;
        input  [07:0] a;
        input  [07:0] b;
        input  [07:0] c;
        output [15:0] res;
        reg    [07:0] a_reg1, a_reg2, b_reg1, b_reg2;
        wire   [15:0] multaddsub;
        always @(posedge clk)
        begin
           a_reg1 <= a;
           a_reg2 <= a_reg1;
           b_reg1 <= b;
           b_reg2 <= b_reg1;
        end
           assign multaddsub = a_reg2 * b_reg2 + c;
           assign res = multaddsub;
        endmodule
       
Following is the Verilog code for resource sharing.
        module addsub(a, b, c, oper, res);
        input        oper;
        input  [7:0] a;
        input  [7:0] b;
        input  [7:0] c;
        output [7:0] res;
        reg    [7:0] res;
        always @(a or b or c or oper)
        begin
           if (oper == 1’b0)
              res = a + b;
           else
              res = a - c;
        end
        endmodule
       
Following templates show a single-port RAM in read-first mode.
        module raminfr (clk, en, we, addr, di, do);
        input        clk;
        input        we;
        input        en;
        input  [4:0] addr;
        input  [3:0] di;
        output [3:0] do;
        reg    [3:0] RAM [31:0];
        reg    [3:0] do;
        always @(posedge clk)
        begin
           if (en) begin
              if (we)
                RAM[addr] <= di;

              do <= RAM[addr];
           end
        end
        endmodule
       
Following templates show a single-port RAM in write-first mode.
        module raminfr (clk, we, en, addr, di, do);
        input        clk;
        input        we;
        input        en;
        input  [4:0] addr;
        input  [3:0] di;
        output [3:0] do;
        reg    [3:0] RAM [31:0];
        reg    [4:0] read_addr;
        always @(posedge clk)
        begin
           if (en) begin
              if (we)
                RAM[addr] <= di;
              read_addr <= addr;
           end
        end
           assign do = RAM[read_addr];
        endmodule
       
Following templates show a single-port RAM in no-change mode.
        module raminfr (clk, we, en, addr, di, do);
        input        clk;
        input        we;
        input        en;
        input  [4:0] addr;
        input  [3:0] di;
        output [3:0] do;
        reg    [3:0] RAM [31:0];
        reg    [3:0] do;
        always @(posedge clk)
        begin
           if (en) begin
              if (we)
                RAM[addr] <= di;
              else
                do <= RAM[addr];
           end
        end
        endmodule
       
Following is the Verilog code for a single-port RAM with asynchronous read.
        module raminfr (clk, we, a, di, do);
        input        clk;
        input        we;
        input  [4:0] a;
        input  [3:0] di;
        output [3:0] do;
        reg    [3:0] ram [31:0];
        always @(posedge clk)
        begin
           if (we)
              ram[a] <= di;
        end
           assign do = ram[a];
        endmodule
       
Following is the Verilog code for a single-port RAM with "false" synchronous read.
        module raminfr (clk, we, a, di, do);
        input        clk;
        input        we;
        input  [4:0] a;
        input  [3:0] di;
        output [3:0] do;
        reg    [3:0] ram [31:0];
        reg    [3:0] do;
        always @(posedge clk)
        begin
           if (we)
              ram[a] <= di;
           do <= ram[a];
        end
        endmodule
       
Following is the Verilog code for a single-port RAM with synchronous read (read through).
        module raminfr (clk, we, a, di, do);
        input        clk;
        input        we;
        input  [4:0] a;
        input  [3:0] di;
        output [3:0] do;
        reg    [3:0] ram [31:0];
        reg    [4:0] read_a;
        always @(posedge clk)
        begin
           if (we)
              ram[a] <= di;
           read_a <= a;
        end
           assign do = ram[read_a];
        endmodule
       
Following is the Verilog code for a single-port block RAM with enable.
        module raminfr (clk, en, we, a, di, do);
        input        clk;
        input        en;
        input        we;
        input  [4:0] a;
        input  [3:0] di;
        output [3:0] do;
        reg    [3:0] ram [31:0];
        reg    [4:0] read_a;
        always @(posedge clk)
        begin
           if (en) begin
              if (we)
                 ram[a] <= di;
              read_a <= a;
           end
        end
           assign do = ram[read_a];
        endmodule
       
Following is the Verilog code for a dual-port RAM with asynchronous read.
        module raminfr (clk, we, a, dpra, di, spo, dpo);
        input        clk;
        input        we;
        input  [4:0] a;
        input  [4:0] dpra;
        input  [3:0] di;
        output [3:0] spo;
        output [3:0] dpo;
        reg    [3:0] ram [31:0];
        always @(posedge clk)
        begin
           if (we)
              ram[a] <= di;
        end
           assign spo = ram[a];
           assign dpo = ram[dpra];
        endmodule
       
Following is the Verilog code for a dual-port RAM with false synchronous read.
        module raminfr (clk, we, a, dpra, di, spo, dpo);
        input        clk;
        input        we;
        input  [4:0] a;
        input  [4:0] dpra;
        input  [3:0] di;
        output [3:0] spo;
        output [3:0] dpo;
        reg    [3:0] ram [31:0];
        reg    [3:0] spo;
        reg    [3:0] dpo;
        always @(posedge clk)
        begin
           if (we)
              ram[a] <= di;

           spo = ram[a];
           dpo = ram[dpra];
        end
        endmodule
       
Following is the Verilog code for a dual-port RAM with synchronous read (read through).
        module raminfr (clk, we, a, dpra, di, spo, dpo);
        input        clk;
        input        we;
        input  [4:0] a;
        input  [4:0] dpra;
        input  [3:0] di;
        output [3:0] spo;
        output [3:0] dpo;
        reg    [3:0] ram [31:0];
        reg    [4:0] read_a;
        reg    [4:0] read_dpra;
        always @(posedge clk)
        begin
           if (we)
              ram[a] <= di;
           read_a <= a;
           read_dpra <= dpra;
        end
           assign spo = ram[read_a];
           assign dpo = ram[read_dpra];
        endmodule
       
Following is the Verilog code for a dual-port RAM with enable on each port.
        module raminfr (clk, ena, enb, wea, addra, addrb, dia, doa, dob);
        input        clk, ena, enb, wea;
        input  [4:0] addra, addrb;
        input  [3:0] dia;
        output [3:0] doa, dob;
        reg    [3:0] ram [31:0];
        reg    [4:0] read_addra, read_addrb;
        always @(posedge clk)
        begin
           if (ena) begin
              if (wea) begin
                ram[addra] <= dia;
              end
           end
        end

        always @(posedge clk)
        begin
           if (enb) begin
              read_addrb <= addrb;
           end
        end
           assign doa = ram[read_addra];
           assign dob = ram[read_addrb];
        endmodule
       
Following is Verilog code for a ROM with registered output.
        module rominfr (clk, en, addr, data);
        input       clk;
        input       en;
        input [4:0] addr;
        output reg [3:0] data;
        always @(posedge clk)
        begin
           if (en)
              case(addr)
                 4’b0000: data <= 4’b0010;
                 4’b0001: data <= 4’b0010;
                 4’b0010: data <= 4’b1110;
                 4’b0011: data <= 4’b0010;
                 4’b0100: data <= 4’b0100;
                 4’b0101: data <= 4’b1010;
                 4’b0110: data <= 4’b1100;
                 4’b0111: data <= 4’b0000;
                 4’b1000: data <= 4’b1010;
                 4’b1001: data <= 4’b0010;
                 4’b1010: data <= 4’b1110;
                 4’b1011: data <= 4’b0010;
                 4’b1100: data <= 4’b0100;
                 4’b1101: data <= 4’b1010;
                 4’b1110: data <= 4’b1100;
                 4’b1111: data <= 4’b0000;
                 default: data <= 4’bXXXX;
              endcase
        end
        endmodule
       
Following is Verilog code for a ROM with registered address.
        module rominfr (clk, en, addr, data);
        input       clk;
        input       en;
        input [4:0] addr;
        output reg [3:0] data;
        reg   [4:0] raddr;
        always @(posedge clk)
        begin
           if (en)
              raddr <= addr;
        end

        always @(raddr)
        begin
           if (en)
              case(raddr)
                4’b0000: data = 4’b0010;
                4’b0001: data = 4’b0010;
                4’b0010: data = 4’b1110;
                4’b0011: data = 4’b0010;
                4’b0100: data = 4’b0100;
                4’b0101: data = 4’b1010;
                4’b0110: data = 4’b1100;
                4’b0111: data = 4’b0000;
                4’b1000: data = 4’b1010;
                4’b1001: data = 4’b0010;
                4’b1010: data = 4’b1110;
                4’b1011: data = 4’b0010;
                4’b1100: data = 4’b0100;
                4’b1101: data = 4’b1010;
                4’b1110: data = 4’b1100;
                4’b1111: data = 4’b0000;
                default: data = 4’bXXXX;
              endcase
        end
        endmodule
       
Following is the Verilog code for an FSM with a single process.
        module fsm (clk, reset, x1, outp);
        input        clk, reset, x1;
        output       outp;
        reg          outp;
        reg    [1:0] state;
        parameter s1 = 2’b00; parameter s2 = 2’b01;
        parameter s3 = 2’b10; parameter s4 = 2’b11;
        always @(posedge clk or posedge reset)
        begin
           if (reset) begin
              state <= s1; outp <= 1’b1;
           end
           else begin
              case (state)
                s1: begin
                       if (x1 == 1’b1) begin
                          state <= s2;
                           outp  <= 1’b1;
                       end
                       else begin
                          state <= s3;
                           outp  <= 1’b1;
                       end
                    end
                s2: begin
                       state <= s4;
                        outp  <= 1’b0;
                    end
                s3: begin
                       state <= s4;
                        outp  <= 1’b0;
                    end
                s4: begin
                       state <= s1;
                        outp  <= 1’b1;
                    end
              endcase
           end
        end
        endmodule
       
Following is the Verilog code for an FSM with two processes.
        module fsm (clk, reset, x1, outp);
        input        clk, reset, x1;
        output       outp;
        reg          outp;
        reg    [1:0] state;
        parameter s1 = 2’b00; parameter s2 = 2’b01;
        parameter s3 = 2’b10; parameter s4 = 2’b11;
        always @(posedge clk or posedge reset)
        begin
           if (reset)
              state <= s1;
           else begin
              case (state)
                s1: if (x1 == 1’b1)
                       state <= s2;
                    else
                       state <= s3;
                s2: state <= s4;
                s3: state <= s4;
                s4: state <= s1;
              endcase
           end
        end
        always @(state) begin
           case (state)
              s1: outp = 1’b1;
              s2: outp = 1’b1;
              s3: outp = 1’b0;
              s4: outp = 1’b0;
           endcase
        end
        endmodule
   


Verilog code for an FSM with three processes.


        module fsm (clk, reset, x1, outp);
        input        clk, reset, x1;
        output       outp;
        reg          outp;
        reg    [1:0] state;
        reg    [1:0] next_state;
        parameter s1 = 2’b00; parameter s2 = 2’b01;
        parameter s3 = 2’b10; parameter s4 = 2’b11;
        always @(posedge clk or posedge reset)
        begin
           if (reset)
              state <= s1;
           else
              state <= next_state;
        end

        always @(state or x1)
        begin
           case (state)
              s1: if (x1 == 1’b1)
                    next_state = s2;
                 else
                    next_state = s3;
              s2: next_state = s4;
              s3: next_state = s4;
              s4: next_state = s1;
           endcase
        end
       
Synthesis vs. Compilation


Have the hardware design clear in your mind when you write the verilog .  Write the Verilog CODE to describe that HW.It is a Hardware Description Language not a Hardware Imagination Language.If you are very clear, the synthesis tools are likely to figure it out

          Descriptions mapped to hardware
          Verilog design patterns for best synthesis
          Verilog and VHDL started out as simulation languages, but soon programs were written to automatically convert Verilog code into low-level circuit descriptions (netlists).

          Synthesis converts Verilog (or other HDL) descriptions to an implementation using technology-specific primitives:
          For FPGAs: LUTs, flip-flops, and RAM blocks
          For ASICs: standard cell gate and flip-flop libraries, and memory blocks

          Automatically manages many details of the design process:
          Fewer bugs
          Improves productivity

          Abstracts the design data (HDL description) from any particular implementation technology
          Designs can be re-synthesized targeting different chip technologies;  E.g.:  first implement in FPGA then later in ASIC

          In some cases, leads to a more optimal design than could be achieved by manual means (e.g.: logic optimization)

          Variety of general and ad-hoc (special case) methods:
          Instantiation:  maintains a library of primitive modules (AND, OR, etc.) and user defined modules
          “Macro expansion”/substitution: a large set of language operators 
(+, -, Boolean operators, etc.) and constructs (if-else, case) expand into special circuits
          Inference: special patterns are detected in the language description and treated specially (e.g.,: inferring memory blocks from variable declaration and read/write statements, FSM detection and generation from “always @ (posedge clk)” blocks)
          Logic optimization: Boolean operations are grouped and optimized with logic minimization techniques
          Structural reorganization: advanced techniques including sharing of operators, and retiming of circuits (moving FFs), and others
          Logical operators map into primitive logic gates
          Arithmetic operators map into adders, subtractors, …
          Unsigned 2s complement
          Model carry: target is one-bit wider that source
          Watch out for *, %, and /
          Relational operators generate comparators
          Shifts by constant amount are just wire connections
          No logic involved
          Variable shift amounts a whole different story --- shifter


Condition

          Compiler
        Recognizes all possible constructs in a formally defined program language
        Translates them to a machine language representation of execution process
          Synthesis
        Recognizes a target dependent subset of a hardware description language
        Maps to collection of concrete hardware resources
        Iterative tool in the design flow


          Verilog has two types of assignments within always blocks:

          Blocking procedural assignment “=“
        RHS is executed and assignment is completed before the next statement is executed;  e.g.,

Assume A holds the value 1 … A=2;  B=A;   A is left with 2, B with 2.
          Non-blocking procedural assignment “<=“
        RHS is executed and assignment takes place at the end of the current time step (not clock cycle); e.g.,

Assume A holds the value 1 … A<=2;  B<=A;   A is left with 2, B with 1.


          Notion of “current time step” is tricky in synthesis, so to guarantee that your simulation matches the behavior of the synthesized circuit, follow these rules:
                                i.            Use blocking assignments to model combinational logic within an always block
                              ii.            Use non-blocking assignments to implement sequential logic
                            iii.            Do not mix blocking and non-blocking assignments in the same always block
                            iv.            Do not make assignments to the same variable from more than one always block



Supported verilog constructs

        Net types: wire, tri, supply1, supply0; register types: reg, integer, time (64 bit reg); arrays of reg
        Continuous assignments
        Gate primitive and module instantiations
        always blocks, user tasks, user functions
        inputs, outputs, and inouts to a module
        All operators (+, -, *, /, %, <, >, <=, >=, ==, !=, ===, !==, &&, ||, !, ~, &, ~&, |, ~|, ^~, ~^, ^, <<, >>, ?:, { }, {{ }}) [Note: / and % are supported for compile-time constants and constant powers of 2]
        Procedural statements: if-else-if, case, casex, casez, for, repeat, while, forever, begin, end, fork, join
        Procedural assignments: blocking assignments =nonblocking assignments <= (Note: <= cannot be mixed with = for the same register).
        Compiler directives: `define, `ifdef, `else, `endif, `include, `undef
        Miscellaneous:
        Integer ranges and parameter ranges
        Local declarations to begin-end block
        Variable indexing of bit vectors on the left and right sides of assignments


Unsupported Verilog 

Generate error and halt synthesis

          Net types: trireg, wor, trior, wand, triand, tri0, tri1, and charge strength;
          register type: real
          Built-in unidirectional and bidirectional switches, and pull-up, pull-down
          Procedural statements: assign (different from the “continuous assignment”), deassign, wait
          Named events and event triggers
          UDPs (user defined primitives) and specify blocks
          force, release, and hierarchical net names (for simulation only)

Simply ignored

          Delay, delay control, and drive strength
          Scalared, vectored
          Initial block
          Compiler directives (except for `define, `ifdef, `else, `endif, `include, and `undef, which are supported)
          Calls to system tasks and system functions (they are only for simulation)

Combinational logic   can be generated using:

  1. Primitive gate instantiation:
AND, OR,  etc.
  1. Continuous assignment (assign keyword), example:
                        Module adder_8 (cout, sum, a, b, cin);
                        output cout;
                        output [7:0] sum;
                        input cin;
                        input [7:0] a, b;
                        assign {cout, sum} = a + b + cin;
                        endmodule
    1. Always block:
            always @ (event_expression)
            begin
                         // procedural assignment statements, if statements,
             // case statements, while, repeat, and for loops. 
             // Task and function calls
            end     
          Make sure all signals assigned in a combinational always block are explicitly assigned values every time that the always block executes--otherwise latches will be generated to hold the last value for the signals not assigned values!

module mux4to1 (out, a, b, c, d, sel);
output out;
input a, b, c, d;
input [1:0] sel;
reg out;
always @(sel or a or b or c or d)
begin
  case (sel)
    2'd0: out = a;
    2'd1: out = b;
    2'd3: out = d;
  endcase
end
endmodule


          To avoid synthesizing a latch in this case, add the missing select line:
                                    2'd2: out = c;
          Or, in general, use the “default” case:
                                    default:  out = foo;
          If you don’t care about the assignment in a case (for instance you know that it will never come up) then assign the value “x” to the variable;  E.g.:
                                    default:  out = 1‘bx;
            The x is treated as a “don’t care” for synthesis and will simplify the logic
            (The synthesis directive “full_case” will accomplish the same, but can lead to differences between simulation and synthesis.)

Latch rule
          If a variable is not assigned in all possible executions of an always statement then a latch is inferred
        E.g., when not assigned in all branches of an if or case
        Even a variable declared locally within an always is inferred as a latch if incompletely assigned in a conditional statement

FSM

          Style guidelines (some of these are to get the right result, and some just for readability)
        Must have reset
        Use separate always blocks for sequential and combination logic parts
        Represent states with defined labels or enumerated types
          Use CASE statement in an always to implement next state and output logic
          Always use default case and assert the state variable and output to ‘bx:
        Avoids implied latches
        Allows use of don’t cares leading to simplified logic
          “FSM compiler” within synthesis tool can re-encode your states;  Process is controlled by using a synthesis attribute (passed in a comment).

Introduction to Gate level Modelling


        Verilog has built in primitives like gates, transmission gates, and switches. These are rarely used in design (RTL Coding), but are used in post synthesis world for modeling the ASIC/FPGA cells; these cells are then used for gate level simulation, or what is called as SDF simulation. Also the output netlist format from the synthesis tool, which is imported into the place and route tool, is also in Verilog gate level primitives.

      Note : RTL engineers still may use gate level primitivies or ASIC library cells in RTL when using IO CELLS, Cross domain synch cells.

      Gate primitives are predefined in Verilog, which are ready to use. They are instantiated like modules.

      There are two classes of gate primitives: Multiple input gate primitives and Single input gate primitives.

      Multiple input gate primitives include and, nand, or, nor, xor, and xnor. These can have multiple inputs and a single output. They are instantiated as follows:

      // Two input AND gate.
and and_1 (out, in0, in1);

// Three input NAND gate.
nand nand_1 (out, in0, in1, in2);

// Two input OR gate.
or or_1 (out, in0, in1);

// Four input NOR gate.
nor nor_1 (out, in0, in1, in2, in3);

// Five input XOR gate.
xor xor_1 (out, in0, in1, in2, in3, in4);

// Two input XNOR gate.
xnor and_1 (out, in0, in1);

      Single input gate primitives include not, buf, notif1, bufif1, notif0, and bufif0. These have a single input and one or more outputs. Gate primitives notif1, bufif1, notif0, and bufif0 have a control signal.

      The gates propagate if only control signal is asserted, else the output will be high impedance state (z). They are instantiated as follows:

      // Inverting gate.
not not_1 (out, in);

// Two output buffer gate.
buf buf_1 (out0, out1, in);

// Single output Inverting gate with active-high control signal.
notif1 notif1_1 (out, in, ctrl);

// Double output buffer gate with active-high control signal.
bufif1 bufif1_1 (out0, out1, in, ctrl);

// Single output Inverting gate with active-low control signal.
notif0 notif0_1 (out, in, ctrl);

// Single output buffer gate with active-low control signal.
bufif0 bufif1_0 (out, in, ctrl);

     Array of instances

          wire [3:0] out, in0, in1;
          and and_array[3:0] (out, in0, in1);

The above statement is equivalent to following bunch of statements:

and and_array0 (out[0], in0[0], in1[0]);
and and_array1 (out[1], in0[1], in1[1]);
and and_array2 (out[2], in0[2], in1[2]);
and and_array3 (out[3], in0[3], in1[3]);
      module full_adder (sum, c_out, ino, in1, c_in);
output sum, c_out;
input in0, in1, c_in;
wire s0, c0, c1;
// Half adder : port connecting by order.
half_adder ha_0 (s0, c0, in0, in1);
// Half adder : port connecting by name.
half_adder ha_1 (.sum(sum),
.in0(s0),
.in1(c_in),
.carry(c1));
// 2-input XOR gate, to get c_out.
xor xor_1 (c_out, c0, c1);
endmodule



In Verilog, a designer can specify the gate delays in a gate primitive instance. This helps the designer to get a real time behavior of the logic circuit.

Rise delay
: It is equal to the time taken by a gate output transition to 1, from another value 0, x, or z.

Fall delay
: It is equal to the time taken by a gate output transition to 0, from another value 1, x, or z.

Turn-off delay
: It is equal to the time taken by a gate output transition to high impedance state, from another value 1, x, or z.
If the gate output changes to x, the minimum of the three delays is considered.
      If only one delay is specified, it is used for all delays.
      If two values are specified, they are considered as rise, and fall delays.
      If three values are specified, they are considered as rise, fall, and turn-off delays.
      The default value of all delays is zero.

and #(5) and_1 (out, in0, in1);
// All delay values are 5 time units.

nand #(3,4,5) nand_1 (out, in0, in1);
// rise delay = 3, fall delay = 4, and turn-off delay = 5.

or #(3,4) or_1 (out, in0, in1);
// rise delay = 3, fall delay = 4, and turn-off delay = min(3,4) = 3.

There is another way of specifying delay times in verilog, Min:Typ:Max values for each delay. This helps designer to have a much better real time experience of design simulation, as in real time logic circuits the delays are not constant. The user can choose one of the delay values using +maxdelays, +typdelays, and +mindelays at run time. The typical value is the default value.

and #(4:5:6) and_1 (out, in0, in1);
// For all delay values: Min=4, Typ=5, Max=6.

nand #(3:4:5,4:5:6,5:6:7) nand_1 (out, in0, in1);
// rise delay: Min=3, Typ=4, Max=5, fall delay: Min=4, Typ=5, Max=6, turn-off delay: Min=5, Typ=6, Max=7.

In the above example, if the designer chooses typical values, then rise delay = 4, fall delay = 5, turn-off delay = 6.

HDL EMERGENCE

          The need to a standardized language for hardware description
          Verilog® and VHDL
          Simulators emerged
          Usage: functional verification
          Path to implementation: manual translation into gates
          Logic synthesis technology
          Late 1980s
          Dramatic change in digital design
          Design at Register-Transfer Level (RTL) using an HDL

TYPICAL DESIGN FLOW

          Design specification
          Behavioral description
          RTL description
          Functional verification and testing
          Logic synthesis
          Gate-level netlist
          Logical verification and testing
          Floor planning, automatic place & route
          Physical layout
          Layout verification
          Implementation

IMPORTANCE OF HDL

          Retargeting to a new fabrication technology
          Functional verification earlier in the design cycle
          Textual concise representation of the design
          Similar to computer programs
          Easier to understand

Trends 

Design at behavioral level
Formal verification techniques
Very high speed and time critical circuits
e.g. microprocessors
Mixed gate-level and RTL designs
Hardware-Software Co-design
System-level languages: SystemC, SpecC,


          IEEE 1364-2001 is the latest Verilog HDL standard
          Verilog is case sensitive  (Keywords are in lowercase)
          The Verilog is both a behavioral and a structure language

Popularity of Verilog HDL 

          Verilog HDL
          General-purpose
          Easy to learn, easy to use
          Similar in syntax to C
          Allows different levels of abstraction and mixing them
          Supported by most popular logic synthesis tools
          Post-logic-synthesis simulation libraries by all fabrication vendors
PLI to customize Verilog simulators to designers’ needs

DIFFERENCES:VERILOG AND VHDL

          Verilog is similar to C- language.
          VHDL is similar to Ada- (ada is a structuredstatically typedimperativewide-spectrum, and object-oriented high-level computer programming language, extended from Pascal )
          Many feel that Verilog is easier to learn and use than VHDL.

Behavioral

          Procedural code, similar to C programming
          Little structural detail (except module interconnect)

         Dataflow

          Specifies transfer of data  between registers
          Some structural information is available (RTL)
          Sometimes similar to behavior

    Structural (gate,switch)
          Interconnection of simple components
          Purely structural


Elements of Verilog-logic values

0: zero, logic low, false, ground
1: one, logic high, power
X: unknown
              Z: high impedance, unconnected, tri-state

          Nets
    Nets are physical connections between devices
        Many types of nets, but all we care about is wire.
          Declaring a net
wire [<range>] <net_name> ;
Range is specified as [MSb:LSb]. Default is one bit wide
          Registers
        Implicit storage-holds its value until a new value is assigned to it.
        Register type is denoted by reg.
          Declaring a register
reg [<range>] <reg_name>;
Ø  Parameters are not variables, they are constants.

Basic verilog primitives
          Basic logic gates only
        and
        or
        not
        buf
        xor
        nand
        nor
        xnor
        bufif1, bufif0
notif1, notif0

Logical operators

          && ® logical AND
          || ® logical OR
          !  ® logical NOT
          Operands evaluated to ONE bit value: 0, 1 or x
          Result is ONE bit value: 0, 1 or x
                A = 1;                     A && B ® 1 && 0 ® 0
                B = 0;                     A || !B ® 1 || 1 ® 1
                C = x;                     C || B ® x || 0 ® x

Bitwise operators

                                      ® bitwise AND
          |                              ® bitwise OR
                                      ® bitwise NOT
                                      ® bitwise XOR
          ~^ or ^~               ® bitwise XNOR
          Operation on bit by bit basis

Shift conditional operator
          ® shift right
          <<           ® shift left
          a = 4’b1010;
d = a >> 2;// d = 0010,c = a << 1;// c = 0100
          cond_expr ? true_expr : false_expr
keywords
          Note : All keywords are defined in lower case
          Examples : 
          module, endmodule
          input, output, inout
          reg, integer, real, time
          not, and, nand, or, nor, xor
          parameter
          begin, end
          fork, join
          specify, endspecify
          module – fundamental building block for Verilog designs
          Used to construct design hierarchy
          Cannot be nested
           endmodule – ends a module – not a statement
               => no “;”
          Module Declaration
           module module_name (module_port, module_port);
          Example: module full_adder (A, B, c_in,
                   c_out, S);   

Modules

          Verilog supported levels of abstraction
          Behavioral (algorithmic) level
          Describe the algorithm used
          Very similar to C programming
          Dataflow level
Describe how data flows between registers and is processed
          Gate level
Interconnect logic gates
          Switch level
Interconnect transistors (MOS transistors)
          Register-Transfer Level (RTL)
Generally known as a combination of behavioral+dataflow that is synthesizable by EDA tools


VERILOG Lexical conventions

Verilog is very similar to C and is  case-sensitive
All keywords are in lowercase
A Verilog program is a string of tokens
       Whitespace
       Comments
       Delimiters
       Numbers
       Strings
       Identifiers
       Keywords
Whitespace
Blank space (\b)
Tab (\t)
Newline (\n)
Whitespace is ignored in Verilog except
In strings
When separating tokens
       Comments
Used for readability and documentation
Just like C:
       // single line comment
       /* multi-line 
comment 
*/
  /* Nested comments 
/* like this */ may not be acceptable (depends on Verilog compiler) */

       Operators
Unary
a = ~b;
Binary
a = b && c;
Ternary
a = b ? c : d; // the only ternary operator
       Number Specification
Sized numbers
Unsized number
Unknown and high-impedance values
       Negative numbSized numbers
      General syntax: <size>’<base><number>
       <size> number of bits (in decimal)
       <number> is the number in radix <base>
       <base> :
      d or D for decimal (radix 10)
      b or B for binary (radix 2)
      o or O for octal (radix 8)
      h or H for hexadecimal (radix 16)
       Examples:4’b1111
      12’habc
16’d255ers

       Unsized numbers
Default base is decimal
Default size is at least 32 (depends on Verilog compiler)
Examples
       23232
       ’habc
       ’o234

       X or Z values
Unknown value: lowercase x
       4 bits in hex, 3 bits in octal, 1 bit in binary
High-impedance value: lowercase z
       4 bits in hex, 3 bits in octal, 1 bit in binary
      Examples
       12’h13x
       6’hx
       32’bz
Extending the most-significant part
       Applied when <size> is bigger than the specified value
      Filled with x if the specified MSB is x
      Filled with z if the specified MSB is z
      Zero-extended otherwise
       Examples:
      6’hx

       Negative numbers
Put the sign before the <size>
Examples:
       -6’d3
       4’d-2    // illegal
Two’s complement is used to store the value
       Underscore character and question marks
Use ‘_’ to improve readability
       12’b1111_0000_1010
       Not allowed as the first character
‘?’ is the same as ‘z’ (only regarding numbers)
       4’b10?? // the same as 4’b10zz

       Strings
As in C, use double-quotes
Examples:
       “Hello world!”
       “a / b”
       “text\tcolumn1\bcolumn2\n”
       Identifiers and keywords
identifiers: alphanumeric characters, ‘_’, and ‘$’
       Should start with an alphabetic character or ‘_’
       Only system tasks can start with ‘$’
Keywords: identifiers reserved by Verilog
Examples:
       reg value;
       input clk;

       Escaped identifiers
Start with ‘\’
End with whitespace (space, tab, newline)
Can have any printable character between start and end
The ‘\’ and whitespace are not part of the identifier
      Examples:
       \a+b-c  // a+b-c is the identifier
       \**my_name** // **my_name** is the identifier
Used as name of modules

DATA TYPES

       Value set and strengths
       Nets and Registers
       Vectors
       Integer, Real, and Time Register Data Types
       Arrays
       Memories
       Parameters
       Strings
VALUE SET

Verilog concepts to model hardware circuits
Value level
Value strength
Used to accurately model
Signal contention
MOS devices
Dynamic MOS
Other low-level details

Value level
HW Condition
0
Logic zero, false
1
Logic one, true
x
Unknown
z
High imp., floating

Strength level
Type
supply
Driving
strong
Driving
pull
Driving
large
Storage
weak
Driving
medium
Storage
small
Storage
highz
High Impedance


NETS
       Used to represent connections between HW elements
Values continuously driven on nets
       Keyword: wire
Default: One-bit values
       unless declared as vectors
Default value: z
       For trireg, default is x
Examples
       wire a;
       wire b, c;
       wire d=1’b0;

REGISTERS
       Registers represent data storage elements
Retain value until next assignment
NOTE: this is not a hardware register or flipflop
Keyword: reg
Default value: x
      Example:
reg reset;
initial
begin
   reset = 1’b1;
   #100 reset=1’b0;
end

VECTORS
       Net and register data types can be declared as vectors (multiple bit widths)
       Syntax:
wire/reg [msb_index : lsb_index] data_id;
       Example
wire a;
wire [7:0] bus;
wire [31:0] busA, busB, busC;
reg clock;
reg [0:40] virtual_addr;

Consider wire [7:0] bus;
wire [31:0] busA, busB, busC;
reg [0:40] virtual_addr;
       Access to bits or parts of a vector is possible:
busA[7]
bus[2:0] // three least-significant bits of bus
// bus[0:2] is illegal.
virtual_addr[0:1] /* two most-significant bits
                   * of virtual_addr
                   */
INTEGER, REAL, AND TIME REGISTER DATA TYPES
       Integer
Keyword: integer
Very similar to a vector of reg
       integer variables are signed numbers
       reg vectors are unsigned numbers
Bit width: implementation-dependent (at least 32-bits)
       Designer can also specify a width:
integer [7:0] tmp;
      Examples:
integer counter;
initial
   counter = -1;
       Real
      Keyword: real
      Values:
       Default value: 0
       Decimal notation: 12.24
       Scientific notation: 3e6 (=3x106)
      Cannot have range declaration
      Example:
real delta;
initial
begin
   delta=4e10;
   delta=2.13;
end
integer i;
initial
   i = delta; // i gets the value 2 (rounded value of 2.13)



Time

Used to store values of simulation time
Keyword: time
Bit width: implementation-dependent (at least 64)
$time system function gives current simulation time
      Example:
time save_sim_time;
initial
   save_sim_time = $time;

ARRAYS

       Only one-dimensional arrays supported
       Allowed for reg, integer, time
      Not allowed for real data type
       Syntax:
<data_type> <var_name>[start_idx : end_idx];
       Examples:
integer count[0:7];
reg bool[31:0];
time chk_point[1:100];
reg [4:0] port_id[0:7];
integer matrix[4:0][4:0]; // illegal
count[5]
chk_point[100]
port_id[3]
Note the difference between vectors and arrays

MEMORIES

       RAM, ROM, and register-files used many times in digital systems
       Memory = array of registers in Verilog
       Word = an element of the array
      Can be one or more bits
       Examples:
reg membit[0:1023];
reg [7:0] membyte[0:1023];
membyte[511]
       Note the difference (as in arrays):
reg membit[0:127];
reg [0:127] register;                

PARAMETERS

       Similar to const in C
But can be overridden for each module at compile-time
       Syntax:
parameter <const_id>=<value>;
       Gives flexibility
Allows to customize the module
       Example:
parameter port_id=5;
parameter cache_line_width=256;
parameter bus_width=8;
wire [bus_width-1:0] bus;

STRINGS

       Strings are stored in reg variables.
       8-bits required per character
       The string is stored from the least-significant part to the most-significant part of the reg variable
       Example:
reg [8*18:1] string_value;
initial
   string_value = “Hello World!”;
       Escaped characters
      \n: newline      \t: tab
      %%: %            \\: \
      \”: “                  \ooo: character number in octal



SYSTEM TASKS AND COMPILER DIRECTIVES

       System Tasks: standard routine operations provided by Verilog
Displaying on screen, monitoring values, stopping and finishing simulation, etc.
       All start with $
       $display: displays values of variables, strings, expressions.
       Syntax: $display(p1, p2, p3, …, pn);
       p1,…, pn can be quoted string, variable, or expression
       Adds a new-line after displaying pn by default
       Format specifiers:
       %d, %b, %h, %o: display variable respectively in decimal, binary, hex, octal
       %c, %s: display character, string
       %e, %f, %g: display real variable in scientific, decimal, or whichever smaller notation
       %v: display strength
       %t: display in current time format
       %m: display hierarchical name of this module
       $display examples:
       $display(“Hello Verilog World!”);
       Output: Hello Verilog World!
       $display($time);
       Output: 230
       reg [0:40] virtual_addr;
       $display(“At time %d virtual address is %h”, $time, virtual_addr);
       Output: At time 200 virtual address is 1fe000001c
       reg [4:0] port_id;
       $display(“ID of the port is %b”, port_id);
       Output: ID of the port is 00101
       reg [3:0] bus;
       $display(“Bus value is %b”, bus);
       Output: Bus value is 10xx
       $display(“Hierarchical name of this module is %m”);
       Output: Hierarchical name of this module is top.p1
       $display(“A \n multiline string with a %% sign.”);
       Output: A
     multiline string with a % sign.
       $monitor: monitors a signal when its value changes
       Syntax: $monitor(p1, p2, p3, …, pn);
       p1,…, pn can be quoted string, variable, or signal names
       Format specifiers just as $display
       Continuously monitors the values of the specified variables or signals, and displays the entire list whenever any of them changes.
       $monitor needs to be invoked only once (unlike $display)
       Only one $monitor (the latest one) can be active at any time
       $monitoroff to temporarily turn off monitoring
       $monitoron to turn monitoring on again
       $monitor Examples:
       initial
       begin
          $monitor($time, “Value of signals clock=%b, reset=%b”, clock, reset);
       end
       Output:
0 value of signals clock=0, reset=1
5 value of signals clock=1, reset=1
10 value of signals clock=0, reset=0
       $stop: stops simulation
       Simulation enters interactive mode when reaching a $stop system task
       Most useful for debugging
       $finish: terminates simulation
       Examples:
initial
begin
 clock=0;
reset=1;
#100 $stop;
             #900 $finish;
            end

General syntax:

`<keyword>
`define: similar to #define in C, used to define macros
`<macro_name> to use the macro defined by `define
Examples:
`define WORD_SIZE 32
`define S $stop
`define WORD_REG reg [31:0]
`WORD_REG a_32_bit_reg;



COMPILER DIRECTIVES
       General syntax:
`<keyword>
       `define: similar to #define in C, used to define macros
       `<macro_name> to use the macro defined by `define
       Examples:
`define WORD_SIZE 32
`define S $stop
`define WORD_REG reg [31:0]
`WORD_REG a_32_bit_reg;

       include: Similar to #include in C, includes entire contents of another file in your Verilog source file
       Example:
`include header.v
...
<Verilog code in file design.v>


...Dataflow modeling


      Dataflow modeling is a higher level of abstraction. The designer no need have any knowledge of logic circuit. He should be aware of data flow of the design.
      The gate level modeling becomes very complex for a VLSI circuit. Hence dataflow modeling became a very important way of implementing the design.
      In dataflow modeling most of the design is implemented using continuous assignments, which are used to drive a value onto a net. The continuous assignments are made using the keyword assign.

Features

      A powerful way to implement a design
       Logic synthesis tools can be used to create a gatelevel net list
       RTL (register transfer level) is a combination of dataflow and behavioral modeling

Assign

             The assign statement is used to make continuous assignment in the dataflow modeling. The assign statement usage is given below:

assign out = in0 + in1; // in0 + in1 is evaluated and then assigned to out.

      The LHS of assign statement must always be a scalar or vector net or a concatenation. It cannot be a register.

      Continuous statements are always active statements.

      Registers or nets or function calls can come in the RHS of the assignment.

      The RHS expression is evaluated whenever one of its operands changes. Then the result is assigned to the LHS.

      Delays can be specified.

          assign out[3:0] = in0[3:0] & in1[3:0];
         assign {o3, o2, o1, o0} = in0[3:0] | {in1[2:0],in2}; // Use of concatenation.

Implicit Net Declaration:

wire in0, in1;
assign out = in0 ^ in1;
In the above example out is undeclared, but verilog makes an implicit net declaration for out.

Implicit Continuous Assignment:

wire out = in0 ^ in1;
The above line is the implicit continuous assignment. It is same as,
wire out;
assign out = in0 ^ in1;


 Operands
      constants
       parameters
       nets
       variables (reg, integer, time, real, realtime)
       bit-select
       part-sel
       array element
       function calls


Delays

There are three types of delays associated with dataflow modeling. They are: Normal/regular assignment delay, implicit continuous assignment delay and net declaration delay.

Normal/regular assignment delay:
assign #10 out = in0 | in1;

If there is any change in the operands in the RHS, then RHS expression will be evaluated after 10 units of time.

Lets say that at time t, if there is change in one of the operands in the above example, then the expression is calculated at t+10 units of time.

 The value of RHS operands present at time t+10 is used to evaluate the expression.

Implicit continuous assignment delay:

wire #10 out = in0 ^ in1;
is same as
wire out;
assign 10 out = in0 ^ in1;

Net declaration delay:
wire #10 out;
assign out = in;
is same as
wire out;
assign #10 out = in;

Variable data types

reg
integer
time
 real
 real-time

Reg variable

Hold a value between assignments
May be used to model hardware registers
      ™ Examples
reg a, b;
reg [7:0] data_a;
reg [0:7] data_b;
reg signed [7:0] d;

Integer Variable

Contains integer values
      ™ Has at least 32 bits
      ™ Is treated as a signed reg variable with the LSB
      being bit 0
      integer i, j;
      integer data[7:0];

Time variable
      Used for storing and manipulating simulation time
      Used in conjunction with the $time system task
      Only unsigned value and at least 64 bits, with the
      LSB being bit 0
      time events;
      time current_time;
    
     Real and real time variable
       Cannot use range declaration
       Defaulted to zero (0.0)
      real events;
      realtime current_time;


Assignments in Verilog


          Continuous assignments assign values to nets (vector and scalar)
They are triggered whenever simulation causes the value of the right-hand side to change

Keyword “assign”

                e.g. assign out = in1 & in2;    

      
          Procedural assignments drive values onto registers (vector and scalar)
They Occur within procedures such as always and initial
They are triggered when the flow of execution reaches them (like in C)
Blocking and Non-Blocking procedural assignments

          Procedural Assignments

        Blocking assignment statement (operator) acts much like in traditional programming languages. The whole statement is done before control passes on to the next statement
  
         Nonblocking assignment statement (<= 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

          Delay Control (#)

 
Expression specifies the time duration between initially encountering the statement and when the statement actually executes.


Delay in Procedural Assignments

          Inter-Statement Delay
          Intra-Statement Delay

For example:
          Inter-Statement Delay
                                                #10 A = A + 1;
          Intra-Statement Delay
                                                A = #10 A + 1;

D Flip flop with synchronous reset

module d_flipflop_synrst(data_in,data_out,clock,reset); 
input data_in;
input clock,reset;
output reg data_out;
always@(posedge clock)
begin
if(reset)
data_out<=1'd0;
else
data_out<=data_in;
         end
endmodule

Procedural Assignments

         Executes a procedure allowing for more powerful constructs such as if-then-else and case statement.
         For example 2:1 mux:
        if-then-else
if (A) then D = B else D = C;
        case
case(A) 
 1'b1 : D = B; 
 1'b0 : D = C; 
 endcase
This is obviously much easier to implement and read then Boolean expressions!!

          Always block
         An always block is an example of a procedure.
         The procedure executes a set of assignments when a defined set of inputs change.

Example:
module mux_2_1(a, b, out, sel);
input a, b, sel;
output out;
reg out;
always @ (a or b or sel)
begin
if (sel) out = a;
else out = b;

end
endmodule
The always block ‘executes’ whenever signals named in the sensitivity list change.
Literally: always execute at a or b or sel.
Sensitivity list should include conditional (sel) and right side (a, b) assignment variables.
As Easier Way to Implement the Sensitivity List

         Recent versions of Verilog provides a means to implement the sensitivity list without explicitly listing each potential variable.
         Instead of listing variables as in the previous example
always @ (a or b or sel)
    Simply use
always @*
The * operator will automatically identify all sensitive variables.
Blocking and non-blocking assignments
         Blocking (=) and non-blocking (<=) assignments are provided to control the execution order within an always block.
         Blocking assignments literally block the execution of the next statement until the current statement is executed.
        Consequently, blocking assignments result in ordered statement execution.
        Combinational logic: Use blocking statements with always blocks with the * operator to mimic logic flow of combinational logic.
        Sequential logic: Use non-blocking statements with always blocks sensitive to rising clock edge to mimic parallel sequential logic.
         
For example:
assume a = b = 0 initially;
a = 1;       //executed first
b = a;       //executed second
then a = 1, b = 1 after ordered execution
         Non-blocking assignments literally do not block the execution of the next statements. The right side of all statements are determined first, then the left sides are assigned together.
        Consequently, non-blocking assignments result in simultaneous or parallel statement execution.
For example:
assume a = b = 0 initially;
a <= 1;      
b <= a;
then a = 1, b = 0 after parallel execution
Result is different from ordered exec!!! Does not preserve logic flow



To block or not to block
Ordered execution mimics the inherent logic flow of combinational logic.
Hence blocking assignments generally work better for combinational logic.
For example:

module blocking(a,b,c,x,y);
input a,b,c;
output x,y;
reg x,y;
always @*
begin
x = a & b;
y = x | c;
end
endmodule
module nonblocking(a,b,c,x,y);
input a,b,c;
output x,y;
reg x,y;
always @*
begin
x <= a & b;
y <= x | c;
end
endmodule
Blocking behavior
a
b
c
x
y
Initial values
1
1
0
1
1
a changesàalways block execs
0
1
0
1
1
x = a & b;  //make assignment
0
1
0
0
1
y = x | c;    //make assignment
0
1
0
0
0

Non-blocking behavior
a
b
c
x
y
Initial values
1
1
0
1
1
a changesàalways block execs
0
1
0
1
1
x = a & b;
0
1
0
1
1
y = x | c; //x not passed from here
0
1
0
1
1
make x, y assignments
0
1
0
0
1

non-blocking behavior does not preserve logic flow!!


Sequential logic


         Can be generalized as a series of combinational blocks with registers to hold results.

         Shift registers are used to implement multiplication/division and other functions.
clk
D0
Q0
Q1
initial
1
0
0
rising edge
1
1
0
rising edge
0
0
1


  Notice that the inputs of each stage are “evaluated” then latched into the registers at each rising clock edge.

         Because the shift logic evaluates inputs in parallel and latches result on a rising clk edge, a non-blocking always procedure sensitive to a rising clock can be used to implement.

Sensitive to rising clock edge. Note that in this case we must explicitly specify sensitivity to the rising edge of clock. Simply using the * will not work.

         What if we used blocking statements instead. Notice the following results:

The logic statements are simplified to Q0 = Q1 = D0. Logic is evaluated on rising edge of clk. Verilog is synthesized as one stage logic.

Test bench for D Flip flop with synchronous reset


module Tb_dflipflop_synrst(); 
reg data_in;
reg clock,reset;
wire data_out;

d_flipflop_synrst UUT(.data_in(data_in),
.data_out(data_out),
.clock(clock),
.reset(reset));
initial begin
// Initiliase Input Stimulus
data_in = 0;
clock = 0;
reset=0;
end

always #100 clock=~clock;

//Stimulus
initial 
begin 
#200 data_in = 1'b1; 
reset = 1'b1;
#200 data_in = 1'b1;
reset = 1'b1;

#300 data_in = 1'b1;
reset=1'b0;
#600 data_in = 1'b0;
#500 data_in = 1'b1;
#200 data_in = 1'b0;
#400 $stop;
end

endmodule