//in data flow model module and_gate( input a,b, output y);
//Above style of declaring ports is ANSI style.Verilog2001 Feature
assign y = a & b;
endmodule
TestBench
module tb_and_gate;
reg A,B; wire Y;
and_gate a1 (.a(A) ,.b(B),.y(Y));
//Above style is connecting by names
initialbegin
A =1'b0;
B= 1'b0;
#45 $finish; end
always #6 A =~A; always #3 B =~B;
always @(Y)
$display( "time =%0t \tINPUT VALUES: \t A=%b B =%b \t output value Y =%b",$time,A,B,Y); endmodule
output
time =0 INPUT VALUES: A=0 B =0 output value Y=0
time =6 INPUT VALUES: A=1 B=0 output value Y =0
time =9 INPUT VALUES: A=1 B =1 output value Y =1
time =12 INPUT VALUES: A=0 B =0 output value Y =0
time =18 INPUT VALUES: a=1 b =0 output value y =0
XOR GATE
Truth Table
Verilog design
//in Structural model
module xor_gate ( input a,b, output y);
xor x1(y,a, b); //xor is a built in primitive. While using these primitives you should follow the connection rules. First signal should be output and then inputs.
endmodule
TestBench
module tb_and_gate;
reg A,B; wire Y;
xor_gate a1 (.a(A) ,.b(B),.y(Y));
initialbegin
A =1'b0;
B= 1'b0;
#45 $finish;
end
always #6 A =~A; always #3 B =~B;
always @(Y)
$display( "time =%0t \tINPUT VALUES: \t A=%b B =%b \t output value Y =%b",$time,A,B,Y);
endmodule
output
time =0 INPUT VALUES: A=0 B =0 output value Y =0
time =3 INPUT VALUES: A=0 B =1 output value Y =1
time =6 INPUT VALUES: A=1 B =0 output value Y =1
time =9 INPUT VALUES: A=1 B =1 output value Y =0
OR GATE
Truth Table
Verilog design
//in Behaviour model module or_gate( input a,b, outputreg y);
always @(a,b)
y = a |b;
endmodule
TestBench
module tb_and_gate; reg A,B; wire Y;
or_gate a1 (.a(A) ,.b(B),.y(Y));
initialbegin
A =1'b0;
B= 1'b0;
#45 $finish;
end
always #6 A =~A; always #3 B =~B;
always @(Y)
$display( "time =%0t \tINPUT VALUES: \t A=%b B =%b \t output value Y =%b",$time,A,B,Y);
endmodule
output
time =0 INPUT VALUES: A=0 B =0 output value Y =0
time =3 INPUT VALUES: A=0 B =1 output value Y =1
time =12 INPUT VALUES: A=0 B =0 output value Y =0
time =15 INPUT VALUES: A=0 B =1 output value Y =1
time =24 INPUT VALUES: A=0 B =0 output value Y =0
Half Adder
Truth Table
Verilog design
module half_adder( input a,b, output sum,carry);
assign sum = a^b; assign carry = a & b;
endmodule
TestBench
module tb_half_adder;
reg A,B; wire SUM,CARRY;
half_adder HA (.a(A) ,.b(B),.sum(SUM),.carry(CARRY))
initialbegin
A =1'b0;
B= 1'b0;
#45 $finish; end
always #6 A =~A; always #3 B =~B;
always @(SUM,CARRY)
$display( "time =%0t \tINPUT VALUES: \t A=%b B =%b \t output value SUM =%b CARRY =%b ",$time,A,B,SUM,CARRY);
endmodule
output
time =0 INPUT VALUES: A=0 B =0 output value SUM =0 CARRY =0
time =3 INPUT VALUES: A=0 B =1 output value SUM =1 CARRY =0
time =6 INPUT VALUES: A=1 B =0 output value SUM =1 CARRY =0
time =9 INPUT VALUES: A=1 B =1 output value SUM =0 CARRY =1
always @(*) begin
sum = a^b^cin;
cout = (a&b)+(b&cin)+(cin&a); end
endmodule
TestBench
module tb_full_adder;
reg A,B,CIN; wire SUM,COUT;
full_adder FA (.a(A) ,.b(B),.sum(SUM),.cin(CIN),.cout(COUT));
initialbegin
A =1'b0;
B= 1'b0;
CIN = 1'b0;
#45 $finish; end
always #6 A =~A; always #3 B =~B; always #12 CIN = ~CIN;
always @(SUM,COUT)
$display( "time =%0t \tINPUT VALUES: \t A =%b B =%b CIN =%b \t output value SUM
=%b COUT =%b ",$time,A,B,CIN,SUM,COUT);
endmodule
output
time =0 INPUT VALUES: A =0 B =0 CIN =0 output value SUM =0 COUT =0
time =3 INPUT VALUES: A =0 B =1 CIN =0 output value SUM =1 COUT =0
time =9 INPUT VALUES: A =1 B =1 CIN =0 output value SUM =0 COUT =1
time =12 INPUT VALUES: A =0 B =0 CIN =1 output value SUM =1 COUT =0
time =15 INPUT VALUES: A =0 B =1 CIN =1 output value SUM =0 COUT =1
Ripple Carry Adder(Parameterized and using generate )
Verilog design
`include "full_adder.v"
//Full_added.v contains above defined(Full ADDER) program
//generate statement without using label is verilog-2005 feature. Generate statement is verilog-2001 feature. genvar i; generatefor(i=0;i<N;i=i+1) begin
full_adder FA (.a(a[i]),.b(b[i]),.cin(carry[i]),.sum(sum[i]),.cout(carry[i+1])); end
Time =0 INPUT VALUES A=0000 B=0000 CIN =0 OUTPUT VALUES SUM =0000 COUT =0
Time =4 INPUT VALUES A=0000 B=1101 CIN =1 OUTPUT VALUES SUM =1110 COUT =0
Time =8 INPUT VALUES A=1111 B=0001 CIN =1 OUTPUT VALUES SUM =0001 COUT =1
Time =12 INPUT VALUES A=1101 B=1110 CIN =1 OUTPUT VALUES SUM =1100 COUT =1
Time =16 INPUT VALUES A=0001 B=0010 CIN =1 OUTPUT VALUES SUM =0100 COUT =0
Time =20 INPUT VALUES A=0001 B=0000 CIN =1 OUTPUT VALUES SUM =0010 COUT =0
Time =24 INPUT VALUES A=1110 B=1101 CIN =0 OUTPUT VALUES SUM =1011 COUT =1
Time =28 INPUT VALUES A=0001 B=1111 CIN =0 OUTPUT VALUES SUM =0000 COUT =1
Time =32 INPUT VALUES A=0011 B=0010 CIN =0 OUTPUT VALUES SUM =0101 COUT =0
Time =36 INPUT VALUES A=0000 B=1101 CIN =0 OUTPUT VALUES SUM =1101 COUT =0
Multiplexer(2:1)
Truth Table
Verilog design
module mux21( input a,b,sel, output y);
assign y = sel ?b:a;
endmodule
TestBench
module tb_mux21;
reg A,B,SEL; wire Y;
mux21 MUX (.a(A) ,.b(B),.sel(SEL),.y(Y));
initialbegin
A =1'b0;
B= 1'b0;
SEL =1'b0;
#45 $finish; end
always #6 A =~A; always #3 B =~B; always #5 SEL = ~SEL;
always @(Y)
$display( "time =%0t \tINPUT VALUES: \t A=%b B =%b SEL =%b \t output value Y =%b ",$time,A,B,SEL,Y);
endmodule
output
time =0 INPUT VALUES: A=0 B =0 SEL =0 output value Y =0
time =5 INPUT VALUES: A=0 B =1 SEL =1 output value Y =1
time =6 INPUT VALUES: A=1 B =0 SEL =1 output value Y =0
time =9 INPUT VALUES: A=1 B =1 SEL =1 output value Y =1
always @(*) //It includes all Inputs. You can use this instead of specifying all inputs in //sensivity list.Verilog-2001 Feature begin case ({sel0,sel1})
2'b00 : y = i0;
2'b01 : y = i1;
2'b10 : y = i2;
2'b11 : y = i3; endcase end
always@(*) begin if(!en) //Active low enable
out = 0; elsebegin case ({in})
8'b0000_0001 : out =3'b000;
8'b0000_0010 : out =3'b001;
8'b0000_0100 : out =3'b010;
8'b0000_1000 : out =3'b011;
8'b0001_0000 : out =3'b100;
8'b0010_0000 : out =3'b101;
8'b0100_0000 : out =3'b110;
8'b1000_0000 : out =3'b110; default : out =3'bxxx; endcase end end
endmodule
TestBench using $random and Tasks
module tb_encoder83;
reg en; reg [7:0]in; wire [2:0] out;
encoder83 ENC (.en(en),.in(in),.out(out));
initialbegin
en =0;
in =0; repeat(10)
random_generation(in,en);
#45 $finish; end
task random_generation; output [7:0]in_t; output en_t; begin
#4;
in_t = $random % 8;
en_t =$random; end endtask
task display; input en_t; input [7:0]in_t; input [2:0]out_t;
$display("time =%0t \t INPUT VALUES \t en =%b in =%b \t OUTPUT VALUES out =%b",$time,en_t,in_t,out_t); endtask
always@(out)
display(en,in,out);
endmodule
output
time =0 INPUT VALUES en =0 in =00000000 OUTPUT VALUES out =000
time =4 INPUT VALUES en =1 in =00000100 OUTPUT VALUES out =010
time =8 INPUT VALUES en =1 in =11111001 OUTPUT VALUES out =xxx
time =16 INPUT VALUES en =0 in =11111101 OUTPUT VALUES out =000
time =24 INPUT VALUES en =1 in =00000110 OUTPUT VALUES out =xxx
time =28 INPUT VALUES en =0 in =00000101 OUTPUT VALUES out =000
time =40 INPUT VALUES en =1 in =00000101 OUTPUT VALUES out =xxx
Priority Encoder(8:3)
Priority Encoder overcomes all drawbacks of encoder.
* At a time more than one input can be active, Based on priority output will come.
* "v" is a valid Indicator, it become HIGH only when at least one input is active. You can differentiate the output when enable is zero and when only LSB (in0) is active
always@(*) begin if(!en) begin
out = 2'b00;
v =1'b0; end else begin :block1 for (i=3; i>=0; i= i-1) begin
//Priority Logic. each Time It will check Whether the MSB bit is active, If so it will break //the loop. Otherwise It will decrement and continue the same if (in[i]==1'b1) begin case (i)
3: begin out = 2'b11; v= 1'b1; end
2: begin out = 2'b10; v= 1'b1; end
1: begin out = 2'b01; v= 1'b1; end
0: begin out = 2'b00; v= 1'b1; end default :begin out = 2'bxx; v= 1'bx; end endcase
disable block1;
//Disable statement is synthesizible
$display("time =%0t \t INPUT VALUES \t en =%b in =%b \t OUTPUT VALUES out =%b v =%b",$time,en_t,in_t,out_t,v_t);
endtask
always@(out)
display(en,in,out,v);
endmodule
output
time =0 INPUT VALUES en =0 in =0000 OUTPUT VALUES out =00 v =0
time =8 INPUT VALUES en =1 in =1101 OUTPUT VALUES out =11 v =1
time =12 INPUT VALUES en =1 in =0001 OUTPUT VALUES out =00 v =1
time =24 INPUT VALUES en =1 in =0010 OUTPUT VALUES out =01 v =1
time =28 INPUT VALUES en =0 in =0001 OUTPUT VALUES out =00 v =0
time =44 INPUT VALUES en =1 in =1110 OUTPUT VALUES out =11 v =1
time =48 INPUT VALUES en =0 in =0010 OUTPUT VALUES out =00 v =0
time =60 INPUT VALUES en =1 in =1101 OUTPUT VALUES out =11 v =1
time =64 INPUT VALUES en =0 in =1111 OUTPUT VALUES out =00 v =0
time =72 INPUT VALUES en =1 in =0010 OUTPUT VALUES out =01 v =1
time =76 INPUT VALUES en =1 in =1110 OUTPUT VALUES out =11 v =1
always@(*) begin if(!en)
out = 0; elsebegin case ({in})
3'b000 : out = 8'b0000_0001;
3'b001 : out = 8'b0000_0010;
3'b010 : out = 8'b0000_0100;
3'b011 : out = 8'b0000_1000;
3'b100 : out = 8'b0001_0000;
3'b101 : out = 8'b0010_0000;
3'b110 : out = 8'b0100_0000;
3'b111 : out = 8'b1000_0000; default : out = 8'bxxxx_xxxx; endcase end end
//Below Block is used to generate expected outputs in Test bench only. These outputs //are used to compare with DUT output. You have Checker task (ScoreBoard in SV), for //that you need Reference output
task random_generation; output [2:0]in_t; output en_t; begin
#4;
in_t = $random % 3;
en_t =$random; end endtask
task checker;
//In this block reference value and generated output are compared input [7:0]outd_t; input [7:0]outtb_t; begin if(outd_t === outtb_t)
$display("time =%0t \t DUT VALUE =%b TB VALUE =%b \tDUT and TB VALUES ARE MATCHED ",$time,outd_t,outtb_t); else
$display("time =%0t \tDUT and TB VALUES ARE NOT MATCHED ",$time); end endtask
always@(out_d,out_tb)
checker(out_d,out_tb);
endmodule
TestBench using $random and Tasks
time =0 DUT VALUE =00000000 TB VALUE =00000000 DUT and TB VALUES ARE MATCHED
time =4 DUT VALUE =00000100 TB VALUE =00000100 DUT and TB VALUES ARE MATCHED
time =8 DUT VALUE =00000001 TB VALUE =00000001 DUT and TB VALUES ARE MATCHED
time =16 DUT VALUE =00000000 TB VALUE =00000000 DUT and TB VALUES ARE MATCHED
time =20 DUT VALUE =00000001 TB VALUE =00000001 DUT and TB VALUES ARE MATCHED
time =28 DUT VALUE =00000000 TB VALUE =00000000 DUT and TB VALUES ARE MATCHED
time =40 DUT VALUE =00000001 TB VALUE =00000001 DUT and TB VALUES ARE MATCHED
D-Latch
Verilog design
module d_latch( input en,d, outputreg q);
always@(en,d) begin if(en)
q <= d; end
endmodule
TestBench
module tb_latch; reg en,d; wire q;
d_latch DLATCH (.en(en) ,.d(d) ,.q(q));
initialbegin
en =1'b0;
d =1'b1;
#45 $finish; end
always #6 en =~ en; always #3 d =~d;
always@( q , en )
$display("time =%0t \t INPUT VALUES \t en =%b d =%b \t OUTPUT VALUES q=%b",$time,en,d,q);
endmodule
output
time =0 INPUT VALUES en =0 d =1 OUTPUT VALUES q=x
time =6 INPUT VALUES en =1 d =1 OUTPUT VALUES q=1
time =9 INPUT VALUES en =1 d =0 OUTPUT VALUES q=0
time =12 INPUT VALUES en =0 d =1 OUTPUT VALUES q=0
time =18 INPUT VALUES en =1 d =1 OUTPUT VALUES q=0
time =18 INPUT VALUES en =1 d =1 OUTPUT VALUES q=1
time =21 INPUT VALUES en =1 d =0 OUTPUT VALUES q=0
D-FlipFlop(Asynchronous Reset)
Verilog design
module d_ff ( input clk,d,rst_n, outputreg q);
//Here is reset is Asynchronous, You have include in sensitivity list
always@(posedge clk ,negedge rst_n) begin if(!rst_n)
q <= 1'b0; else
q <= d; end
always @(posedge CLK ,negedge RST_n)
$strobe("time =%0t \t INPUD VALUES \t D =%b RST_n =%b \t OUDPUD VALUES Q =%d",$time,D,RST_n,Q);
//$strobe will execute as a last statement in current simulation.
endmodule
output
time =0 INPUT VALUES D =0 RST_n =0 OUTPUT VALUES Q =0
time =3 INPUT VALUES D =0 RST_n =0 OUTPUT VALUES Q =0
time =9 INPUT VALUES D =1 RST_n =1 OUTPUT VALUES Q =1
time =15 INPUT VALUES D =0 RST_n =1 OUTPUT VALUES Q =0
time =18 INPUT VALUES D =1 RST_n =0 OUTPUT VALUES Q =0
time =21 INPUT VALUES D =1 RST_n =0 OUTPUT VALUES Q =0
time =27 INPUT VALUES D =0 RST_n =1 OUTPUT VALUES Q =0
time =33 INPUT VALUES D =1 RST_n =1 OUTPUT VALUES Q =1
time =39 INPUT VALUES D =0 RST_n =1 OUTPUT VALUES Q =0
D-FlipFlop(Synchronous Reset)
Verilog design
module d_ff ( input clk,d,rst_n, outputreg q);
//In Synchronous Reset, Reset condition is verified wrt to clk.Here It is verified at every //posedge of clk. always@(posedge clk ) begin if (!rst_n)
q <= 1'b0; else
q <= d; end
initial begin
rst_n <= 0;
@(posedge clk);
@(negedge clk);
rst_n <= 1; repeat (10) @(posedge clk);
$finish; end
//Below always block represents the 3-bit counter in behavior style.
//Here it is used to generate reference output always @(posedge clk ornegedge rst_n) begin if (!rst_n)
count <= 0; else
count <= (count + 1); end
always @( q ) scoreboard(count);
//Below task is used to compare reference and generated output. Similar to score board //in SV Test bench
task scoreboard; input [2:0]count; input [2:0] q; begin if (count == q)
$display ("time =%4t q = %3b count = %b match!-:)",
$time, q, count); else
$display ("time =%4t q = %3b count = %b <-- no match",
$time, q, count); end endtask
endmodule
output
time = 0 q = 000 count = 000 match!-:)
time = 15 q = 001 count = 001 match!-:)
time = 25 q = 010 count = 010 match!-:)
time = 35 q = 011 count = 011 match!-:)
time = 45 q = 100 count = 100 match!-:)
time = 55 q = 101 count = 101 match!-:)
time = 65 q = 110 count = 110 match!-:)
time = 75 q = 111 count = 111 match!-:)
time = 85 q = 000 count = 000 match!-:)
time = 95 q = 001 count = 001 match!-:)
17. Gray code counter (3-bit) Using FSM.
It will have following sequence of states. It can be implemented without FSM also.
000
001
011
010
110
111
101
100
FSM Design IN VERILOG
There are many ways of designing FSM.Most efficient are
(i)Using Three always Block (ex: Gray code counter)
(ii)Using Two always block (Ex: divide by 3 counter)
always@(posedge clk, negedge rst_n) begin // FIRST ALWAYS BLOCK
//This always block is used for State assignment. Sequential always block. if(!rst_n)
pr_state <= cnt0; else
pr_state <=nx_state; end
always@(pr_state) begin //SECOND ALWAYS BLOCK
//this always block used for next state logic, Combinational case (pr_state)
cnt0 : nx_state = cnt1;
cnt1 : nx_state = cnt2;
cnt2 : nx_state = cnt3;
cnt3 : nx_state = cnt4;
cnt4 : nx_state = cnt5;
cnt5 : nx_state = cnt6;
cnt6 : nx_state = cnt7;
cnt7 : nx_state = cnt0; default : nx_state = cnt0; endcase end
This is an example for two always block FSM
in this Example you have Two FSMs, one is operating at posedge clk and other //operating at negedge clk. In Double Data Rate (DDR2) also data transfer occur at both //the edges. It is synthesizable
always@(posedge clk ,negedge rst_n) begin if(!rst_n)
pr_state1 <= ST10; else
pr_state1 <= nx_state1; end
always @(pr_state1) begin
//In second always block only we have output logic and next state logic case (pr_state1)
ST10 : begin clk_temp1 = 1'b1; nx_state1 =ST11; end
ST11 : begin clk_temp1 = 1'b0; nx_state1 =ST12; end
ST12 : begin clk_temp1 = 1'b0; nx_state1 =ST10; end default : begin clk_temp1 = 1'bx; nx_state1 =ST10; end endcase end
always@(negedge clk ,posedge rst_n) begin if(!rst_n)
pr_state2 <= ST20; else
pr_state2 <= nx_state2; end
always @(pr_state2) begin case (pr_state2)
ST20 : begin clk_temp2 = 1'b0; nx_state1 =ST21; end
ST21 : begin clk_temp2 = 1'b0; nx_state1 =ST22; end
ST22 : begin clk_temp2 = 1'b1; nx_state1 =ST20; end default : begin clk_temp2 = 1'bx; nx_state1 =ST20; end endcase end