Verilog Reference Guide From
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
No. 1 – AND Gate
Introduction
Example
/* A simple AND gate File: and.v */
module andgate (a, b, y);
input a, b;
output y;
assign y = a & b;
endmodule
RTL Schematic
Simulation Text Fixture
/* testbench for AND gate File: and_tb.v */
module andgate_tb;
wire t_y;
reg t_a, t_b;
andgate my_gate( .a(t_a), .b(t_b), .y(t_y) );
initial
begin
$monitor(t_a, t_b, t_y);
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
No. 2 – Procedural Blocks
Example:
module comb(a, b, c);
input c;
input b;
output a;
reg a;
always @( c or b)
begin
a = c & b;
end
endmodule
RTL:
1. Figure: Output of module comb
Simulation TestFixture:
module forkjoin(clk, a, b);
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 (
binary_in , // 4 bit binary input
decoder_out , // 16-bit out
enable // Enable for the decoder
);
input [3:0] binary_in ;
input enable ;
output [15:0] decoder_out ;
wire [15:0] decoder_out ;
assign decoder_out = (enable) ? (1 << binary_in) : 16'b0 ;
endmodule
No. 4 – MUX (2:1)
Module mux21a (
Input wire a,
Input wire b,
Input wire s,
Output wire y
);
assign y = ~s & a| s &strong;
endmodule
Simulation
No. 5 – 2:1 MUX with Gate level modelling
Example
//declare the Verilog module - The inputs and output signals.
module mux2to1(
Data_in_0,
Data_in_1,
sel,
Data_out
);
//what are the input ports.
input Data_in_0;
input Data_in_1;
input sel;
//What are the output ports.
output Data_out;
//Internal variables.
wire not_sel;
wire temp1,temp2;
wire Data_out_temp;
//NOT gate - first signal(not_sel) is output and others are inputs.
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 gate - first signal(Data_out_temp) is output and others are inputs.
or or_1(Data_out_temp,temp1,temp2);
//Assign the final value to the output port.
assign Data_out = Data_out_temp;
endmodule
Output
No. 6 – 2:1 MUX using if statements
Example
//declare the Verilog module - The inputs and output signals.
module mux2to1( Data_in_0, Data_in_1, sel, Data_out );
//what are the input ports.
input Data_in_0;
input Data_in_1;
input sel; //What are the output ports.
output Data_out; //Internal variables.
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
if(sel == 0) Data_out = Data_in_0; //when select signal to the mux
is low
else Data_out = Data_in_1; //when select signal to the mux is
high
end
endmodule
Simulation Test Fixture
module tb_mux;
// Declaring Inputs
reg Data_in_0;
reg Data_in_1;
reg sel;
// Declaring Outputs
wire Data_out;
// Instantiate the Unit Under Test (UUT)
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;
//Similarly apply Inputs and wait for 100 ns
Data_in_0 = 0; Data_in_1 = 0; sel = 1; #100;
Data_in_0 = 0; Data_in_1 = 1; sel = 0; #100;
Data_in_0 = 0; Data_in_1 = 1; sel = 1; #100;
Data_in_0 = 1; Data_in_1 = 0; sel = 0; #100;
Data_in_0 = 1; Data_in_1 = 0; sel = 1; #100;
Data_in_0 = 1; Data_in_1 = 1; sel = 0; #100;
Data_in_0 = 1; Data_in_1 = 1; sel = 1; #100;
end
endmodule
Output
No. 7 – Structural Level Coding of MUX [4:1]
A multiplexer (or mux) is a device that selects one of several input signals
and forwards the selected input into a single output line. In previous posts,
there is Verilog code for 2:1 MUX's using Behavioral modelling and Gate
level modelling. It might have to use either of these codes in this example.
In the structural level coding using Verilog ,the 2:1 MUX's is used to create
a 4:1 MUX. A 4:1 MUX has 4 input bits, a 2 bit select signal and one single
output bit. It can be implemented using three 2:1 MUX's as shown below:
Example
//Declare the ports of the module
module mux4to1(
Data_in_0,
Data_in_1,
Data_in_2,
Data_in_3,
sel,
Data_out );
//list the inputs and their sizes
input
Data_in_0;
input Data_in_1;
input Data_in_2;
input Data_in_3;
input [1:0] sel;
//list the outputs and their sizes
output Data_out;
//Instantiate the mux for selecting between input 0 or 1.
mux2to1 low_mux (
.Data_in_0(Data_in_0),
.Data_in_1(Data_in_1),
.sel(sel[0]),
//LSB of sel is connected here
.Data_out(Data_temp1)
); //Instantiate the mux for selecting between input 2 or 3.
mux2to1 high_mux (
.Data_in_0(Data_in_2),
.Data_in_1(Data_in_3),
.sel(sel[0]),
//LSB of sel is connected here
.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]),
//MSB of sel is connected here
.Data_out(Data_out)
//The output of module is connected here.
);
endmodule
Testbench for 4:1 MUX
module tb_tm; // Inputs
reg Data_in_0;
reg Data_in_1;
reg Data_in_2;
reg Data_in_3;
reg [1:0] sel; // Outputs
wire Data_out; // Instantiate the Unit Under Test (UUT)
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)
);
initial begin // Initialize Inputs
Data_in_0 = 0;
Data_in_1 = 0;
Data_in_2 = 0;
Data_in_3 = 0; sel = 0; #100;
Data_in_0 = 1; #100; Data_in_0 = 0; Data_in_1 = 1; #100;
sel = 1; #100;
Data_in_1 = 0; Data_in_2 = 1; #100;
sel = 2; #100;
Data_in_2 = 0; Data_in_3 = 1; #100; sel = 3; #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
module demux (s2,s1,I,en,y0,y1,y2,y3)
input s2,s1,I,en;
output y0,y1,y2,y3;
assign y0=(~s2)&(~s1)& I& en;
assign y1=(~s2)& s1& I& en;
assign y2=s2&(~s1)& I & en;
assign y3=s2& s1 & I & en;
end module
No. 10 – 1:4 Demux using Case statements
Example
Demultiplexer(Also known as Demux) is a data distributer, which is
basically the exact opposite of a multiplexer. A Demux can have one single
bit data input and a N-bit select line. The number of output lines will be
2^N.Here is the Verilog code for a 1:4 Demux. The code is designed using
behavioral modelling and implemented using Case statements.
//Verilog module for 1:4 DEMUX
module demux1to4(
Data_in, sel, Data_out_0, Data_out_1, Data_out_2, Data_out
_3
); //list the inputs and their sizes
input Data_in; input [1:0] sel;
//list the outputs and their sizes
output Data_out_0; output Data_out_1; output Data_out_2; output
Data_out_3;
//Internal variables
reg Data_out_0; reg Data_out_1; reg Data_out_2; reg Data_out_3;
//always block with Data_in and sel in its sensitivity list
always @(Data_in or sel)
begin
case (sel)
//case statement with "sel"
//multiple statements can be written inside each case.
//you just have to use 'begin' and 'end' keywords as shown below.
2'b00 : begin Data_out_0 = Data_in; Data_ou
t_1 = 0; Data_out_2 = 0; Data_out_3 = 0;
end
2'b01 : begin Data_out_0 = 0; Data_out_1 =
Data_in; Data_out_2 = 0; Data_out_3 = 0;
end
2'b10 : begin Data_out_0 = 0; Data_out_1 =
0; Data_out_2 = Data_in; Data_out_3 = 0;
end
2'b11 : begin Data_out_0 = 0; Data_out_1 =
0;
Data_out_2 = 0;
Data_out_3 = Data_in;
end
endcase
end
endmodule
Simulation Test Fixture
module tb_demux;
// Inputs
reg Data_in;
reg [1:0] sel;
// Outputs
wire Data_out_0;
wire Data_out_1;
wire Data_out_2;
wire Data_out_3;
// Instantiate the Unit Under Test (UUT)
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
Data_in = 1; sel = 0; #100; sel = 1; #100;
sel = 2; #100; sel = 3; #100; Data_in = 0;
end
endmodule
Output
Figure: The simulated waveform is generate Xilinx ISE 13.1
No. 11 – Half Adder (HA)
Example
module halfadder(
input wire a,
input wire b,
output wire c,
output wire s
);
assign s = b^ a;
assign c= b & a;
endmodule
No. 12 – Full Adder: Structural Design using Half Adder
and OR Gate.
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
module RC_adder( A, B, C_in, Sum_out, C_out);
//What are the Inputs?
input [3:0] A; input [3:0] B; input C_in;
//What are the Outputs?
output [3:0] Sum_out; output C_out;
//Internal variables.
wire [3:0] Sum; wire [3:0] Carry; wire [3:0] Sum_out; wire C_out;
//Instantiate Full Adder 1
full_adder fa1(
.Data_in_A (A[0]), .Data_in_B (B[0]), .Data_in_C (C_in), .Data
_out_Sum (Sum[0]), .Data_out_Carry (Carry[0])
);
//Instantiate Full Adder 2
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])
);
//Instantiate Full Adder 3
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])
);
//Assign the final outputs.
assign Sum_out = Sum;
assign C_out = Carry[3];
endmodule
Simulation Test Fixture
module tb_RCA; // Inputs
reg [3:0] A; reg [3:0] B; reg C_in;
// Outputs
wire [3:0] Sum_out; wire C_out;
// Instantiate the Unit Under Test (UUT)
RC_adder uut (
.A(A), .B(B), .C_in(C_in), .Sum_out(Sum_out), .C_o
ut(C_out)
);
initial begin //Apply Inputs
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 = 13; B = 11; C_in = 1; #100;
A = 15; B = 3; C_in = 0; #100;
A = 0; B = 0; C_in = 1; #100;
end
endmodule
Output: Waveform
No. 14 – Encoder (if - else)
Example
module encoder_using_if(
binary_out , // 4 bit binary output
encoder_in , // 16-bit input
enable // Enable for the encoder
);
//-----------Output Ports---------------
output [3:0] binary_out ;
//-----------Input Ports---------------
input enable ;
input [15:0] encoder_in ;
//------------Internal Variables--------
reg [3:0] binary_out ;
//-------------Code Start-----------------
always @ (enable or encoder_in)
begin
binary_out = 0;
if (enable) begin
if (encoder_in == 16'h0002) begin
binary_out = 1;
end if (encoder_in == 16'h0004) begin
binary_out = 2;
end if (encoder_in == 16'h0008) begin
binary_out = 3;
end if (encoder_in == 16'h0010) begin
binary_out = 4;
end if (encoder_in == 16'h0020) begin
binary_out = 5;
end if (encoder_in == 16'h0040) begin
binary_out = 6;
end if (encoder_in == 16'h0080) begin
binary_out = 7;
end if (encoder_in == 16'h0100) begin
binary_out = 8;
end if (encoder_in == 16'h0200) begin
binary_out = 9;
end if (encoder_in == 16'h0400) begin
binary_out = 10;
end if (encoder_in == 16'h0800) begin
binary_out = 11;
end if (encoder_in == 16'h1000) begin
binary_out = 12;
end if (encoder_in == 16'h2000) begin
binary_out = 13;
end if (encoder_in == 16'h4000) begin
binary_out = 14;
end if (encoder_in == 16'h8000) begin
binary_out = 15;
end
end
end
endmodule
No. 10 – Encoder (Using Case)
Example
module encoder_using_case(
binary_out , // 4 bit binary Output
encoder_in , // 16-bit Input
enable // Enable for the encoder
);
output [3:0] binary_out ;
input enable ;
input [15:0] encoder_in ;
reg [3:0] binary_out ;
always @ (enable or encoder_in)
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;
16'h0400 : binary_out = 10;
16'h0800 : binary_out = 11;
16'h1000 : binary_out = 12;
16'h2000 : binary_out = 13;
16'h4000 : binary_out = 14;
16'h8000 : binary_out = 15;
endcase
end
end
endmodule
No. 10 – Decoder (Case Statement)
Example
module decoder_using_case (
binary_in , // 4 bit binary input
decoder_out , // 16-bit out
enable // Enable for the decoder
);
input [3:0] binary_in ;
input enable ;
output [15:0] decoder_out ;
reg [15:0] decoder_out ;
always @ (enable or binary_in)
begin
decoder_out = 0;
if (enable) begin
case (binary_in)
4'h0 : decoder_out = 16'h0001;
4'h1 : decoder_out = 16'h0002;
4'h2 : decoder_out = 16'h0004;
4'h3 : decoder_out = 16'h0008;
4'h4 : decoder_out = 16'h0010;
4'h5 : decoder_out = 16'h0020;
4'h6 : decoder_out = 16'h0040;
4'h7 : decoder_out = 16'h0080;
4'h8 : decoder_out = 16'h0100;
4'h9 : decoder_out = 16'h0200;
4'hA : decoder_out = 16'h0400;
4'hB : decoder_out = 16'h0800;
4'hC : decoder_out = 16'h1000;
4'hD : decoder_out = 16'h2000;
4'hE : decoder_out = 16'h4000;
4'hF : decoder_out = 16'h8000;
endcase
end
end
endmodule
No. 12 – MUX (4:1)
Example
<Illustrative short example using the syntax goes here> <make code font –
courier new>
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. 1 – 4 bit comparator
A simple comparator with two 4 bit inputs and three output bits which says,
whether one of the input is less, greater or equal to the second input.
Example
//declare the Verilog module - The inputs and output signals.
module comparator(
Data_in_A, //input A
Data_in_B, //input B
less, //high when A is less than B
equal, //high when A is equal to B
greater //high when A is greater than B
);
//what are the input ports.
input [3:0] Data_in_A;
input [3:0] Data_in_B;
//What are the output ports.
output less;
output equal;
output greater;
//Internal variables
reg less;
reg equal;
reg greater;
//When the inputs and A or B are changed execute this block
always @(Data_in_A or Data_in_B)
begin
if(Data_in_A > Data_in_B) begin //check if A is bigger than B.
less = 0;
equal = 0;
greater = 1; end
else if(Data_in_A == Data_in_B) begin //Check if A is equal to B
less = 0;
equal = 1;
greater = 0; end
else begin //Otherwise - check for A less than B.
less = 1;
equal = 0;
greater =0;
end
end
endmodule
Testbench for Comparator:
module tb_tm;
// Inputs
reg [3:0] Data_in_A;
reg [3:0] Data_in_B;
// Outputs
wire less;
wire equal;
wire greater;
// Instantiate the Unit Under Test (UUT)
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.
Our ALU is capable of doing the following operations:
These functions are implemented using a case statement. The ALU
calculates the outputs, whenever there is a change in the input operands A
or B or in the operation to be performed Op . As soon as the outputs are
calculated it is available at the port signal 'R'.
Example
//Verilog module for an ALU
module ALU(
A, B, Op, R
); //inputs,outputs and internal variables declared here
input [7:0] A,B;
input [2:0] Op;
output [7:0] R;
wire [7:0] Reg1,Reg2;
reg [7:0] Reg3;
//Assign A and B to internal variables for doing operations
assign Reg1 = A;
assign Reg2 = B; //Assign the output
assign R = Reg3;
//Always block with inputs in the sensitivity list.
always @(Op or Reg1 or Reg2)
begin
case (Op)
0 : Reg3 = Reg1 + Reg2; //addition
1 : Reg3 = Reg1 - Reg2; //subtraction
2 : Reg3 = ~Reg1; //NOT gate
3 : Reg3 = ~(Reg1 & Reg2); //NAND gate
4 : Reg3 = ~(Reg1 | Reg2); //NOR gate
5 : Reg3 = Reg1 & Reg2; //AND gate
6 : Reg3 = Reg1 | Reg2; //OR gate
7 : Reg3 = Reg1 ^ Reg2; //XOR gate
endcase
end
endmodule
Simulation test Fixture
module tb_alu; // Inputs
reg [7:0] A;
reg [7:0] B;
reg [2:0] Op;
// Outputs
wire [7:0] R;
// Instantiate the Unit Under Test (UUT)
ALU uut (
.A(A), .B(B), .Op(Op), .R(R)
);
initial begin // Apply inputs.
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
No. 9 – Syntax Name
Example
<Illustrative short example using the syntax goes here> <make code font –
courier new>
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
);
always @ (posedge clk)
Q<= d;
endmodule
Simulation
Reference
ECE UMD EDU
ece-research unm edu /jimp
No. 14 – T Flip Flops (Asynchronous reset)
Example
module tff_async_reset (
data , // Data Input
clk , // Clock Input
reset , // Reset input
q // Q output
);
//-----------Input Ports---------------
input data, clk, reset ;
//-----------Output Ports---------------
output q;
//------------Internal Variables--------
reg q;
//-------------Code Starts Here---------
###p
if (~reset) begin
q <= 1'b0;
end else if (data) begin
q <= !q;
end
endmodule //End Of Module tff_async_reset
No. 13 – T Flip Flops (Synchronous reset)
Example
module tff_sync_reset (
data , // Data Input
clk , // Clock Input
reset , // Reset input
q // Q output
);
//-----------Input Ports---------------
input data, clk, reset ;
//-----------Output Ports---------------
output q;
//------------Internal Variables--------
reg q;
//-------------Code Starts Here---------
always @ ( posedge clk)
if (~reset) begin
q <= 1'b0;
end else if (data) begin
q <= !q;
end
endmodule //End Of Module tff_async_reset
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);
input J,K; //inputs
input Clk; //Clock
input R; //synchronous reset (R)
input S; //synchronous set (S)
input CE; //clock enable (CE)
output Qout; //data output (Q)
//Internal variable
reg Qout;
always@ (posedge(Clk)) //Everything is synchronous to positive edge of
clock
begin
if(R == 1) //reset has highest priority.
Qout = 0;
else
if(S == 1) //set has next priority
Qout = 1;
else
if(CE == 1) //J,K values are considered only when CE is ON.
if(J == 0 && K == 0)
Qout = Qout; //no change
else
if(J == 0 && K == 1)
Qout = 0; //reset
else
if(J == 1 && K == 0)
Qout = 1; //set
else
Qout = ~Qout; //toggle
else
Qout = Qout; //no change
end
endmodule
Simulation Test fixture
module tb_jkff; // Inputs
reg J;
reg K;
reg Clk;
reg R;
reg S;
reg CE; // Outputs
wire Qout; // Instantiate the Unit Under Test (UUT)
FJKRSE uut (
.J(J), .K(K), .Clk(Clk), .R(R), .S(S), .CE(CE),
.Qout(Qout)
); //Create 50 Mhz clock(20 ns clock period).
initial Clk = 0;
always
#10 Clk = ~Clk;
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
Output: Simulation Waveform
The codes were simulated in Xilinx ISE 13.1 and we got the following
waveform.
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,
No. 15 – Digital Clock
The module has two inputs - A Clock at 1 Hz frequency and an active high
reset. There are three outputs to tell the time - seconds,minutes and hours.
The time units are incremented in an always block using Behavioral
modelling. At every clock cycle we increment 'seconds'.Whenever seconds
reaches the value '60' we increment 'minutes' by 1.Similarly whenever
minutes reach '60' we increment 'hours' by 1.Once hours reaches the value
'23' we reset the digital clock.
Example
module Digital_Clock(
Clk_1sec, //Clock with 1 Hz frequency
reset, //active high reset
seconds, minutes, hours
); //What are the Inputs?
input Clk_1sec; input reset;
//What are the Outputs?
output [5:0] seconds; output [5:0] minutes; output [4:0] hours;
//Internal variables.
reg [5:0] seconds; reg [5:0] minutes; reg [4:0] hours;
//Execute the always blocks when the Clock or reset inputs are
//changing from 0 to 1(positive edge of the
signal) always @(posedge(Clk_1sec) or posedge(reset))
begin
if(reset == 1'b1)
begin //check for active high reset.
//reset the time.
seconds = 0; minutes = 0; hours = 0;
end
else if(Clk_1sec == 1'b1)
begin //at the beginning of each second
seconds = seconds + 1;
//increment sec
if(seconds == 60)
begin //check for max value of sec
seconds = 0; //reset seconds
minutes = minutes + 1;
//increment minutes
if(minutes == 60)
begin //check for max value of min
minutes = 0; //reset minutes
hours = hours + 1; //increment hours
if(hours == 24) begin //check for max value of hours
hours = 0; //reset hours
end
end
end
end
end
endmodule
Simulation Test fixture
module tb_clock; // Inputs
reg Clk_1sec;
reg reset; // Outputs
wire [5:0] seconds;
wire [5:0] minutes;
wire [4:0] hours; // Instantiate the Unit Under Test (UUT)
Digital_Clock uut (
.Clk_1sec(Clk_1sec), .reset(reset), .seconds(seconds), .m
inutes(minutes), .hours(hours)
);
//Generating the Clock with `1 Hz frequency
initial Clk_1sec = 0;
always
#50000000
Clk_1sec = ~Clk_1sec;
//Every 0.5 sec toggle the clock.
initial begin
reset = 1;
// Wait 100 ns for global reset to finish
#100;
reset = 0;
end
endmodule
Output
Reference
Verilog Codes
No. 16– 4-Bit Binary Counter
Counter includes reset and enable, it counts from the binary "0000" to
"1111" i.e from decimal 0 to 15. Binary Coded Decimal (BCD) counter
counts from 0000 to 1111.
Example
module upcount(Resetn, Clock, E, Q);
input Resetn, Clock, E;
output [3:0] Q;
reg [3:0] Q;
always @(negedge Resetn or posedge Clock)
if (!Resetn)
Q <= 0; // asynchronous reset overrides enable
else if (E)
Q <= Q + 1; // synthesizes adder circuit
endmodule
Simulation
No. 17 – 8-Bit Simple Up Counter
Example
module up_counter (
out , // Output of the counter
enable , // enable for counter
clk , // clock Input
reset // reset Input
);
//----------Output Ports--------------
output [7:0] out;
//------------Input Ports--------------
input enable, clk, reset;
//------------Internal Variables--------
reg [7:0] out;
//-------------Code Starts Here-------
always @(posedge clk)
if (reset) begin
out <= 8'b0 ;
end else if (enable) begin
out <= out + 1;
end
endmodule
Output
No. 18 – 8-Bit Up-Down Counter
Example
module up_down_counter (
out , // Output of the counter
up_down , // up_down control for counter
clk , // clock input
reset // reset input
);
//----------Output Ports--------------
output [7:0] out;
//------------Input Ports--------------
input [7:0] data;
input up_down, clk, reset;
//------------Internal Variables--------
reg [7:0] out;
//-------------Code Starts Here-------
always @(posedge clk)
if (reset) begin // active high reset
out <= 8'b0 ;
end else if (up_down) begin
out <= out + 1;
end else begin
out <= out - 1;
end
endmodule
Output
No. 19– Shift Register
• 4-bit with Parallel Load
• Shift left and shift right
Example
module shift_reg (
input clk,
input load,
input left_right_n,
input [3:0] d,
output [3:0] q
);
always @ (posedge clk) //all operations synchronous
if(load)
q<=d; //sync load
else if (left_right_n)
q<= { q[2:0], 1’b0}; //shift left
else
q<=q>>1; //shift right
endmodule
Simulation
No. 20 – Single Port RAM Synchronous Read/Write
Example
module ram_sp_sr_sw (
clk , // Clock Input
address , // Address Input
data , // Data bi-directional
cs , // Chip Select
we , // Write Enable/Read Enable
oe // Output Enable
);
parameter DATA_WIDTH = 8 ;
parameter ADDR_WIDTH = 8 ;
parameter RAM_DEPTH = 1 << ADDR_WIDTH;
//--------------Input Ports-----------------------
input clk ;
input [ADDR_WIDTH-1:0] address ;
input cs ;
input we ;
input oe ;
//--------------Inout Ports-----------------------
inout [DATA_WIDTH-1:0] data ;
//--------------Internal variables----------------
reg [DATA_WIDTH-1:0] data_out ;
reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];
reg oe_r;
//--------------Code Starts Here------------------
// Tri-State Buffer control
// output : When we = 0, oe = 1, cs = 1
assign data = (cs && oe && !we) ? data_out : 8'bz;
// Memory Write Block
// Write Operation : When we = 1, cs = 1
always @ (posedge clk)
begin : MEM_WRITE
if ( cs && we ) begin
mem[address] = data;
end
end
// Memory Read Block
// Read Operation : When we = 0, oe = 1, cs = 1
always @ (posedge clk)
begin : MEM_READ
if (cs && !we && oe) begin
data_out = mem[address];
oe_r = 1;
end else begin
oe_r = 0;
end
end
endmodule // End of Module ram_sp_sr_sw
Output
Reference
Verilog Guru, Verilog Codes, FPGA4student
No. 21 – Synchronous FIFO
Example
module syn_fifo (
clk , // Clock input
rst , // Active high reset
wr_cs , // Write chip select
rd_cs , // Read chipe select
data_in , // Data input
rd_en , // Read enable
wr_en , // Write Enable
data_out , // Data Output
empty , // FIFO empty
full // FIFO full
);
// FIFO constants
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 8;
parameter RAM_DEPTH = (1 << ADDR_WIDTH);
// Port Declarations
input clk ;
input rst ;
input wr_cs ;
input rd_cs ;
input rd_en ;
input wr_en ;
input [DATA_WIDTH-1:0] data_in ;
output full ;
output empty ;
output [DATA_WIDTH-1:0] data_out ;
//-----------Internal variables-------------------
reg [ADDR_WIDTH-1:0] wr_pointer;
reg [ADDR_WIDTH-1:0] rd_pointer;
reg [ADDR_WIDTH :0] status_cnt;
reg [DATA_WIDTH-1:0] data_out ;
wire [DATA_WIDTH-1:0] data_ram ;
//-----------Variable assignments---------------
assign full = (status_cnt == (RAM_DEPTH-1));
assign empty = (status_cnt == 0);
//-----------Code Start---------------------------
always @ (posedge clk or posedge rst)
begin : WRITE_POINTER
if (rst) begin
wr_pointer <= 0;
end else if (wr_cs && wr_en ) begin
wr_pointer <= wr_pointer + 1;
end
end
always @ (posedge clk or posedge rst)
begin : READ_POINTER
if (rst) begin
rd_pointer <= 0;
end else if (rd_cs && rd_en ) begin
rd_pointer <= rd_pointer + 1;
end
end
always @ (posedge clk or posedge rst)
begin : READ_DATA
if (rst) begin
data_out <= 0;
end else if (rd_cs && rd_en ) begin
data_out <= data_ram;
end
end
always @ (posedge clk or posedge rst)
begin : STATUS_COUNTER
if (rst) begin
status_cnt <= 0;
// Read but no write.
end else if ((rd_cs && rd_en) && !(wr_cs && wr_en)
&& (status_cnt != 0)) begin
status_cnt <= status_cnt - 1;
// Write but no read.
end else if ((wr_cs && wr_en) && !(rd_cs && rd_en)
&& (status_cnt != RAM_DEPTH)) begin
status_cnt <= status_cnt + 1;
end
end
ram_dp_ar_aw #(DATA_WIDTH,ADDR_WIDTH)DP_RAM (
.address_0 (wr_pointer) , // address_0 input
.data_0 (data_in) , // data_0 bi-directional
.cs_0 (wr_cs) , // chip select
.we_0 (wr_en) , // write enable
.oe_0 (1'b0) , // output enable
.address_1 (rd_pointer) , // address_q input
.data_1 (data_ram) , // data_1 bi-directional
.cs_1 (rd_cs) , // chip select
.we_1 (1'b0) , // Read enable
.oe_1 (rd_en) // output enable
);
endmodule
Output
No. 22 – Content Addressable Memory (CAM)
Example
module cam (
clk , // Cam clock
cam_enable , // Cam enable
cam_data_in , // Cam data to match
cam_hit_out , // Cam match has happened
cam_addr_out // Cam output address
);
parameter ADDR_WIDTH = 8;
parameter DEPTH = 1 << ADDR_WIDTH;
//------------Input Ports--------------
input clk;
input cam_enable;
input [DEPTH-1:0] cam_data_in;
//----------Output Ports--------------
output cam_hit_out;
output [ADDR_WIDTH-1:0] cam_addr_out;
//------------Internal Variables--------
reg [ADDR_WIDTH-1:0] cam_addr_out;
reg cam_hit_out;
reg [ADDR_WIDTH-1:0] cam_addr_combo;
reg cam_hit_combo;
reg found_match;
integer i;
//-------------Code Starts Here-------
always @(cam_data_in) begin
cam_addr_combo = {ADDR_WIDTH{1'b0}};
found_match = 1'b0;
cam_hit_combo = 1'b0;
for (i=0; i<DEPTH; i=i+1) begin
if (cam_data_in[i] && !found_match) begin
found_match = 1'b1;
cam_hit_combo = 1'b1;
cam_addr_combo = i;
end else begin
found_match = found_match;
cam_hit_combo = cam_hit_combo;
cam_addr_combo = cam_addr_combo;
end
end
end
// Register the outputs
always @(posedge clk) begin
if (cam_enable) begin
cam_hit_out <= cam_hit_combo;
cam_addr_out <= cam_addr_combo;
end else begin
cam_hit_out <= 1'b0;
cam_addr_out <= {ADDR_WIDTH{1'b0}};
end
end
endmodule
Output
No. 23 – Finite State Machine (FSM) Design
Example
<Illustrative short example using the syntax goes here> <make code font –
courier new>
module jk_counter(count, clock);
input clock;
output [2:0] count;
reg [2:0] count;
parameter [2:0] A = 3'b000, B = 3'b100, C = 3'b111,
D = 3'b010, E = 3'b011;
###p
case(count)
A: count <= B;
B: count <= C;
C: count <= D;
D: count <= E;
E: count <= A;
default: count <= A;
endcase
endmodule
Output
<Output of the above example goes here>
Simulation
No. 24 – Modeling With Switch Primitives (Not Gate using
switch)
Example
module not_switch (out, in);
output out;
input in;
supply1 power;
supply0 ground;
pmos (out, power, in);
nmos (out, ground, in);
endmodule
No. 25 – User Defined Primitives (Two Input OR using
UDP)
Example
primitive or2_input (c,a,b);
output c;
input a,b;
table
//a b : c
1 ? : 1;
? 1 : 1;
0 0 : 0;
0 x : x;
x 0 : x;
endtable
endprimitive
Looping Structures in Verilog
No. 26 – Synthesisable Verilog code for Division of two
binary numbers
For doing division, Verilog has an operator, '/' defined. But this operator has
some limitation when it comes to certain synthesis tools such as Xilinx
XST. The '/' operator is synthesisable only when the second operand is a
power of 2.
For division of generic numbers Xilinx returns the following error message
during synthesis:
Can not simplify operator DIV
The design was based on Restoring Division algorithm.
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 and output ports.
input [WIDTH-1:0] A;
input [WIDTH-1:0] B; output [WIDTH-1:0] Res;
//internal variables
reg [WIDTH-1:0] Res = 0; reg [WIDTH-
1:0] a1,b1; reg [WIDTH:0] p1; integer i; always@ (A or B)
begin
//initialize the variables.
a1 = A; b1 = B; p1= 0;
for(i=0;i < WIDTH;i=i+1)
begin //start the for loop
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
wire [WIDTH-1:0] Res;
// Instantiate the division module (UUT)
division #(WIDTH)
uut (
.A(A), .B(B), .Res(Res)
);
initial begin
// Initialize Inputs and wait for 100 ns
A = 0; B = 0; #100;
//Undefined inputs
//Apply each set of inputs and wait for 100 ns.
A = 100; B = 10; #100;
A = 200; B = 40; #100;
A = 90; B = 9; #100;
A = 70; B = 10; #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.
No. 27 – Verilog code for 4 bit Wallace tree multiplier
A Wallace tree multiplier is much faster than the normal multiplier designs.
The design uses half adder and full adder Verilog designs . These modules
will be instantiated for the implementation 4 bit Wallace multiplier.
Example
module wallace(A,B,prod);
//inputs and outputs
input [3:0] A,B; output [7:0] 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;
//initialize the p's.
assign p0 = A & {4{B[0]}}; assign p1 = A & {4{B[1]}}; assign p2 = A
& {4{B[2]}};
assign p3 = A & {4{B[3]}};
//final product assignments
assign prod[0] = p0[0]; assign prod[1] = s11; assign prod[2] = s22;
assign prod[3] = s32; assign prod[4] = s34; assign prod[5] = s35;
assign prod[6] = s36; assign prod[7] = s37; //first stage
half_adder ha11 (p0[1],p1[0],s11,c11);
full_adder fa12(p0[2],p1[1],p2[0],s12,c12);
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
half_adder ha22 (c11,s12,s22,c22);
full_adder fa23 (p3[0],c12,s13,s23,c23);
full_adder fa24 (c13,c32,s14,s24,c24);
full_adder fa25 (c14,c24,s15,s25,c25);
full_adder fa26 (c15,c25,p3[3],s26,c26);
//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
reg [3:0] A; reg [3:0] B;
// Outputs
wire [7:0] prod;
integer i,j,error;
// Instantiate the Unit Under Test (UUT)
wallace uut (
.A(A), .B(B), .prod(prod)
);
initial begin
// Apply inputs for the whole range of A and B.
// 16*16 = 256 inputs.
error = 0;
for(i=0;i <=15;i = i+1)
for(j=0;j <=15;j = j+1)
begin
A <= i;
B <= j;
#1;
if(prod != A*B)
//if the result isnt correct increment "error".
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.
To get the sample values following commands can be used in Matlab.
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);
//declare input and output
input Clk; output [7:0] data_out;
//declare the sine ROM - 30 registers each 8 bit wide.
reg [7:0] sine [0:29];
//Internal signals
integer i; reg [7:0] data_out;
//Initialize the sine rom with samples.
initial begin i = 0; sine[0] = 0; sine[1] = 16; sine[2] = 31
; sine[3] = 45; sine[4] = 58; sine[5] = 67; sine[6] = 74;
sine[7] = 77; sine[8] = 77; sine[9] = 74; sine[10] = 67;
sine[11] = 58; sine[12] = 45; sine[13] = 31; sine[14] = 16;
sine[15] = 0; sine[16] = -16; sine[17] = -31; sine[18] = -
45; sine[19] = -58; sine[20] = -67; sine[21] = -
74; sine[22] = -77; sine[23] = -77; sine[24] = -
74; sine[25] = -67; sine[26] = -58; sine[27] = -
45; sine[28] = -31; sine[29] = -16;
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
wire [7:0] data_out;
// Instantiate the Unit Under Test (UUT)
sine_wave_gen uut (
.Clk(Clk), .data_out(data_out)
);
//Generate a clock with 10 ns clock period.
initial Clk = 0;
always
#5
Clk = ~Clk;
endmodule
Output