Skip to content

jun-gu-kang/VerilogHDL

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

prerequisite

sudo apt install make
sudo apt install iverilog
sudo apt install gtkwave
$ make            # compile
$ make DUMP=1     # compile and generate dump file for wave
$ make wave       # open generated dump vcd file using GTKWAVE
$ make clean      # remove all build up files.

Verilog HDL Summary

  • Line terminator: Semicolon ;
  • Single line comment: //
  • Multiple line comment: /* ... */

Identifier & Keyword

  • Identifier: the name of the object
  • Keyword: The word cannot be used as identifier since it is reserved for Verilog HDL.
Keywords reserved for Verilog
always
end
ifnone
or
rpmos
tranif1
and
endcase
initial
output
rtran
tri
assign
endmodule
inout
parameter
rtranif0
tri0
begin
endfunction
input
pmos
rtranif1
tri1
buf
endprimitive
integer
posedge
scalared
triand
bufif0
endspecify
join
primitive
small
trior
bufif1
endtable
large
pull0
specify
trireg
case
endtask
macromodule
pull1
specparam
vectored
casex
event
medium
pullup
strong0
wait
casez
for
module
pulldown
strong1
wand
cmos
force
nand
rcmos
supply0
weak0
deassign
forever
negedge
real
supply1
weak1
default
for
nmos
realtime
table
while
defparam
function
nor
reg
task
wire
disable
highz0
not
release
time
wor
edge
highz1
notif0
repeat
tran
xnor
else
if
notif1
rnmos
tranif0
xor

Logial Values

Value Logic Detail
0 Logic LOW False
1 Logic HIGH True
X Don't care 0,1, or Z
Z High Impedence not connected

Examples are below.

& 0 1 X Z
0 0 0 0 0
1 0 1 X X
X 0 X X X
Z 0 X X X
| 0 1 X Z
0 0 1 X X
1 1 1 1 1
X X 1 X X
Z X 1 X X

Number Representation

Signed Number Representation

Usage: <size>'<base_format><number>

  • <size>: number of bits

  • <base_format>: base format code of following <number>

    • b or B: binary
    • o or O: octal
    • d or D: decimal
    • h or H: hexadecimal
  • <number>: value of number represented in format specified as <base_format>

  • _ (underscore): it has no grammatical meaning, but used for separation.

  • ? (question mark): imply casex or casez syntax

eg)

4'b1111                // 4bit number    1111
12'habc                // 12bit number   101010111100
16'd255                // 16bit number   1111111111111111

12'b1010_1011_1100     // 12bit number   101010111100
4'b10??                // 4bit number    10zz

12'h13x                // 12bit number   00010011xxxx
6'hx                   // 6bit number    xxxxxx
8'bz                   // 8bit number    zzzzzzzz

Data Type

Net(wire)

  • keyword: wire
  • connection between hardware elements or module
  • net is continuously driven by other signal
  • default value: 'z' (high impedence)

Register (reg)

  • keyword: reg
  • Data storage elements to retain value until another value is stored
  • default value: 'x' (don't care)

Integer, Real, Time may not be realized as Hardware (for simulating stimulus block)

Integer: integer number

Real: real number

Time: data time for time

Vector Form

Nets or Registers can be declared as vector (multiple bit widths)

Usage: <data_type>[left_range:right_range]<variable_name>

eg)

wire[7:0] bus;        // 8bit bus
$display(bus[3:0]);   // part selection (only lower 4bit)

Note that descending index convention is commonly used, such that [(N-1):0] for N-bit vector

Array Form

Usage: <data_type><array_name>[<subscript>]

Array allows the data types of <reg>,<ingeger>, <time>, <vector reg>.

Vector form is preferred more, and array form is used especially for memory.

eg)

reg[7:0] membyte [0:1023]    // Memory of 1K(1024) of byte words
membyte[511]                 // 1 byte word whose address is 511

System Task

performs certain routine operations.

Usage: $<keyword>;

  • $display(<list_of_arguments>); prints the argument given, only when it is called.
    • accepts 'Verilog Format Specifiers' listed below.
  • $monitor(<list_of_arguments>); prints the argument given, whenever the given arguments are changed.
    • accepts 'Verilog Format Specifiers' listed below.
    • needs to be invoked only once unlike $display
  • $stop; suspends the simulation in an interactive mode.
  • $finish; terminates the simulation.

Verilog Format Specifiers

In order to print variables inside display functions, appropriate format specifiers have to be given for each variable.

Argument Description
%h, %H Display in hexadecimal format
%d, %D Display in decimal format
%b, %B Display in binary format
%m, %M Display hierarchical name
%s, %S Display as a string
%t, %T Display in time format
%f, %F Display 'real' in a decimal format
%e, %E Display 'real' in an exponential format

Compiler Directive

Compiler Directives are annotated by starting with grave accent ```````. It operates pre-processing during compilation

Usage: \`<keyword>

  • \`define <macro_name> <macro_value>: text macro in Verilog (similar with #define in C)
    • use macro by \`<macro_name>
    • eg)
      `define WORD_SIZE 32                      // 'WORD_SIZE' implies 32  
      `define WORD_REG reg[(`WORD_SIZE-1):0]    // 'WORD_REG' implies reg[31:0]
      ...
      `WORD_REG reg32;                          // reg32 declared in type of WORD_REG
  • \`include <verilog_source_file>: include Verilog Source file in another Verilog file during compliation. (similar with #include in C)
    • eg)
      `include header.v

Module vs Instance

Module is Basic building blocks that provide the necessary functionality to the higher-level block, and the port interfaces (input&output) while hiding internal implementation. Module may be defined as the form of below.

module <module_name>(<port_list>);
    <port_declaration>                    // if port present
    <intermediate_data_definition>        // if wire, reg and other variables are needed
    <lower_level_module_instantiation>    // instantiation of implemented module or primitive gates.
    <dataflow_statement>                  // 'assign'
    <behavioral_statement>                // 'initial' and 'always' block
    <system_task_and_functions>           // system task and function if needed.
endmodule

module, <module_name>, endmodule are mandatory for module, while others are optional (used if needed).

Note that the semicolon ; locates at the end of first line of module definition.

Module is a templete, and instance is actual object created by the templete 'module'.

Instance can be created by module instantiation as follows:

Usage: <module_name> <instance_name> (<list_of_mapped_variable_with_ports>);

eg) D_FF DFF1 (Q,D,CLK,RESET);

Port, Instantiation and Connection Rules

module_example

Port (interface or terminal)

  • provides the interface by which a module can communicate with its environment.
Verilog Keyword Type of Port
input Input port
output Output port
inout Bidirectional port

eg) port declaration

module Full_Adder_4bit(sum,cout,a,b,cin);
    output wire[3:0] sum;    // (output) port declaration
    output wire cout;        // (output) port declaration
    input wire[3:0] a, b;    // (output) port declaration
    input wire cin;          // (output) port declaration
    /*Module Instatiation placed here*/
endmodule
module D_FF(q,d,clk,reset);
    output reg q;            // (output) port declaration
    input d, clk, reset;     // (input) port declaration
    /*Module Instatiation placed here*/
endmodule

Connection Rules

Characteristic of two data type mentioned above are followed:

net is continuously driven by other signal

register is data storage elements to retain value until another value is stored

These derives following rules:

  • recipient must be declared as 'net' type so that its value can be driven by sender.
  • sender can be declared as either 'register' or 'net'.
    • if sender is driven by another signal, then it must be 'net' type.
    • if sender has its own state and retain its value until modification, then it must be 'reg' type.

Therefore, connection rule should be as follows

connection_rule

Internal External
input wire wire or reg
output wire or reg wire
inout wire wire

Connecting by ordered list

  • mapping variables with each corresponding port by order
  • eg) D_FF DFF1 (Q,D,CLK,RESET);

Connecting by name

  • mapping variables with each correponding port by name
  • eg) D_FF DFF1 (.clk(CLK), .reset(RESET), .d(D), .q(Q))

Recommendation: Ordered connection by name (for readability)

  • basically connecting by name, but list in order for easier debugging
  • eg) D_FF DFF1 (.q(Q), .d(D), .clk(CLK), .reset(RESET))

Design Block and Stimulus Block

design_under_testbench

Design Block

  • The block that required to be designed.
  • The design block may targets the Hardware.
  • It is also called DUT(design under testblock).

Stimulus Block

  • The stimulus block is not included in design requirement.
  • It is implemented for only testing the design block.
  • It may not be implemented as hardware, but software.
  • It is commonly called 'testbench'.

Gate Level Modeling

  • Intuitive for user with knowledge of digital logic design
  • One-to-one correspondence between the logic circuit and Verilog

Gate Type

Note that the following gate types (called 'primitives') are defined in Verilog already. These can be instantiated without gate module definition. Note that the name of primitives does not need to be specified. (But recommend to specify in order to reduce ambiguity)

  • AND/OR Gate type
    • Multiple scalar input
    • Single scalar output
    • the first port -> output port
    • other ports -> input ports
  • BUF/NOT Gate type
    • Single scalar input
    • Multiple scalar output
    • the last port -> input port
    • other ports -> output ports

eg)

and a1 (OUT,IN1,IN2);        // OUT = IN1 * IN2
nand (OUT,IN1,IN2,IN3);      // OUT = ~(IN1 * IN2 * IN3)

buf b1 (OUT1,IN);            // OUT1 = IN
not n1 (OUT1,OUT2,IN);       // OUT1 = OUT2 = ~IN

Gate delay

Ideal gate may not have the transition delay, but practical does. Verilog simulate the gate delays as follows.

  • Rise Delay: transition delay from 0 to 1
  • Fall Delay: transition delay from 1 to 0
  • Turn Off Delay: transition to high impedence 'Z'

Usage example

and #(5) a1 (out,i1,i2);     // Delay time = 5
or #(3,4) o1 (out,i1,i2);    // Rise Delay = 3, Fall Delay = 4
buf #(3,4,5) b1 (out,in);    // Rise = 3, Fall = 4, Turn-off = 5

Also, delay time may not be consistant. Verilog implements the delay variation using multiple values as follows

variation: (<minimum_value>:<typical_value>:<maximum_value>)

Usage example

and #(3:4:5) a1 (out,i1,i2);        // Delay time: min=3, typ=4, max=5
or #(2:3:4,3:4:5) o1 (out,i1,i2);   // Rise Delay: min=2, typ=3, max=4
                                    // Fall Delay: min=3, typ=4, max=5

Gate delay is commonly determined or measured by fabricator.

DataFlow Modeling

Dataflow modeling focuses on data flow between registers and how a design processes data rather than instantiation of individual gates.

  • Logic Synthensis: create a gate-level circuit from a dataflow design description using EDA (Electronic Design Automation) tool.
  • RTL Design: combination of dataflow modeling and behavioral modeling.

Dataflow modeling is done by 'continuous assignment' using keyword assign.

assign is used to drive a value onto a net such as : assign LHS=RHS;

Continuous assignment means that LHS(left-hand side) changes as soon as RHS(right-hand side) changes

Note that LHS must be 'assignable' variable and the value of LHS is driven continuously by RHS, which may be an expression. This fact gives a following constraint:

side possible type
LHS net or concatenation of net (either scalar or vector)
RHS expression consists of operator and operand (that is either registers or nets)

Delay values can be specified by inserting #<delay_time> after keyword assign.

eg)

assign out=i1&i2;                             // dataflow modeling of and gate
assign #10 out=i1&i2;                         // and gate with delay of 10 time unit

assign addr[15:0]=addr1[15:0]^addr2[15:0];    // some address calculation using xor bitwise operation between addr1 and addr2

assign {cout,sum[3:0]}=a[3:0]+b[3:0]+cin;     // dataflow modeling of 4 bit full adder.

Operand of Expression in dataflow modeling

  • Can be any one of data types (reg, wire, integer, real, time)
  • may be restricted by operator (operator takes only certain types of operands)

Operator of Expression in dataflow modeling

Verilog has three types of operator.

  • Unary: eg) a=~b;
  • Binary: eg) a=b&&c;
  • ternary: eg) a=b?c:d;

Operator can be classified as various type as below

1. Arithmetic Operator

These binary operations take two operands

A=4'b0100; B=4'b0011;
wire[3:0] C;

assign C=A*B;    // multiplication:    C==4'b1100
assign C=A/B;    // Division:          C==4'b0001
assign C=A+B;    // Addition:          C==4'b0111
assign C=A-B;    // Subtraction:       C==4'b0001
assign C=A**B;   // Power:             overflow
assign C=A%B;    // Modulus:           C==4'b0001

2. Logical Operator

Logical operators always evaluate to a 1-bit 0 or 1 or x.

Note that all the non-zero operand considered as logical 1.

A=3; B=0; D=2'b0x; E==2'b10;
wire C;

assign C=A&&B;   // logical-and:    C==0
assign C=A||B;   // logical-or:     C==1
assign C=!A;     // logical-not:    C==0
assign C=!B;     // logical-not:    C==1

assign C=D&&E;   // C=(2'b0x)&&(2'b10): either 0 or 1 => C==X (don't care)

3. Relational Operator

It works exactly same as C. Relational operators return a logical true 1 if the expression is true.

A=4; B=3;
X=4'b1010; Y=4'b1101; Z=4'b1xxx;
wire C;

assign C=A<=B;    // C==0 (less than or equal)
assign C=A>B;     // C==1 (greater than)
assign C=Y>=X;    // C==1 (greater than or equal)
assign C=Y<Z;     // C==x (less than)

4. Equality Operator

logical equality == and logical inequality != returns logical evaluation result. It returns 'don't care' x if result varies with x in operand.

Case equality === and Case inequality !== evaluates equality same as above, but it checks even casex and casez bits are identical or not and returns only 0 or 1.

A=4; B=3;
X=4'b1010; Y=4'b1101; Z=4'b1xxz; M=4'b1xxz; N=4'b1xxx;
wire C;

assign C=A==B;    // C==0 (logical equality)
assign C=X!=Y;    // C==1 (logical inequality)
assign C=X==z;    // C==x (logical equality; result depends on don't care bits in Z)
assign C=Z===M;   // C==1 (case equality; all bits match)
assign C=Z===N;   // C==0 (case equality; least significant bit does not match)
assign C=M!==N;   // C==1 (case inequality; least significant bit does not match)

5. Bitwise Operator

Note that bitwise operators performs a bit-by-bit operation (bitwise logical operation) on two operands, and it returns same size of bits.

symbol operation
~ negation
& and
| or
^ xor
^ (^) xnor
X=4'b1010; Y=4'b1101; Z=4'b10x1;
wire[3:0] W;

assign W=~X;     // W==4'b0101 (negation)
assign W=X&Y;    // W==4'b1000 (bitwise and)
assign W=X|Y;    // W==4'b1111 (bitwise or)
assign W=X^Y;    // W==4'b0111 (bitwise xor)
assign W=X~^Y;   // W==4'b1000 (bitwise xnor)
assign W=X&Z;    // W==4'b10x0 (bitwise and with x)

6. Reduction Operator

Reduction operator is unary operator. It performs a bitwise operation on a single vector operand and yield a 1bit result. Refer the example below.

symbol operation
& and
~& nand
| or
~| nor
^ xor
^ (^) xnor
X=4'b1010;
wire Y;

assign Y=&X;     // Y==1'b0 (equivalent to 1 & 0 & 1 & 0)
assign Y=~&X;    // Y==1'b1 (equivalent to ~(1&0&1&0))
assign Y=|X;     // Y==1'b1 (equivalent to 1 | 0 | 1 | 0)
assign Y=~|X;    // Y==1'b0 (equivalent to ~(1|0|1|0))
assign Y=^X;     // Y==1'b0 (equivalent to 1 ^ 0 ^ 1 ^ 0) even parity checker
assign Y=~^X;    // Y==1'b1 (equivalent to ~(1^0^1^0))    odd parity checker

7. Shift Operator

symbol operation
>> shift right logical
<< shift left logical
>>> shift right arithmetic
<<< shift left arithmetic

Arithmetic shift may consider sign-extension. Thus sra may fill MSB with previous MSB while srl just fill with 0. Note that sll and sla may result same.

X=4'b1100;
wire[3:0] Y;

assign Y=X>>1;     // Y==4'b0110 (shift right logical by 1)
assign Y=X<<1;     // Y==4'b1000 (shift left logical by 1)
assign Y=X<<2;     // Y==4'b0000 (shift left logical by 2)
assign Y=X>>>1;    // Y==4'b1110 (shift right arithmetic by 1; MSB filled with 1 (sign-extended))

8. Concatenation Operator { }

Concatenation operator appends multiple operator, and result an appended single vector (in order)

A=1'b1; B=2'b00; C=2'b10; D=3'b110;

assign Y={B,C};            // Y==4'b0010         (4'b00_10)
assign Y={A,B,C,D,3'b011}; // Y==11'b10010110001 (11'b1_00_10_110_001)
assign Y={A,B[0],C[1]};    // Y==3'b101          (3'b1_0_1)

9. Replicantion Operator (using nested concatenation operator { { } })

Replication operator replicate the operands and concatenate as many as the specified number.

reg A;
reg[1:0] B,C;
reg[2:0] D;
A=1'b1; B=2'b00; C=2'b10; D=3'b110;

assign Y={4{A}};            // Y==4'b1111         (4'b1_1_1_1)
assign Y={4{A},2{B}};       // Y==8'b11110000     (8'b1_1_1_1_00_00)
assign Y={4{A},2{B},C};     // Y==11'b11110000110 (11'b1_1_1_1_00_00_110)

10. Conditional Operator ? :

Conditional operator is also known as ternary operator.

Usage: <condition_expression>?<true_expression>:<false_expression>

The condition is evaluated first, then returns corresponding expression. Note that conditional operator can be nested as below.

assign out=(control==1'b1)?in1:in0;    // 2-to-1 MUX

assign out=(control[1]==1'b1)?((control[0]==1'b1)?in3:in2):((control[0]==1'b1)?in1:in0); // 4-to-1 MUX

Behavioral Modeling

Behavioral Modeling can be done by two basic statement of procedure block: initial and always

Multiple behavioral statements must be grouped in order to be used by initial and always. It can be grouped by using keywords begin and end.

If #<delay_time> is seen before a statement, then the statement is executed <delay_time> time unit after the current simulation time.

initial statement

initial block starts at time 0 and executes only once during a simulation.

Multiple initial block start to execute concurrently at time 0, but finishes execution in various time.

always statement

always block starts at time 0 and executes the statement continuously in a looping fashion.

Multiple always block starts to execute concurrently at time 0, and operates independently in a parallel manner.

Event control @() for always statement

always statement can be triggered by a particular event if always @ (<trigger_signal_list>)

keyword posedge or negedge can be used to make sensitive to transition edge.

eg)

module stimulus
    reg x,y,clk;
    initial
        clk=1'b0;
    initial begin
        x=1'b0;
        #5 y=1'b1;
    end
    always #10
        clk=~clk;
    always @ (posedge clk) begin
        x=~x;
        y=~y;
    end
    always @(*)
        $display(x,y);
endmodule

Procedural Assignment

The values should remain unchanged until another procedural assignment update the variable with a different value. (unlike dataflow modeling)

Thus left-hand side value must be reg type in behavioral modeling, while wire in dataflow modeling.

Blocking Assignments <LHS> = <RHS>

Blocking assignment statements are executed in the order they are specified in a sequential block.

Non-blocking Assignments <LHS> <= <RHS>

Non-blocking assignment allow scheduling of assignments without blocking execution of the statements. In other words, non-blocking assignment statement in the block without waiting for the non-blocking statement to complete execution.

initial begin
    A=4'h0; B=4'h0; C=4'h0; D=4'h0;
end

always @(posedge CLK)    // B is ahead of A by 1
begin
    A=A+1;
    B=A+1;               // executed after A=A+1; is done.
end

always @(posedge CLK)    // D is the same as C
begin
    C<=C+1;
    D<=C+1;              // executed concurrently with C<=C+1;
end

Conditional Statement: if and else

Similar with if statement in C.

if(<expression1>) <true_statement1>;
else if(<expression2>) <true_statement2>;
else if(<expression3>) <true_statement3>;
else <default_statement>;

Case Statement using case (or casex, casez), endcase, default

Similar with switch-case statement in C.

Case statement is alternative of if-elseif-else statement in Verilog.

case(<expression1>)
    <alternative1>: <statement1>;
    <alternative2>: <statement2>;
    <alternative3>: <statement3>;
    default: <default_statement>;
endcase

keyword casex allows all x and z values to be considered as don't care. (Only Non-x and Non-z positions in the case expression are compared.)

keyword casez allows all z values to be considered as don't care.

reg[3:0] encoding;
reg next_state;

casex(encoding)
    4'b1xxx: next_state=3;
    4'bx1xx: next_state=2;
    4'bxx1x: next_state=1;
    4'bxxx1: next_state=0;
    default: next_state=0;
endcase

Note that case statement is alternative representation of if statement in Verilog. If encoding==4'b0110, then next_state will be 2 (not 1) because case statement above will check 4'bx1xx prior than 4'bxx1x.

File I/O

Opening a file: $fopen

Usage: <file_handle> = $fopen("<filename>");

Writing to the file: $fdisplay, $fmonitor, fwrite

Usage: $fdisplay(<file_handle>,<arguments>);

Closing a file: $fclose

Usage: $fclose(<file_handle>);

Initializing memeory from file: $readmemb to read a file as binary / $readmemh to read a file as hexadecimal

Usage: $readmemb("<file_name>",<mem_name>,<start_addr>,<end_addr>); (<start_addr> and <end_addr> are optional)

eg)

module test;
    reg[7:0] memory[0:7];    // 8 byte memeory
    integer i;
    reg CLK;

    initial begin
        CLK=1'b0;
        $readmemb("init.dat",memory);
    end
    always #5
        CLK=~CLK;
    always @(posedge CLK)
        $display("Memory[%0h]=%b",i,memory[i]);     
endmodule

About

VerilogHDL Syntax Learning and Excersices

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published