VERILOG LAB - CHR
VERILOG LAB - CHR
VERILOG LAB - CHR
Introduction to Verilog
This manual uses short examples to demonstrate the basic Verilog syntax, time delays,
and concurrent execution features. We have tried to condense all the interesting and hard
parts of Verilog into 14 pages and skip all of the boring stuff like what is the difference
between real and integer data types. Studying this document will enable you to model
circuits using simple structural and behavioral Verilog code and provide a solid
framework for learning all the details of the language.
Most Verilog and VHDL books begin with several chapters describing the language's
history and advantages. But the arguments boil down to these:
HDL simulators are better then gate level simulators for 2 reasons: portable
model development, and the ability to design complicated test benches that react
to outputs from the model under test. Finding a model for a unique component for
your particular gate level simulator can be a frustrating task, with an HDL
language you can always write your own model. Also most gate level simulators
are limited to simple waveform based test benches which complicates the testing
of bus and microprocessor interface circuits.
Verilog is a great low level language. Structural models are easy to design and
Behavioral RTL code is pretty good. The syntax is regular and easy to remember.
It is the fastest HDL language to learn and use. However Verilog lacks user
defined data types and lacks the interface-object separation of the VHDL's entity-
architecture model.
VHDL is good for designing behavioral models and incorporates some of the
modern object oriented techniques. It's syntax is strange and irregular, and the
language is difficult to use. Structural models require a lot of code that interferes
with the readability of the model.
C++as an hardware modeling language is excellent choice for high-level
behavioral analysis of a system (like evaluating different data flow architectures
in a microprocessor). However C++ lacks the basic hardware concepts like
knowledge of strengths, connections, and concurrent execution which complicates
model generation for lower level simulations.
Choosing Verilog, VHDL, or C++ will be based on availability of tools, models, and in-
house expertise. If you are just learning your first HDL language we recommend Verilog
because you will be able to quickly become comfortable with the syntax and timing
issues of the language:
Verilog Structure
Verilog differs from regular programming languages (C, Pascal ...) in 3 main aspects:
(3) Some basic circuit concepts like network connections and primitive gates.
If you know how to program in C and you understand basic digital design then learning
Verilog will be easy.
Modules
In Verilog, circuit components are designed inside a module. Modules can contain both
structural and behavioral statements. Structural statements represent circuit components
like logic gates, counters, and microprocessors. Behavioral level statements are
programming statements that have no direct mapping to circuit components like loops, if-
then statements, and stimulus vectors which are used to exercise a circuit.
A module starts with the keyword module followed by an optional module name and an
optional port list. The key word endmodule ends a module.
Verilog defines some basic logic gates as part of the language. The module
some_logic_component instantiates two gate primitives: the not gate and the and gate.
The output of the gate is the first parameter, and the inputs are the rest of the parameters.
If you have a lot of random logic, the gate primitives of the previous section are tedious
to use because all the internal wires must be declared and hooked up correctly.
Sometimes it is easier to just describe a circuit using a single Boolean equation. In
Verilog, Boolean equations which have similar timing properties as the gate primitives
are defined using a continuous assignment statement.
For example
wire d;
and a1(d, a, b);
not n1(c, d);
can be replaced with one statement:
assign c = !(a && b); //notice that wire d was not used here
Behavioral code is used to describe circuits at a more abstract level then the structural
level statements we have studied. All Behavioral code occurs within either an initial
An initial block executes once during a simulation. Initial blocks are usually used to
initialize variables and to describe stimulus waveforms which exercise which drive the
simulation.
An always block continuously repeats its execution during a simulation. Always blocks
usually contain behavioral code that models the actual circuit operation.
During a simulation each always and each initial block begin to execute at time zero.
Each block executes concurrently with each structural statement and all the other
behavioral blocks. The following example shows a behavioral SRAM model. The initial
block sets the memory cells to zero at startup. The always block executes each time there
is a change on the write control line, the chip select line, or the address bus. As an
exercise, copy and paste this code into a verilog file and write a test bench to exercise the
model.
//SRAM Model
module sram(CSB,WRB,ABUS,DATABUS);
input CSB; // active low chip select
input WRB; // active low write control
input [11:0] ABUS; // 12-bit address bus
inout [7:0] DATABUS; // 8-bit data bus
//** internal signals
reg [7:0] DATABUS_driver;
wire [7:0] DATABUS = DATABUS_driver;
reg [7:0] ram[0:4095]; // memory cells
integer i;
initial //initialize all RAM cells to 0 at startup
begin
DATABUS_driver = 8'bzzzzzzzz;
for (i=0; i < 4095; i = i + 1)
ram[i] = 0;
end
always @(CSB or WRB or ABUS)
begin
if (CSB == 1'b0)
begin
if (WRB == 1'b0) //Start: latch Data on rising edge of CSB or
WRB
begin
DATABUS_driver <= #10 8'bzzzzzzzz;
@(posedge CSB or posedge WRB);
$display($time," Writing %m ABUS=%b DATA=%b",ABUS,DATABUS);
Verilog supports structural data types called nets which model hardware connections
between circuit components. The two most common structural data types are wire and
reg. The wire nets act like real wires in circuits. The reg type hold their values until
another value is put on them, just like a register hardware component. The declarations
for wire and reg signals are inside a module but outside any initial or always block. The
initial state of a reg is x unknown, and the initial state of a wire is z.
Ports:Modules communicate with each other through ports, the signals listed in the
parameter list at the top of the module. Ports can be of type in, out, and inout.
Here are 3 simplistic rules for matching the structural data type to the type of port:
1. Use reg as the outputs of Behavioral blocks. If you us a wire then the value will
never be seen by other blocks.
2. Use wire for all inputs, inouts, and most outputs of Structural elements.
3. If you need a special strength type operation use special net keyword wand, wor,
tir, triand, trior, trireg.
The types in integer and real are convenient data types to use for counting in behavioral
code blocks. These data types act like their counter parts in other programming
languages. If you eventually plan to synthesize your behavioral code then you would
probably want to avoid using these data types because they often synthesize large
circuits.
The data type time can hold a special simulator value called simulation time which is
extracted from the system function $time. The time information can be used to help you
debug your simulations.
..... //code fragment from inside a module
integer i, y;
real a;
real b = 3.5;
real c = 4;
time simulationTime;
initial
begin
y = 4;
i = 5 + y;
c = c + 3.5;
a = 5.3e4;
simulationTime = $time;
$display("integer y = %d, i = %f \n", y, i);
$display("reals c = %f, a = %e, b= %g \n", c, a, b);
$display("time simulationTime = %t \n", simulationTime);
end
The size is always specified as a decimal number. If no is specified then the default size
is at least 32bits and may be larger depending on the machine. Valid base formats are 'b ,
'B , 'h , 'H 'd , 'D , 'o , 'O for binary, hexadecimal, decimal, and octal. Numbers consist
of strings of digits (0-9, A-F, a-f, x, X, z, Z). The X's mean unknown, and the Z's mean
high impedance If no base format is specified the number is assumed to be a decimal
number. Some examples of valid numbers are:
Verilog supports three similar data structures called Arrays, Vectors, and Memories.
Arrays are used to hold several objects of the same type. Vectors are used to represent
multi-bit busses. And Memories are arrays of vectors which are accessed similar to
hardware memories. Read the following examples to determine how to reference and use
the different data structures.
//*** Arrays for integer, time, reg, and vectors of reg ***************
integer i[3:0]; //integer array with a length of 4
time x[20:1]; //time array with length of 19
reg r[7:0]; //scalar reg array with length of 8
c = r[3]; //the 3rd reg value in array r is assigned to c
//*** Vectors are multi-bit words of type reg or net (wire)************
reg [7:0] MultiBitWord1; // 8-bit reg vector with MSB=7 LSB=0
wire [0:7] MultiBitWord2; // 8-bit wire vector with MSB=0 LSB=7
reg [3:0] bitslice;
reg a; // single bit vector often referred to as a
scalar
.... //referencing vectors
a = MultiBitWord1[3]; //applies the 3rd bit of MultiBitWord1 to a
bitslice = MultiBitWord1[3:0]; //applies the 3-0 bits of MultiBitWord1
to bitslice
Operators
Here is a small selection of the Verilog Operators which look similar but have different
effects. Logical Operators evaluate to TRUE or FALSE. Bitwise operators act on each bit
of the operands to produce a multi-bit result. Unary Reduction operators perform the
operation on all bits of the operand to produce a single bit result.
Create the top-level Schematic source file for the project as follows:
1. Click New Source in the New Project dialog box.
2. Select Verilog Module as the source type in the New Source dialog box.
3. Type in the file name counter.
4. Verify that the Add to Project checkbox is selected.
5. Click Next.
6. Declare the ports for the counter design by filling in the port information as shown
below:
7. Click Next, then Finish in the New Source Information dialog box to complete the new
source file template.
8. Click Next, then Next, then Finish.
When you choose the “counter.v” tab you will see the outline of a Verilog module.
Notice that it looks somewhat different than the examples in the textbook. Both methods
of listing inputs and outputs are correct!
Now fill in the code for the counter as shown below – you won’t recognize all the
commands but for this tutorial just copy what is shown below.
When the source files are complete save the file and check the syntax of the design to
find errors and typos.
1. Verify that Synthesis/Implementation is selected from the drop-down list in the
Sources window.
2. Select the counter design source in the Sources window to display the related
processes in the Processes window.
3. Click the “+” next to the Synthesize-XST process to expand the process group.
4. Double-click the Check Syntax process.
Note: You must correct any errors found in your source files. You can check for errors in
the Console tab of the Transcript window. If you continue without valid syntax, you will
not be able to simulate your design.
Create a test bench waveform containing input stimulus you can use to verify the
functionality of the counter module. The test bench waveform is a graphical view of a test
bench.
Create the test bench waveform as follows:
1. Select the counter HDL file in the Sources window.
2. Create a new test bench source by selecting Project → New Source.
3. In the New Source Wizard, select Test Bench WaveForm as the source type, and type
counter_tbw in the File Name field.
4. Click Next.
5. The Associated Source page shows that you are associating the test bench waveform
with the source file counter. Click Next.
6. The Summary page shows that the source will be added to the project, and it displays
the source directory, type and name. Click Finish.
7. You need to set the clock frequency, setup time and output delay times in the Initialize
Timing dialog box before the test bench waveform editing window opens.
Lab Experiments
1. Implementation of all basic gates
Verilog Code
Verilog code for AND GATE Verilog code for OR GATE
module and12(a,b,c); module or12(a,b,d);
input a; input a;
input b; input b;
output c; output d;
assign c = a & b; assign d = a | b;
endmodule endmodule
Verilog code for NAND GATE Verilog code for XOR GATE
module nand12(a,b,e); module xor12(a,b,h);
input a; input a;
input b; input b;
output e; output h;
assign e = ~(a & b); assign h = a ^ b;
endmodule endmodule
Verilog code for XNOR GATE Verilog code for NOR GATE
module xnor12(a,b,i); module nor12(a,b,f);
input a; input a;
input b; input b;
output i; output f;
assign i = ~(a ^ b); assign f = ~(a | b);
endmodule endmodule
Verilog code for NOT GATE
module not12(a,g);
input a;
output g;
assign g = ~a;
endmodule
A) Half Adder
Truth Table
Input Output
A B S(Sum) C(Carry)
0 0 0 0
0 1 1 0
1 0 1 0
1 1 1 1
Circuit Diagram Graphical Notation
Equations
S (Sum) =A^B
C (Carry) =AB
B)Full Adder
Truth Table
Input Output
A B C SUM Cout
0 0 0 0 0
0 0 1 1 0
0 1 0 1 0
0 1 1 0 1
1 0 0 1 0
1 0 1 0 1
1 1 0 0 1
1 1 1 1 1
SUM = A’B’C + A’BC’ + AB’C’ + ABC Cout = A’BC + AB’C + ABC’ +ABC
SUM= A^B^C Cout= (A^B)C+AB
Circuit Diagram
module HA(s,c,a,b);
input a,b;
output s,c;
s=a^b;
c=ab;
endmodule
A) 4:1 Multiplexer
Function Table
Selection output
Inputs
S1 S0
0 0 D0
0 1 D1
1 0 D2
1 1 D3
B)1:4 Demultiplexer
Function table
Function Table
Inputs Output
S1 S0
0 0 Y0=D
0 1 Y1=D
1 0 Y2=D
1 1 Y3=D
Function Table
Input Output
enable A1 A1 A0 Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0
0 x x x 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 1
1 0 0 1 0 0 0 0 0 0 1 0
1 0 1 0 0 0 0 0 0 1 0 0
1 0 1 1 0 0 0 0 1 0 0 0
1 1 0 0 0 0 0 1 0 0 0 0
1 1 0 1 0 0 1 0 0 0 0 0
1 1 1 0 0 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0
Input
enable I7 I6 I5 I4 I3 I2 I1 I0 Y2 Y1 Y0
0 x x x x x x x x 0 0 0
1 0 0 0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 0 1 0 0 0 1
1 0 0 0 0 0 1 0 0 0 1 0
1 0 0 0 0 1 0 0 0 0 1 1
1 0 0 0 1 0 0 0 0 1 0 0
1 0 0 1 0 0 0 0 0 1 0 1
1 0 1 0 0 0 0 0 0 1 1 0
1 1 0 0 0 0 0 0 0 1 1 1
Y0 = I1 + I3 + I5 + I7
Y1= I2 + I3 + I6 + I7
Y2 = I4 + I5 + I6 +I7
Block Diagram8:3 line encoder(Octal-Binary Conversion)
Z7
A0
Z6
Z5 A1
Z4
Z3 8 to 3 line A2
Z2 decoder
Z1
Z0
C) Priority Encoder
Function Table
K-Map simplification
Y0=D3+D1D’2
Y1=D2+D3
V=D0+D1+D2+D3
Circuit Diagram
C= K+ Z1Z3+ Z2Z3
module adder_4bit(carry,sum,a,b,cin);
output carry;
input [3:0] sum;
input [3:0] a,b;
input c_in;
assign {carry,sum}=a+b+cin;
endmodule
(A = B) = x3x2x1x0
Circuit Diagram
module compare(A,B,x,y,z);
input [3:0] A,B;
output x, y,z;
wire x0,x1,x2,x3;
assign x0=((~A[0]&B[0])| (A[0]&~B[0]));
assign x1=((~A[1]&B[1])| (A[1]&~B[1]));
assign x2=((~A[2]&B[2])| (A[2]&~B[2]));
assign x3=((~A[3]&B[3])| (A[3]&~B[3]));
assign x=x0&x1&x2&x3;
assign y=((A[3]&~B[3]|(x3&A[2]&~B[2])|(x3&x2&A[1]&~B[1])|(x3&x2&x1&A[0]&~B[0]));
assign z=((~A[3]&B[3]|(x3&~A[2]&B[2])|(x3&x2&~A[1]&B[1])|(x3&x2&x1&~A[0]&B[0]));
endmodule
A) JK Flip-Flop
Circuit Diagram
Graphical Notation
Characteristic Table
Input Input Output
J K CP Q(t+1)
x x 0 No
Change
0 0 Q(t)
0 1 0
1 0 1
1 1 Q’(t)
Characteristic Equation
Q(t+1)=JQ’(t)+K’Q(t)
Graphical Notation
Characteristic Table
Input Clock Input Next
State
D CP Q(t+1)
x 0/1 No
Change
0 0
1 1
Characteristic Equation
Q(t+1)=D
Verilog code for D flip flop:
module dff(d,clk,q,qbar);
input d;
input clk;
output q,qbar;
reg q, qbar;
always @ (posedge clk)
begin
q = d;
qbar = ~d;
end
Graphical Notation
Characteristic Table
Input Clock Input Next
State
T CP Q(t+1)
x 0/1 No
Change
0 Q(t)
1 Q’(t)
Characteristic Equation
Q (t+1)=T’Q(t)+TQ’(t)
Function Table
Output(count 0-15)
A B C D
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1
Circuit Diagram
module ripple(clkr,st,,t,A,B,C,D);
input clk,rst,t;
output A,B,C,D;
Tff T0(D,clk,rst,t);
Tff T1(C,clk,rst,t);
Tff T2(B,clk,rst,t);
Tff T3(A,clk,rst,t);
endmodule
module Tff(q,clk,rst,t);
input clk,rst,t;
output q;
reg q;
always @(posedge clk)
begin
if(rst)
q<=1’b0;
else
if(t)
Count Table
1 1 1 0 0 0 0 1
1 1 0 1 0 0 1 0
1 1 0 0 0 0 1 1
1 0 1 1 0 1 0 0
1 0 1 0 0 1 0 1
1 0 0 1 0 1 1 0
1 0 0 0 0 1 1 1
0 1 1 1 1 0 0 0
0 1 1 0 1 0 0 1
0 1 0 1 1 0 1 0
0 1 0 0 1 0 1 1
0 0 1 1 1 1 0 0
0 0 1 0 1 1 0 1
0 0 0 1 1 1 1 0
0 0 0 0 1 1 1 1
Circuit diagram
A) Ring Counter
Count Table
clk Qa Qb Qc Qd
1 1 0 0 0
2 0 1 0 0
3 0 0 1 0
4 0 0 0 1
outputs
Vcc QA QB QC QD CLK1
14 13 12 11 10 9 8
74LS95
1 2 3 4 5 6 7
A B C D
A1A
2 1
Count Table
Verilog code
module FA(a,b,c,s,c);
input a,b,c;
output s,c;
assign s=a^b^c;
assign c=((a^b)&c)|(a&b);
endmodule
Function Diagram
Notes
H = HIGH voltage level
h = HIGH voltage level one set-up time prior to the LOW-to-HIGH CP transition
L = LOW voltage level
Verilog Code
module uni_shift(out,l0,r0,in,li,ri,s,clr,clk);
output [3:0] out;
output l0,r0;
input [3:0] in;
intput [1:0] s;
input li,ri,clr,clk;
reg out;
assign l0=out[3];
assign r0=out[0];
always @ (posedge clk)
begin
if(clr)
out<=0;
else
case(s)
3:out<=in;
2:out<={out[2:0],ri};
1:out<={li,out[3:1]};
0:out<=out;
endcase
end
endmodule
Block Diagram
Binary Multiplication
The data path for the sequential multiplier is consists of several registers and an adder.
The required registers include:
E-Register: A 1-bit register, that is used to hold the carryout output of the adder
Initially E is cleared th
It may be considered the 9 Bit of P, i.e. P8.
In the final step, E will hold a 0 value.
Cnt: A 2-bit down counter used to control the number of steps to be performed (total of 4
steps). The counter counts from 3 down to 0. The operation is stopped when the count
reaches 0. This zero condition (Zero) is detected by a NOR gate
Notation: (E, PH) refers to the 5-bit register consisting of E as the MSB and PH. (E,
PH, PL) refer to the 9-bit register consisting of E as the MSB, PH. and PL.
Computation Steps:
1. Initialize: i=0, PH? 0, PL? A, B-Reg? B, Cnt? n-1, where n = number of
operand bits.
2. (E, PH)? PH + aiB = PH + P0B;
3. Shift (E, PH, PL) right by one bit; Cnt? Cnt -1; and i=i+1.
4. IF Cnt = 0 then STOP else Loop back to step 2
Verilog code
module mult(product,ready,multiplicand,multiplier,start,clock,reset_b);
parameter dp_width=5;
output [2*dp_width-1:0] product;
output ready;
input [dp_width-1:0] multiplicand,multiplier;
input start, clock,reset_b;
parameter bc_size=3;
parameter s_Idle=3'b001;
parameter s_add=3'b010;
parameter s_shift=3'b100;
reg [2:0] state,next_state;
reg [dp_width-1:0] A,B,Q;
reg c;
reg [bc_size-1:0] p;
reg load_regs,dec_p,add_regs,shift_regs;
// miscellaneous combinational logic
assign product={A,B};
wire zero=(p==0);
//zero=~p;
wire ready=(state==s_idle);
// control unit
always @ (posedge clock, negedge reset_b)
if(~reset_b)
state<=s_idle;
else
state<=next_state;
always @ (state,start,Q[0],zero)
begin
next_state=s_idle;
load_regs=0;
decr_p=0;
add_regs=0;
shift_regs=0;
case(state)
s_idle:begin
If(start)
Next_state=s_add;
// data unit
always @(posedge clock)
begin
if(load_regs)
begin
p<=dp_width;
A<=0;
C<=0;
B<=multiplicand;
Q<=multiplier;
end
if(add_regs)
{C,A}=A+B;
If(shift_regs}
{C,A,Q}<={C,A,Q}>>1;
If(decr_p)
p<=p-1;
end
endmodule
To load the project first we need to double click the Xilinx 9.2i ISE shortcut present on
the desktop or in corresponding drive. As soon as the software opens it shows a ‘Tip of
the day’ on which we select ok.
Make appropriate selections and click next then Add source using Add source option and
click to load files.
To synthesize check syntax first in the behavioral simulation mode and simulate using
simulate behavioral mode.