Verilog Reference
Verilog Reference
Digitronix Nepal
Verilog Reference Guide For Beginners
Table of Contents: Design and Simulation of
1. Gate
2. MUX, Encoder
3. DeMUX, Decoder
4. Half Adder
5. Full Adder
6. ALU Design (2–bit)
7. Latch , Flip-flops
8. Structural Design in Verilog: 8 bit ALU Design
9. Counter Design
10. Finite State Machine: Sequence Detector
11. File Handling in Verilog
12. Image Processing in Verilog
13. Complete flow for Implementing design in Spartan 3e FPGA
Example
/* A simple AND gate File: and.v */
input a, b;
output y;
assign y = a & b;
endmodule
RTL Schematic
module andgate_tb;
wire t_y;
initial
begin
t_a = 1'b0;
t_b = 1'b0;
#5
t_a = 1'b0;
t_b = 1'b1;
#5
t_a = 1'b1;
t_b = 1'b0;
#5
t_a = 1'b1;
t_b = 1'b1;
end endmodule
Simulation Output
Reference
Electrosoft
Verilog Codes
input c;
input b;
output a;
reg a;
always @( c or b)
begin
a = c & b;
end
endmodule
RTL:
Simulation TestFixture:
input clk;
output a;
output b;
reg a, b;
initial
begin
a = 0;
b = 0;
end
always @(posedge clk)
fork
#2 a = 1;
#1 b = 1;
join
endmodule
Output:
No. 3 – Decoder
Decoder selects 2n signals from n select signals.
Example:
module decoder_using_assign (
);
input enable ;
endmodule
Module mux21a (
Input wire a,
Input wire b,
Input wire s,
Output wire y
);
endmodule
Simulation
No. 5 – 2:1 MUX with Gate level modelling
Example
module mux2to1(
Data_in_0,
Data_in_1,
sel,
Data_out
);
input Data_in_0;
input Data_in_1;
input sel;
//Internal variables.
wire not_sel;
wire temp1,temp2;
wire Data_out_temp;
not n1(not_sel,sel);
//AND gate - first signal(temp1 and temp2) is output and others are
inputs.
and and_1(temp1,Data_in_0,not_sel);
and and_2(temp2,Data_in_1,sel);
or or_1(Data_out_temp,temp1,temp2);
endmodule
Output
No. 6 – 2:1 MUX using if statements
Example
input Data_in_0;
input Data_in_1;
reg Data_out; //Always block - the statements inside this block are
executed when the given sensitivity list //is satidfied. for example in this
case the block is executed when any changes occur in the three
signals //named 'Data_in_0','Data_in_1' or
'sel'. always @(Data_in_0,Data_in_1,sel)
begin
end
endmodule
module tb_mux;
// Declaring Inputs
reg Data_in_0;
reg Data_in_1;
reg sel;
// Declaring Outputs
wire Data_out;
mux2to1 uut (
.Data_in_0(Data_in_0),
.Data_in_1(Data_in_1),
.sel(sel),
.Data_out(Data_out)
);
initial begin
// Apply Inputs
Data_in_0 = 0;
Data_in_1 = 0;
sel = 0;
// Wait 100 ns
#100;
end
endmodule
Output
Example
module mux4to1(
Data_in_0,
Data_in_1,
Data_in_2,
Data_in_3,
sel,
Data_out );
Data_in_0;
input Data_in_1;
input Data_in_2;
input Data_in_3;
output Data_out;
mux2to1 low_mux (
.Data_in_0(Data_in_0),
.Data_in_1(Data_in_1),
.sel(sel[0]),
.Data_out(Data_temp1)
mux2to1 high_mux (
.Data_in_0(Data_in_2),
.Data_in_1(Data_in_3),
.sel(sel[0]),
.Data_out(Data_temp2)
); //Instantiate the mux for selecting between low or high mux
output
mux2to1 last_mux (
.Data_in_0(Data_temp1),
.Data_in_1(Data_temp2),
.sel(sel[1]),
.Data_out(Data_out)
);
endmodule
reg Data_in_0;
reg Data_in_1;
reg Data_in_2;
reg Data_in_3;
mux4to1 uut (
.Data_in_0(Data_in_0),
.Data_in_1(Data_in_1),
.Data_in_2(Data_in_2),
.Data_in_3(Data_in_3),
.sel(sel),
.Data_out(Data_out)
);
Data_in_0 = 0;
Data_in_1 = 0;
Data_in_2 = 0;
sel = 1; #100;
sel = 2; #100;
end
endmodule
Output
No. 8 – MUX (4:1)
Example
module mux4( select, d, q );
input[1:0] select;
input[3:0] d;
output q;
reg q;
wire[1:0] select;
wire[3:0] d;
always @( select or d )
begin
case( select )
0 : q = d[0];
1 : q = d[1];
2 : q = d[2];
3 : q = d[3];
endcase
end
endmodule
No. 9– 1 to 4 De-multiplexer
Example
input s2,s1,I,en;
output y0,y1,y2,y3;
end module
module demux1to4(
//Internal variables
case (sel)
//you just have to use 'begin' and 'end' keywords as shown below.
end
end
end
Data_out_2 = 0;
Data_out_3 = Data_in;
end
endcase
end
endmodule
// Inputs
reg Data_in;
// Outputs
wire Data_out_0;
wire Data_out_1;
wire Data_out_2;
wire Data_out_3;
demux1to4 uut (
.Data_in(Data_in),
.sel(sel),
.Data_out_0(Data_out_0),
.Data_out_1(Data_out_1),
.Data_out_2(Data_out_2),
.Data_out_3(Data_out_3)
);
initial begin
//Apply Inputs
end
endmodule
Output
Example
module halfadder(
input wire a,
input wire b,
output wire c,
output wire s
);
assign s = b^ a;
assign c= b & a;
endmodule
Example
No. 13 – Ripple Carry Adder using Structural Level
Ripple carry adder(RCA) is the most basic form of digital adder for adding
multi bit numbers. The adder is implemented by concatenating N full-
adders to form a N-bit adder. For a 4 bit RCA, the block diagram can be
drawn like
this:
The full adder and half adder modules written in a previous post to
implement RCA. The coding is done in structural modelling.
The code size can be much smaller and compact looking, while using
behavioral modelling.
Example
//Verilog module for Ripple Carry Adder
//Internal variables.
wire [3:0] Sum; wire [3:0] Carry; wire [3:0] Sum_out; wire C_out;
full_adder fa1(
);
full_adder
fa2( .Data_in_A (A[1]), .Data_in_B (B[1]), .Data_in_C (Carry[0]),
.Data_out_Sum (Sum[1]), .Data_out_Carry (Carry[1])
);
full_adder
fa3( .Data_in_A (A[2]), .Data_in_B (B[2]), .Data_in_C (Carry[1]),
.Data_out_Sum (Sum[2]), .Data_out_Carry (Carry[2])
);
//Instantiate Full Adder 4
full_adder
fa4( .Data_in_A (A[3]), .Data_in_B (B[3]), .Data_in_C (Carry[2]),
.Data_out_Sum (Sum[3]), .Data_out_Carry (Carry[3])
);
endmodule
// Outputs
RC_adder uut (
);
A = 3; B = 6; C_in = 0; #100;
A = 5; B = 7; C_in = 1; #100;
A = 6; B = 4; C_in = 0; #100;
A = 8; B = 9; C_in = 1; #100;
A = 11; B = 10; C_in = 0; #100;
A = 0; B = 0; C_in = 1; #100;
end
endmodule
Output: Waveform
);
//-----------Output Ports---------------
//-----------Input Ports---------------
input enable ;
//------------Internal Variables--------
begin
binary_out = 0;
if (enable) begin
binary_out = 1;
binary_out = 2;
binary_out = 3;
binary_out = 4;
binary_out = 5;
binary_out = 6;
binary_out = 7;
binary_out = 8;
binary_out = 9;
end if (encoder_in == 16'h0400) begin
binary_out = 10;
binary_out = 11;
binary_out = 12;
binary_out = 13;
binary_out = 14;
binary_out = 15;
end
end
end
endmodule
);
input enable ;
begin
binary_out = 0;
if (enable) begin
case (encoder_in)
16'h0002 : binary_out = 1;
16'h0004 : binary_out = 2;
16'h0008 : binary_out = 3;
16'h0010 : binary_out = 4;
16'h0020 : binary_out = 5;
16'h0040 : binary_out = 6;
16'h0080 : binary_out = 7;
16'h0100 : binary_out = 8;
16'h0200 : binary_out = 9;
endcase
end
end
endmodule
);
input enable ;
begin
decoder_out = 0;
if (enable) begin
case (binary_in)
endcase
end
end
endmodule
No. 12 – MUX (4:1)
Example
<Illustrative short example using the syntax goes here> <make code font –
courier new>
input[1:0] select;
input[3:0] d;
output q;
reg q;
wire[1:0] select;
wire[3:0] d;
always @( select or d )
begin
case( select )
0 : q = d[0];
1 : q = d[1];
2 : q = d[2];
3 : q = d[3];
endcase
end
endmodule
Example
//declare the Verilog module - The inputs and output signals.
module comparator(
Data_in_A, //input A
Data_in_B, //input B
);
output less;
output equal;
output greater;
//Internal variables
reg less;
reg equal;
reg greater;
begin
less = 0;
equal = 0;
greater = 1; end
less = 0;
equal = 1;
greater = 0; end
less = 1;
equal = 0;
greater =0;
end
end
endmodule
Testbench for Comparator:
module tb_tm;
// Inputs
// Outputs
wire less;
wire equal;
wire greater;
comparator uut (
.Data_in_A(Data_in_A),
.Data_in_B(Data_in_B),
.less(less),
.equal(equal),
.greater(greater)
);
initial begin
//Apply inputs
Data_in_A = 10;
Data_in_B = 12;
#100;
Data_in_A = 15;
Data_in_B = 11;
#100;
Data_in_A = 10;
Data_in_B = 10;
#100;
end
endmodule
Output
No. 8 – ALU
ALU(Arithmetic Logic Unit) is a digital circuit which does arithmetic and
logical operations. Its a basic block in any processor. Note that this is one
of the simplest architecture of an ALU. Most of the ALU's used in practical
designs are far more complicated and requires good design experience.
The block diagram of the ALU is given below.It receives two input operands
'A' and 'B' which are 8 bits long. The result is denoted by 'R' which is also 8
bit long. The input signal 'Op' is a 3 bit value which tells the ALU what
operation has to be performed by the ALU. Since 'Op' is 3 bits long we can
have a maximum of 2^3=8 operations.
Example
//Verilog module for an ALU
module ALU(
A, B, Op, R
output [7:0] R;
assign Reg1 = A;
assign R = Reg3;
begin
case (Op)
endcase
end
endmodule
reg [7:0] A;
reg [7:0] B;
// Outputs
wire [7:0] R;
ALU uut (
);
A = 8'b01101010;
B = 8'b00111011;
Op = 0; #100;
Op = 1; #100;
Op = 2; #100;
Op = 3; #100;
Op = 4; #100;
Op = 5; #100;
Op = 6; #100;
Op = 7; #100;
end
endmodule
Output
Output
<Output of the above example goes here>
Remarks
<Add comments on the implementation of the above syntax if any>
Reference
No. 11 – Flip Flops
Example
module dflipflop(
input clk,
input d,
output req q
);
Q<= d;
endmodule
Simulation
Reference
ECE UMD EDU
q // Q output
);
//-----------Input Ports---------------
input data, clk, reset ;
//-----------Output Ports---------------
output q;
//------------Internal Variables--------
reg q;
###p
if (~reset) begin
q <= 1'b0;
q <= !q;
end
q // Q output
);
//-----------Input Ports---------------
//-----------Output Ports---------------
output q;
//------------Internal Variables--------
reg q;
if (~reset) begin
q <= 1'b0;
q <= !q;
end
No. 14 – JK Flip-flops
In here the Verilog code for a JK flip flop with synchronous reset,set and
clock enable. The particular flip flop is designed at Xilinx ISE DS and is
called by the name, FJKRSE.
From the truth table, we can see that reset(R) has the highest priority and
set(S) the next priority, then the clock enable (CE) and then the J or K
inputs.
Example
//JK flip flop module
module FJKRSE(J,K,Clk,R,S,CE,Qout);
//Internal variable
reg Qout;
begin
Qout = 0;
else
Qout = 1;
else
else
if(J == 0 && K == 1)
Qout = 0; //reset
else
if(J == 1 && K == 0)
Qout = 1; //set
else
else
end
endmodule
reg J;
reg K;
reg Clk;
reg R;
reg S;
initial Clk = 0;
always
initial begin
// Initialize Inputs
J = 0;
K = 0;
R = 0;
S = 0;
CE = 0;
#30;
//Apply inputs
R = 1; #50;
R = 0;
S = 1; #50;
S = 0;
J = 1; K = 1; #50;
CE = 1; #50;
J = 0; K = 0; #50;
J = 0; K = 1; #50;
J = 1; K = 0; #50;
J = 1; K = 1; #50;
CE = 0;
end
endmodule
Note how the outputs are changed only at the positive edge of the clock.
Also note how the priority of reset,set and clock enable works,
Example
module Digital_Clock(
Clk_1sec, //Clock with 1 Hz frequency
//Internal variables.
//Execute the always blocks when the Clock or reset inputs are
begin
if(reset == 1'b1)
end
seconds = seconds + 1;
//increment sec
if(seconds == 60)
begin //check for max value of sec
minutes = minutes + 1;
//increment minutes
if(minutes == 60)
end
end
end
end
end
endmodule
reg Clk_1sec;
);
initial Clk_1sec = 0;
always
#50000000
Clk_1sec = ~Clk_1sec;
initial begin
reset = 1;
#100;
reset = 0;
end
endmodule
Output
Reference
Verilog Codes
Example
module upcount(Resetn, Clock, E, Q);
output [3:0] Q;
reg [3:0] Q;
if (!Resetn)
else if (E)
endmodule
Simulation
);
//----------Output Ports--------------
//------------Input Ports--------------
//------------Internal Variables--------
end
endmodule
Output
No. 18 – 8-Bit Up-Down Counter
Example
module up_down_counter (
);
//----------Output Ports--------------
//------------Input Ports--------------
//------------Internal Variables--------
reg [7:0] out;
end
endmodule
Output
Example
module shift_reg (
input clk,
input load,
input left_right_n,
input [3:0] d,
output [3:0] q
);
if(load)
else if (left_right_n)
else
endmodule
Simulation
cs , // Chip Select
oe // Output Enable
);
parameter DATA_WIDTH = 8 ;
parameter ADDR_WIDTH = 8 ;
//--------------Input Ports-----------------------
input clk ;
input cs ;
input we ;
input oe ;
//--------------Inout Ports-----------------------
//--------------Internal variables----------------
// output : When we = 0, oe = 1, cs = 1
begin : MEM_WRITE
if ( cs && we ) begin
mem[address] = data;
end
end
begin : MEM_READ
data_out = mem[address];
oe_r = 1;
oe_r = 0;
end
end
Output
Reference
Verilog Guru, Verilog Codes, FPGA4student
// FIFO constants
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 8;
// Port Declarations
input clk ;
input rst ;
input wr_cs ;
input rd_cs ;
input rd_en ;
input wr_en ;
output full ;
output empty ;
//-----------Internal variables-------------------
//-----------Variable assignments---------------
//-----------Code Start---------------------------
begin : WRITE_POINTER
if (rst) begin
wr_pointer <= 0;
end
end
begin : READ_POINTER
if (rst) begin
rd_pointer <= 0;
end
end
begin : READ_DATA
if (rst) begin
data_out <= 0;
end
end
begin : STATUS_COUNTER
if (rst) begin
status_cnt <= 0;
end
ram_dp_ar_aw #(DATA_WIDTH,ADDR_WIDTH)DP_RAM (
);
endmodule
Output
);
parameter ADDR_WIDTH = 8;
//------------Input Ports--------------
input clk;
input cam_enable;
//----------Output Ports--------------
output cam_hit_out;
//------------Internal Variables--------
reg cam_hit_out;
reg cam_hit_combo;
reg found_match;
integer i;
//-------------Code Starts Here-------
cam_addr_combo = {ADDR_WIDTH{1'b0}};
found_match = 1'b0;
cam_hit_combo = 1'b0;
found_match = 1'b1;
cam_hit_combo = 1'b1;
cam_addr_combo = i;
found_match = found_match;
cam_hit_combo = cam_hit_combo;
cam_addr_combo = cam_addr_combo;
end
end
end
if (cam_enable) begin
end
end
endmodule
Output
input clock;
D = 3'b010, E = 3'b011;
###p
case(count)
A: count <= B;
B: count <= C;
C: count <= D;
D: count <= E;
E: count <= A;
endcase
endmodule
Output
<Output of the above example goes here>
Simulation
output out;
input in;
supply1 power;
supply0 ground;
pmos (out, power, in);
endmodule
output c;
input a,b;
table
//a b : c
1 ? : 1;
? 1 : 1;
0 0 : 0;
0 x : x;
x 0 : x;
endtable
endprimitive
For division of generic numbers Xilinx returns the following error message
during synthesis:
Example
The size of operands to the division module are defined through a
parameter named WIDTH. This way you can use the same code for
implementing 8 or 16 or 32 or any sized division. Note that, both the input
operands and output have the same size.
module division(A,B,Res);
//the size of input and output ports of the division module is generic.
parameter WIDTH = 8;
input [WIDTH-1:0] A;
//internal variables
begin
p1 = {p1[WIDTH-2:0],a1[WIDTH-1]};
a1[WIDTH-1:1] = a1[WIDTH-2:0];
p1 = p1-b1;
if(p1[WIDTH-1] == 1)
begin
a1[0] = 0;
p1 = p1 + b1;
end
else
a1[0] = 1;
end
Res = a1;
end
endmodule
Testbench
module tb_division;
parameter WIDTH = 8;
// Inputs
reg [WIDTH-1:0] A;
reg [WIDTH-1:0] B;
// Outputs
division #(WIDTH)
uut (
);
initial begin
A = 0; B = 0; #100;
//Undefined inputs
A = 90; B = 9; #100;
A = 16; B = 3; #100;
A = 255; B = 5; #100;
end
endmodule
Output
Remarks
The design was synthesised for Virtex 4 fpga and a maximum
combinational path delay of 20 ns was obtained for 8 bit division.
Example
module wallace(A,B,prod);
//internal variables.
wire s11,s12,s13,s14,s15,s22,s23,s24,s25,s26,s32,s33,s34,s35,s36,s37;
wire c11,c12,c13,c14,c15,c22,c23,c24,c25,c26,c32,c33,c34,c35,c36,c37;
wire [6:0] p0,p1,p2,p3;
full_adder fa13(p0[3],p1[2],p2[1],s13,c13);
full_adder fa14(p1[3],p2[2],p3[1],s14,c14);
half_adder ha15(p2[3],p3[2],s15,c15);
//second stage
//third stage
half_adder ha32(c22,s23,s32,c32);
half_adder ha34(c23,s24,s34,c34);
half_adder ha35(c34,s25,s35,c35);
half_adder ha36(c35,s26,s36,c36);
half_adder ha37(c36,c26,s37,c37);
endmodule
Simulation Testbench
module tb;
// Inputs
// Outputs
wallace uut (
);
initial begin
error = 0;
begin
A <= i;
B <= j;
#1;
if(prod != A*B)
error = error + 1;
end
end
endmodule
Output
No. 28 – simple Sine Wave Generator
The design uses look up table(LUT) method for generating the sine wave.
The sine wave is sampled at a pre-fixed sample rate and the values are
stored in a ROM. These values are read one by one and output to a
DAC(digital to analog converter) which is not included the DAC interface
code here.
In this particular design the sampled and stored 30 values of a sine wave.
Fort a much more smoother sine wave, sample and store more values in
the ROM at the cost of extra fpga resources.
t=0 : pi/10 : 2*pi ; % for 20 values. t=0 : pi/50 : 2*pi ; % for 100 values etc..
(then type one of the following comment - to convert 't' into integer
format) int32(sin(t)*10000/128) %128 for 8 bit
output. int32(sin(t)*10000/512) %512 for 6 bit output etc...
The design can be modified for efficient use of memory. In that way, only
the first (pi/2) values need to be stored in the ROM. That means the
memory usage is reduced by a factor of 4.
If the frequency of your sine wave is very less, then it is better you increase
the number of sample values. Otherwise there will be lot of high frequency
components in your output wave.
Example
module sine_wave_gen(Clk,data_out);
end
//At every positive edge of the clock, output a sine wave sample.
always@ (posedge(Clk))
begin
data_out = sine[i];
i = i+ 1;
if(i == 29)
i = 0;
end endmodule
Testbench Code:
module tb;
// Inputs
reg Clk;
// Outputs
sine_wave_gen uut (
.Clk(Clk), .data_out(data_out)
);
initial Clk = 0;
always
#5
Clk = ~Clk;
endmodule
Output