L05 Introduction to Verilog III

Dr Ryan Robucci

Objective

  1. Introduction to Verilog
  2. Verilog basics
  3. Testbenches
  4. Coding Style
  5. Extended Introduction

References

Constants should use localparal

For more discussion, see http://www.sunburst-design.com/papers/CummingsHDLCON2002_Parameters_rev1_2.pdf

localparam a=31; //int
localparam a=32,b=31; //int (multiple on one line)
localparam byte_size=8, byte_max=bytesize-1; //int
localparam a =6.22; //real
localparam delay = (min_delay + max_delay) /2;//real
localparam initial_state = 8'b1001_0110; //reg

For more discussion, see http://www.sunburst-design.com/papers/CummingsHDLCON2002_Parameters_rev1_2.pdf

Vectors

In C, standard variable types are constrained by the processor architecture, but for custom hardware it makes sense to allow declaring a variables of various bit lengths. We do this by appending the type with and bit address range.

“A net or reg declaration without a range specification shall be considered 1 bit wide and is known as a scalar. Multibit net and reg data types shall be declared by specifying a range, which is known as a vector.” – IEEE Verilog Specification

Standard bit vectors defined by a high to low index are created with square brackets and colon preceding the identifier so as to modify the type of the variable itself

<type> [<HighBit>:<LowBit>] id;

They are accessed using square brackets for single bits and additionally using a colon if accessing a slice of bits. Examples from IEEE Specification:

reg[3:0] v;  // a 4-bit vector reg made up of (from most to 
             // least significant) v[3], v[2], v[1], and v[0]
reg [-1:4] b; // a 6-bit vector reg
reg [4:0] x, y, z; // declares three 5-bit regs

SystemVerilog:

logic [3:0] v;  // a 4-bit vector made up of (from most to 
             // least significant) v[3], v[2], v[1], and v[0]
logic [-1:4] b; // a 6-bit vector
logic [4:0] x, y, z; // declares three 5-bit

Bit Slicing

reg [7:0] v;
wire msb,lsb;  
wire [3:0] highNibble, 
           lowNibble;
wire [7:0] s;


…

assign lsb = v[0];
assign msb = v[7];
assign highNibble = v[7:4];
assign lowNibble = v[3:0];

s[3:0] = 4’b0000;
s[7:0] = lowNibble;

Arrays

<type> id[<LowWordAddress>:<HighWordAddress>];

They are accessed using square brackets

reg x[0:11];  //scalar reg array with length of 12
…
//within procedural code…
x[3] = 1’0;

Memories (Array of Vectors)

High-to-Low Convention for Bit and Low-To-High for Arrays

(updated propagated from Blackbaord Post)

Unpacked arrays in SystemVerilog allow you to create arrays like you may in other languages.

Arrays in SystemVerilog can now be declared with a single number, e.g. [N], rather than a range of indexes, [0:N-1]. So, rather than recommended a convention [0:N-1] for both bit vectors and arrays, it is good to follow the default ordering convention of low-to-high in SystemVerilog for arrays.

Explicit Array Range

I recommend providing the index ranges explicitly like mem[0:9] rather than mem[10]

So, a convention for arrays is to use 0-starting-index with increasing index order. This means an array of 10 elements should be declared with either [10] or explicitly [0:9]. This also means that arrays declared with index range [9:0] will interact with reversed indexes and should be avoided.

This DOES NOT CHANGE THE RECOMMEND BIT-ORDERING, which should remain with MSB downto LSB like

bit [15:0] word;

but memories should be declared like this:

bit [15:0] mem[0:2047];      // total 4kB

Here is an example to demonstrate:

module mux10to1(dout,arr_,sel);
   output logic [15:0] dout;
   input logic  [15:0]  arr_ [10]; //[10] same as [0:9]
   input logic  [3:0]   sel;

   always_comb begin
      dout = arr_[sel];
   end
endmodule

module array_tb;
  
  logic [15:0] doutA,doutB,doutC;

  logic [15:0] arrA_ [10];
  logic [15:0] arrB_ [0:9]; //same as arrA_
  logic [15:0] arrC_ [9:0]; //reversed if connected to port declared with [0:9]
  logic [3:0]  sel;

  //instantiate three multiplexors
  mux10to1 DUTA (.dout(doutA),.arr_(arrA_),.sel);
  mux10to1 DUTB (.dout(doutB),.arr_(arrB_),.sel);
  mux10to1 DUTC (.dout(doutC),.arr_(arrC_),.sel);

  initial begin

     //intialize data inputs muxtiplexors with the same values
     arrA_[0]=1;
     arrA_[1]=2;
     arrA_[2]=4;
     arrA_[3]=8;
     arrA_[4]=16;
     arrA_[5]=32;
     arrA_[6]=64;
     arrA_[7]=128;
     arrA_[8]=256;
     arrA_[9]=65535;

     arrB_[0]=1;
     arrB_[1]=2;
     arrB_[2]=4;
     arrB_[3]=8;
     arrB_[4]=16;
     arrB_[5]=32;
     arrB_[6]=64;
     arrB_[7]=128;
     arrB_[8]=256;
     arrB_[9]=65535;


     arrC_[0]=1;
     arrC_[1]=2;
     arrC_[2]=4;
     arrC_[3]=8;
     arrC_[4]=16;
     arrC_[5]=32;
     arrC_[6]=64;
     arrC_[7]=128;
     arrC_[8]=256;
     arrC_[9]=65535;

     $display("%4s","sel","%6s","doutA","%6s","doutB","%6s","doutC");
     $monitor("%4d",sel,"%6d",doutA,"%6d",doutB,"%6d",doutC);

     #1;
     sel=0;
     #1;
     sel=1;
     #1;
     sel=4;
     #1;
     sel=9;
  end

endmodule // array_tb

Output

 sel doutA doutB doutC
   x     x     x     x
   0     1     1 65535
   1     2     2   256
   4    16    16    32
   9 65535 65535     1

Metalogic Values

Verilog Supports more than the two logic values 0/Low and 1/High. The following Metalogic Values are important to be aware of since they may be encountered unintentionally in simulation.

Operators

Logical Operators

Logical Operators force the evaluation of input arguments to TRUE or FALSE and result in a single TRUE or FALSE.

Operator Name Examples
! logical negation if (!(a==b)) , if (!a)
&& logical and if ((c==a)&&(c==b))
|| logical or if ((c==a)||(c==b))

Bitwise Operators

Example:

wire [3:0] a,y;
assign a = 4’b0101;
assign y = ~a;

Example:

wire [3:0] a = 4’b0101,b= 4’b0011,y;
assign y = a&b; //produces 0001 

Unary Reduction Operators

Example:

wire a = 4’b0001;
wire y1,y2;
assign y1 = |a;
assign y2 = |a;

(Unary and Binary) Bitwise and Unary Reduction Operators

Operator Name Examples
| & bitwise or bitwise and y=a|b;
| & reduction or reduction and y = |b;
~| ~& reduction nor reduction nand y = ~|b;
a^b bitwise xor y = a^b;
^b reduction xor y = ^b;
~^ ^~ bitwise xnor y = a~^b;
~^ ^~ reduction xnor y = ~^b;
~ bitwise negation y = ~a;

Logical and Relational Comparisons

Operator Name, Description Examples
== logical equality if (a==b)
!= logical inequality if (a!=b)
a>b relational greater than if (a>b)
>= relational greater than or equal if (a>=b)
< relational greater than if (a<b)
<= relational greater than or equal if (a<=b)

Shift and Mathematical Operations

Operator Name, Description Examples
>>,<< shift right or left by a number of positions a = shiftvalue >> 2;
<<<,>>> Signed shifts, shift right or left by a number of positions with a signed left argument. Signed variables may be declared with the keyword signed, integers are signed by default
+,-,*,/,% Arithmetic Operators. Note for division: synthesizers may only support divide or modulo by constant power of two y=a+b; y=b/4; //right shift by 2
** Power. Note: synthesizers may only support a right argument that is a constant c=a**3; -->

Concatenation and Replication Operators

Operator Name, Description Examples
{ , } Concatenation: concatenation of one, two, or more operands {4'b1111,4'b0000} {2'b11,2'b11,2'b00,2'b00}
Both produce 8'b11110000
{n{x}} Replication: Allows fixed number of replications (n must be a constant) assume a=16’hFFFF; then
2{a} produces 32'hFFFFFFFF
2{a} produces 32'hFFFFFFFF
{16{1'b0},a} produces 32'h0000FFFF
8{2'b10} roduces 16'b1010101010101010

Case Equality

Operator Name, Description Examples
== logical quality if (bus == 4’b0000)
=== case equality if (bus === 4’bzzzz)
~= logical inequality
!== case inequality if (bus !== 4’bzzzz)

Assignment in Procedural Code

There are two types of assignments that you will see in procedural code

Operator Name, Description Examples
<= non blocking assignment statement, schedules assignment but allows next statement to execute y <= a & b;
= blocking assignment statement, blocks execution of next statement until assignment to left-hand argument (e.g. y) is completed y = a & b;

significant time will be spent discussing these later

Some additional Data Types: integer, real, and time

Integral (integer) types

Signedness:

Real:

Conversions:

Net types

L05 Introduction to Verilog III

Operators

≡