Introduction To Verilog Hardware Description Language
Introduction To Verilog Hardware Description Language
Hardware Description
Language
Introduction
Purpose of HDL:
1. Describe the circuit in algorithmic
level (like c) and in gate-level (e.g.
And gate)
2. Simulation
3. Synthesis
4. Words are better than pictures
2
The best way to describe a
circuit?
Input
Circuit
X Wire
Y Output
Z
O
06/07/17 6
Module declaration
Module
Input
Circuit
X Wire
Y Output
Z
O
Module name
input X,Y,Z;
output O;
06/07/17 endmodule 7
Typical Module Components
Diagram
Module name, Port list (optional, if there are ports)
Port declarations
Parameter list
endmodule declaration
Lexicography
Comments:
Two Types:
// Comment
/* These comments extend
over multiple lines. Good
for commenting out code */
Character Set:
0123456789ABCD..YZabcd...yz_$
Cannot start with a number or $
9
systemCalls.v
module systemCalls(clk);
input clk;
clockGenerator cg(clk);
initial
begin
$write("$write does not Terminates
"); simulation.
$write("add a new line\n");
$display("$display does");
$display("add a new line");
Similar output calls except
$display adds a new line.
$monitor("Clock = %d", cg.clk); end
endmodule
count[5]
chk_point[100]
port_id[3]
Note the difference between vectors and arrays
19 2005 Verilog HDL
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;
23
numbers.v
module numbers;
integer i, j;
reg[3:0] x, y; Register array.
initial
begin
i = b1101; <base>: base can be d, b, o, h Array of register arrays simulate
$display( "decimal i = %d, binary i = %b", i, i );
$display( "octal i = %o, hex i = %h", i, i ); memory. Example memory
j = -1; declaration with 1K 32-bit words:
$display( "decimal j = %d, binary j = %b", j, j ); reg[31:0] smallMem[0:1023];
$display( "octal j = %o, hex j = %h", j, j );
$finish;
end
endmodule
25
Operators
module sample (a, b, c, d);
Reduction Operators: input [2:0] a, b;
Unary operations returns single-bit values output [2;0] c, d;
& : and wire z,y;
| :or
~& : nand assign z = ~| a;
~| : nor c = a * b;
^ : xor If(a==b) d = 1; else d =0;
~^ :xnor
d = a ~^ b;
Shift Operators
Shift Left: << if ((a>=b) && (z)) y=1;
Shift right: >> else y = !x;
Concatenation Operator assign d << 2; //shift left
{ } (concatenation) twice
{ n{item} } (n fold replication of an item) assign {carry, d} = a + b;
Conditional Operator assign c =
{2{carry},2{1b0}};
Implements if-then-else statement // c = {carry,carry,0,0}
(cond) ? (result if cond true) : (result if cond
false) assign c= (inc==2)? a+1:a-1;
26
clockGenerator.v
Port list. Ports can be of three types: input,
output, inout. Each must be declared.
module clockGenerator(clk);
output clk; Internal register.
reg clk;
Register reg data type can have one of
four values: 0, 1, x, z. Registers store a
initial
value till the next assignment. Registers
begin are assigned values in procedural blocks.
clk = 0;
end If this module is run stand-alone make
sure to add a $finish statement here or
always simulation will never complete!
#5 clk = ~clk;
endmodule
The delay is half the clock period.
Verilog Structure
30
Blocking Vs Non-Blocking
Blocking Non-blocking
<variable> = <statement> <variable> <= <statement>
32
blockingVSnba1.v
module blockingVSnba1;
integer i, j, k, l;
initial
begin
#1 i = 3; Blocking (procedural) assignment: the whole statement
#1 i = i + 1; must execute before control is released, as in traditional
j = i +1; programming languages.
#1 $display( "i = %d, j = %d", i, j );
#1 i = 3;
#1 i <= i + 1;
j <= i + 1; Non-blocking (procedural) assignment: all the RHSs for the
current
#1 $display( "i = %d, j = time
%d", i, j ); instant are evaluated (and stored transparently
in temporaries) first and, subsequently, the LHSs are updated
$finish; at the end of the time instant.
end
endmodule
blockingVSnba2.v
module blockingVSnba2(clk);
input clk;
clockGenerator cg(clk); Compile with clockGenerator.v.
integer i, j;
An application of non-blocking assignments
initial to solve a race problem.
begin
i = 10;
#50 $finish;
end
With blocking assignments we get different output
always @(posedge clk) depending on the order these two statements are
i = i + 1; // i <= i + 1; executed by the simulator, though they are both
always @(posedge clk)
supposed to execute simultaneously at posedge clk
j = i; // j <= i;
- race problem.
always @(negedge clk)
$display("i = %d, j = %d", i, j); Race problem is solved if the non-blocking
endmodule assignments (after the comments) are used instead
- output is unique.
blockingVSnba3.v
The most important application of
module blockingVSnba3;
non-blocking assignments is to
reg[7:0] dataBuf, dataCache, instrBuf, instrCache;
model concurrency in hardware
systems at the behavioral level.
initial
begin
dataCache = 8'b11010011;
Both loads from dataCache to dataBuf and
instrCache = 8'b10010010;
instrCache to instrBuf happen concurrently
#20;
in the 20-21 clock cycle.
$display("Time = %d, dataBuf = %b, instrBuf = %b", $time, dataBuf, instrBuf);
dataBuf <= #1 dataCache;
instrBuf <= #1 instrCache;
#1 $display("Time = %d, dataBuf = %b, instrBuf = %b", $time, dataBuf, instrBuf);
$finish;
end
endmodule Replace non-blocking with blocking
assignments and observe.
System Tasks and
Compiler Directives
System Tasks
System Tasks: standard routine
operations provided by Verilog
Displaying on screen, monitoring values,
stopping and finishing simulation, etc.
All start with $
2005 37
Verilog HDL
System Tasks (contd)
$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
2005 38
Verilog HDL
System Tasks (contd)
$display examples:
$display(Hello Verilog World!);
Output: Hello Verilog World!
$display($time);
Output: 230
2005 39
Verilog HDL
System Tasks (contd)
reg [4:0] port_id;
$display(ID of the port is %b, port_id);
Output: ID of the port is 00101
2005 40
Verilog HDL
System Tasks (contd)
$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
2005 41
Verilog HDL
System Tasks (contd)
$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
2005 42
Verilog HDL
System Tasks (contd)
$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
2005 43
Verilog HDL
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
2005 44
Verilog HDL
Compiler Directives (contd)
`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>
...
2005 45
Verilog HDL
Behavior Modeling
simpleBehavioral.v
Sensitivity trigger: when any of a, b or c changes.
Replace this statement with initial. Output?!
if (expression)
begin
...statements...
end
else if (expression)
begin
...statements...
end
...more else if blocks
else
begin
...statements...
end
50
Case Statements
Syntax
case (expression)
case_choice1:
begin
...statements...
end
case_choice2:
begin
...statements...
end
default:
begin
...statements...
end
endcase
51
For loops
Syntax
52
Component Inference
Flip-Flops
always@(posedge clk)
begin
a<=b;
a<=b&c;
end
54
D Flip-Flop with Asynchronous
Reset
always@(posedge clk or negedge
rst)
begin
if (!rst) a<=0;
else a<=b;
end
55
D Flip-flop with Synchronous
reset and Enable
always@(posedge clk)
begin
if (rst) a<=0;
else if (enable) a<=b;
end
56
Shift Registers
reg[3:0] Q;
always@(posedge clk or
posedge rset )
begin
if (rset) Q<=0;
else begin
Q <=Q << 1;
Q[0]<=Q[3];
end
57
Multiplexers
Method 1
assign a = (select ? b : c);
Method 2
always@(select or b or c) begin
if(select) a=b;
else a=c;
end
Method 2b
case(select)
1b1: a=b;
1b0: a=c;
endcase
58
Counters
reg [7:0] count;
wire enable;
always@(posedge clk or negedge
rst)
begin
if (rst) count<=0;
else if (enable)
count<=count+1;
end
59
Step by Step
4-bit adder
4-bit Adder
Step 1: build a 1-bit full adder as a
module
S = (a) XOR (b) XOR (Cin ) ; ( S =
a^b^Cin)
module
C FA_1bit (S,Cout,a,b,Cin);
begin out
= (a&b) |(Cin&(a+b))
input a,b,Cin;
Output S, Cout;
endmodule
61
4-bit Adder
Step 2: initiate 4 instances of FA_1bit module
B3 A3 B2 A2 B1 A1 B0 A0
S3 S2 S1 S0
module FA_4bits (S,Cout,A,B,Cin); The inputs and the
begin
input [3:0] A, B;
output are 4-bits wide
input Cin; we need wires to
output [3:0] S;
output Cout
propagate the carry
wire Cout0, Cout1, Cout2 from one stage to the
next
you may name the
FA_1bit FA1(S[0], Cout0,A[0],B[0],Cin);
FA_1bit FA1(S[1], Cout1,A[1],B[1],Cout0); instances with any
FA_1bit FA1(S[2], Cout2,A[2],B[2],Cout1); name, but you have to
FA_1bit FA1(S[3], Cout,A[3],B[3],Cout2);
maintain the order of
end
endmodule; the inputs and outputs 62
4-bit Adder
Step 3: write a test-bench to test your design and generate outs using sample
inputs.
test_bench
Write a A[3:0] 4
initial
Integer data type: other types are
begin time, real and realtime (same as real).
i = 0;
j = 3;
$display( "i = %d, j = %d", i, j ); One initial procedural block.
$finish;
end
endmodule
blocksTime2.v
module blocksTime2;
integer i, j;
initial
begin Time delay models signal propagation
#2 i = 0; delay in a circuit.
#5 j = i;
$display( "time = %d, i = %d, j = %d", $time, i, j );
end
initial
#3 i = 2;
Multiple initial blocks.
Delays add within each block,
initial
but different initial blocks all start
#10 $finish;
at time $time = 0 and run
endmodule
in parallel (i.e., concurrently).
blocksTime3.v
module blocksTime3;
integer i, j;
initial
begin
#2 i = 0;
#5 j = i; Important Verilog is a discrete event simulator:
$display( "time = %d, i = %d, j = %d", $time, i, j );
end
events are executed in a time-ordered queue.
initial
begin
#3 i = 2;
#2 j = i;
$display( "time = %d, i = %d, j = %d", $time, i, j );
#1 j = 8;
$display( "time = %d, i = %d, j = %d", $time, i, j );
end
initial
#10 $finish;
endmodule Multiple initial blocks.
Predict output before
you run!
blocksTime4.v
module blocksTime4;
integer i, j;
initial
begin
i = 0; Always block is an infinite loop. Following are same:
j = 3;
end always initial initial
begin begin begin
initial
#10 $finish; while(1) forever
end begin begin
always
begin end end
#1
i = i + 1;
end end
j = j + 1;
$display( "i = %d, j = %d", i, j );
end
endmodule Comment out this delay.
Run. Explain the problem!
clockGenerator.v
Port list. Ports can be of three types: input,
output, inout. Each must be declared.
module clockGenerator(clk);
output clk; Internal register.
reg clk;
Register reg data type can have one of
initial four values: 0, 1, x, z. Registers store a
value till the next assignment. Registers
begin are assigned values in procedural blocks.
clk = 0;
end
If this module is run stand-alone make
sure to add a $finish statement here or
always simulation will never complete!
#5 clk = ~clk;
endmodule
The delay is half the clock period.
useClock.v
initial
#50 $finish; Event trigger.
initial
begin
i = 0;
j = 5;
end Comment out the delay.
Run. Explain what happens!
initial
#10 $finish;
endmodule
blocksTime6.v
module blocksTime6;
integer i, j; Intra-assignment delay: RHS is computed and
stored in a temporary (transparent to user) and
initial LHS is assigned the temporary after the delay.
begin
#2 i = 0;
j = #5 i;
$display( "time = %d, i = %d, j = %d", $time, i, j );
end
initial
#3 i = 2;
Compare output with blocksTime2.v.
initial
#10 $finish;
endmodule
simpleDataflow.v
not(q, b);
Wire data type can have one of four values: 0, 1, x, z.
or(p, a, q); Wires cannot store values they are continuously
or(d, p, c); driven.
endmodule
or (out, w, x, y, z);
endmodule
multiplexor4_1Stimulus.v
(Folder Multiplexor)
module muxstimulus;
reg IN1, IN2, IN3, IN4, CNTRL1, CNTRL2; Stimulus code that generates
wire OUT; test vectors.
initial
begin
IN1 = 1; IN2 = 0; IN3 = 1; IN4 = 0;
$display("Initial arbitrary values");
#0 $display("input1 = %b, input2 = %b, input3 = %b, input4 = %b\n",
IN1, IN2, IN3, IN4);
Input
Output
D7 D6 D5 D4 D3 D2 D1 D0 A2
A1 A0
0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 1 0 0 0 1 0
0 0 0 0 1 0 0 0 0 1 1
0 0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0 1 0 1
0 1 0 0 0 0 0 0 1 1 0
1 0 0 0 0 0 0 0 1 1 1
8-to-3 encoder (Folder
Encoder)
Following are four different Verilog implementations of the
same encoder.
Each has its own stimulus module.
encoder8_3Behavioral.v
module encoder8_3( encoder_out , enable, encoder_in );
output[2:0] encoder_out;
input enable;
input[7:0] encoder_in;
reg[2:0] encoder_out; Sensitivity list.
always @ (enable or encoder_in)
begin
if (enable)
case ( encoder_in ) Simple behavioral code using the
8'b00000001 : encoder_out = 3'b000; case statement.
8'b00000010 : encoder_out = 3'b001;
8'b00000100 : encoder_out = 3'b010;
8'b00001000 : encoder_out = 3'b011;
8'b00010000 : encoder_out = 3'b100;
8'b00100000 : encoder_out = 3'b101;
8'b01000000 : encoder_out = 3'b110;
8'b10000000 : encoder_out = 3'b111;
default : $display("Check input bits.");
endcase
end
endmodule
encoder8_3BehavioralStimulus.
v
module stimulus;
wire[2:0] encoder_out;
reg enable;
reg[7:0] encoder_in;
Stimulus for the behavioral code.
encoder8_3 enc( encoder_out, enable, encoder_in );
initial
begin
enable = 1; encoder_in = 8'b00000010;
#1 $display("enable = %b, encoder_in = %b, encoder_out = %b",
enable, encoder_in, encoder_out);
#1 enable = 0; encoder_in = 8'b00000001;
#1 $display("enable = %b, encoder_in = %b, encoder_out = %b",
enable, encoder_in, encoder_out);
#1 enable = 1; encoder_in = 8'b00000001;
Remove this #1
delay.
$display("enable = %b, encoder_in = %b, encoder_out = %b",
Run. Explain! enable, encoder_in, encoder_out);
#1 $finish;
end
endmodule
8-to-3 encoder logic
equations
A0 = D1 + D3 + D5 + D7
A1 = D2 + D3 + D6 + D7
A2 = D4 + D5 + D6 + D7
encoder8_3structural.v
(Folder Encoder)
initial
begin
encoder_in = 8'b00000010;
#1 $display("encoder_in = %b, encoder_out = %b", encoder_in,
encoder_out);
#1 encoder_in = 8'b00000001;
#1 $display("encoder_in = %b, encoder_out = %b", encoder_in,
encoder_out);
#1 $finish;
end
endmodule
encoder8_3Mixed.v
module encoder8_3( encoder_out , enable, encoder_in );
output[2:0] encoder_out;
input enable;
input[7:0] encoder_in;
reg[2:0] encoder_out;
wire b0, b1, b2;
initial
begin Output is puzzling! Explain!
enable = 1; encoder_in = 8'b00000010;
#1 $display("enable = %b, encoder_in = %b, encoder_out = %b",
enable, encoder_in, encoder_out);
#1 $finish;
end
endmodule
Comparator modules
scheme
comparator.v
Parameters that may be set Comparator makes the comparison A ? B
when the module is instantiated. where ? Is determined by the input
greaterNotLess and returns true(1) or false(0).
endmodule
stimulus.v
Stimulus for the comparator.
module system;
wire greaterNotLess; // sense of comparison
wire [15:0] A, B; // comparand values - 16 bit
wire result; // comparison result
// Module instances
comparator #(16, 2) comp (result, A, B, greaterNotLess);
testGenerator tg (A, B, greaterNotLess, result);
endmodule
Parameters being set at module instantiation.
testGen.v
module testGenerator (A, B, greaterNotLess, result);
output [15:0] A, B;
output greaterNotLess;
input result;
parameter del = 5; Module that generates test vectors for
reg [15:0] A, B;
reg greaterNotLess;
the comparator and checks correctness
of output.
task check;
input shouldBe;
begin
if (result != shouldBe)
$display("Error! %d %s %d, result = %b", A, greaterNotLess?">":"<",
B, result);
end Task definition: a task is
exactly like a procedure
endtask
in a conventional programming language.
initial begin // produce test data, check results
A = 16'h1234;
B = 16'b0001001000110100;
greaterNotLess = 0;
testGen.v (cont.)
#del
check(0);
B = 0; Task call
greaterNotLess = 1;
#del
check(1);
A = 1;
greaterNotLess = 0;
#del
check(0);
$finish;
end
endmodule
Finite State Machines
Standard Form for a Verilog
FSM
// state flip-flops // REGISTER DEFINITION
reg [2:0] state, nxt_st; always@(posedge clk)
// state definitions begin
parameter
reset=0,S1=1,S2=2,S3=3,..
state<=next_state;
end
// NEXT STATE CALCULATIONS
always@(state or inputs or ...) // OUTPUT CALCULATIONS
begin output= f(state, inputs)
next_state= ...
end
101
Example
module myFSM (clk, x, z) // NEXT STATE CALCULATIONS
input clk, x; always @(state or x)
output z; begin
// state flip-flops case (state)
reg [2:0] state, nxt_st; S0: if(x) nxt_st=S1;
// state definition else nxt_st=S0;
parameter S1: if(x) nxt_st=S3;
S0=0,S1=1,S2=2,S3=3,S else nxt_st=S2;
7=7 S2: if(x) nxt_st=S0;
else nxt_st=S7;
// REGISTER DEFINITION S3: if(x) nxt_st=S2;
always @(posedge clk) else nxt_st=S7;
begin S7: nxt_st=S0;
state<=nxt_st; default: nxt_st = S0;
end endcase
end
// OUTPUTCALCULATIONS
assign z = (state==S7); endmodule
102
0111 Sequence Detector
103
Test Benches
System tasks
Used to generate input and output during
simulation. Start with $ sign.
Display Selected Variables:
$display (format_string,par_1,par_2,...);
$monitor(format_string,par_1,par_2,...);
Example: $display(Output z: %b, z);
Writing to a File:
$fopen, $fdisplay, $fmonitor and $fwrite
Random number generator: $random (seed)
Query current simulation time: $time
105
Test Benches
Overview Approach
106
Example
timescale1 ns /100 ps
// timeunit =1ns; precision=1/10ns; /****SPECIFY THE INPUT WAVEFORM x
module my_fsm_tb; ****/
reg clk, rst, x; Initial begin
wire z; #1 x=0;
#400 x=1;
/**** DESIGN TO SIMULATE (my_fsm) $display(Output z: %b, z);
INSTANTIATION ****/ #100 x=0;
myfsm dut1(clk, rst, x, z); @(posedge clk) x=1;