0% found this document useful (0 votes)
15 views30 pages

DSD Material

The document provides a comprehensive overview of various digital logic components including binary comparators, code converters (binary to gray and gray to binary), multiplexers (2:1 and 4:1), decoders (2:4 and 4:16), and encoders (4:2 and priority encoder). Each section includes truth tables and corresponding Verilog code implementations for the components. The document serves as a reference for designing and understanding basic digital circuits.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views30 pages

DSD Material

The document provides a comprehensive overview of various digital logic components including binary comparators, code converters (binary to gray and gray to binary), multiplexers (2:1 and 4:1), decoders (2:4 and 4:16), and encoders (4:2 and priority encoder). Each section includes truth tables and corresponding Verilog code implementations for the components. The document serves as a reference for designing and understanding basic digital circuits.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

BINARY COMPARATOR:

Table-1: Truth table of binary comparator

Input(s) Output(s)

a_in b_in a_gt_b a_eq_b a_lt_b

0 0 0 1 0

0 1 0 0 1

1 0 1 0 0

1 1 0 1 0

VERILOG CODE:

module binary_comparator(input [3:0] a_in, b_in, output reg a_gt_b, a_eq_b, a_lt_b);
always@*
begin
if(a_in == b_in)
begin
a_gt_b = 0;
a_eq_b = 1;
a_lt_b = 0;
end
elseif(a_in > b_in)
begin
a_gt_b = 0;
a_eq_b = 1;
a_lt_b = 0;
end
else
begin
a_gt_b = 0;
a_eq_b = 0;
a_lt_b = 1;
end
end
endmodule
CODE CONVERTERS:
1. Binary - Gray code converter:

Input(s) Output(s)
[3:0] binary_in [3:0] gray_out
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 1
0 0 1 0 0 0 1 1
0 0 1 1 0 0 1 0
0 1 0 0 0 1 1 0
0 1 0 1 0 1 1 1
0 1 1 0 0 1 0 1
0 1 1 1 0 1 0 0
1 0 0 0 1 1 0 0
1 0 0 1 1 1 0 1
1 0 1 0 1 1 1 1
1 0 1 1 1 1 1 0
1 1 0 0 1 0 1 0
1 1 0 1 1 0 1 1
1 1 1 0 1 0 0 1
1 1 1 1 1 0 0 0

VERILOG CODE:
module binary_gray(input [3:0] binary_in, output [3:0] gray_out );
assign gray_out[3] = binary_in[3];
assign gray_out[2] = binary_in[3] ^ binary_in[2];
assign gray_out[1] = binary_in[2] ^ binary_in[1];
assign gray_out[0] = binary_in[1] ^ binary_in[0];
endmodule
1. Gray - Binary code converter:

Input(s) Output(s)
[3:0] gray_in [3:0] binary_out
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 1
0 0 1 0 0 0 1 1
0 0 1 1 0 0 1 0
0 1 0 0 0 1 1 1
0 1 0 1 0 1 1 0
0 1 1 0 0 1 0 0
0 1 1 1 0 1 0 1
1 0 0 0 1 1 1 1
1 0 0 1 1 1 1 0
1 0 1 0 1 1 0 0
1 0 1 1 1 1 0 1
1 1 0 0 1 0 0 0
1 1 0 1 1 0 0 1
1 1 1 0 1 0 1 1
1 1 1 1 1 0 1 0

VERILOG CODE:
module gray_binary(input [3:0] gray_in, output [3:0] binary_out );
assign binary_out[3] = gray_in[3];
assign binary_out[2] = gray_in[3] ^ gray_in[2]; //b[2] = b[3] ^ g[2]
assign binary_out[1] = gray_in[3] ^ gray_in[2]^ gray_in[1]; //b[1] = b[2] ^ g[1]
assign binary_out[0] = gray_in[3] ^ gray_in[2]^ gray_in[1]^ gray_in[0];
// b[0] = b[1] ^ g[0]
endmodule
MULTIPLEXER:

1. 2:1 MUX

sel_in y_out
0 a_in
1 b_in

VERILOG CODE-1 (Using assign statements)

module mux_2_1( input a_in, b_in, output y_out);


assign y_out = (sel_in) ? b_in : a_in ;
endmodule

VERILOG CODE-2 (Using always statement)

module mux_2_1(input a_in, b_in, output reg y_out);


always@*
begin
if (sel_in)
y_out = b_in;
else
y_out = a_in;
end
endmodule

VERILOG CODE-3 (Using CASE statement)

module mux_2_1(input a_in, b_in, output reg y_out);


always@*
begin
case(sel_in)
1'b0: y_out = a_in;
1'b1: y_out = b_in;
endcase
end
endmodule
2. 4:1 MUX

selection input(s) Output

sel_in[1] sel_in[0] y_out

0 0 d_in[0]

0 1 d_in[1]

1 0 d_in[2]

1 1 d_in[3]

VERILOG CODE-1 (Using if-else)

module mux_4_1(input [3:0] d_in, [1:0] sel_in, output reg y_out);


always@*
begin
if (sel_in == 2'b00)
y_out = d_in[0];
elseif (sel_in == 2'b01)
y_out = d_in[1];
elseif (sel_in ==2'b10)
y_out = d_in[2];
else
y_out = d_in[3];
end
endmodule

VERILOG CODE-2 (Using CASE)

module mux_4_1(input [3:0] d_in, [1:0] sel_in, output reg y_out);


always@*
begin
case (sel_in)
2'b00: y_out = d_in[0];
2'b01: y_out = d_in[1];
2'b10: y_out = d_in[2];
2'b11: y_out = d_in[3];
endcase
end
endmodule
VERILOG CODE-2 (Using 2:1 MUX )

module mux_4_1(input [3:0] d_in, [1:0] sel_in, output y_out);


reg y1,y2;
always@*
begin
case (sel_in[0])
1'b0:
begin
y1 = d_in[0];
y2 = d_in[2];
end
1'b1:
begin
y1 = d_in[1];
y2 = d_in[3];
end
endcase
end
assign y_out = (sel_in[1]) ? y2: y1;
endmodule
DECODERS
1. 2:4 decoder with enable (Active High Enable)

input(s) output(s)
enable_in d_in[1] d_in[0] y_out[3] y_out[2] y_out[1] y_out[0]
1 0 0 0 0 0 1
1 0 1 0 0 1 0
1 1 0 0 1 0 0
1 1 1 1 0 0 0
0 x x 0 0 0 0

VERILOG CODE

module decoder_2_4 ( input enable_in, [1:0] d_in, output reg [3:0] y_out);
always@*
begin
if (enable_in)
case (d_in)
2'b00: y_out = 4'b0001;
2'b01: y_out = 4'b0010;
2'b10: y_out = 4'b0100;
2'b11: y_out = 4'b1000;
endcase
else
y_out = 4'b0000;
end
endmodule
1. 2:4 decoder with enable (Active Low Enable)

input(s) output(s)
enable_in d_in[1] d_in[0] y_out[3] y_out[2] y_out[1] y_out[0]
0 0 0 1 1 1 0
0 0 1 1 1 0 1
0 1 0 1 0 1 1
0 1 1 0 1 1 1
1 x x 1 1 1 1

VERILOG CODE

module decoder_2_4 ( input enable_in, [1:0] d_in, output reg [3:0] y_out);
always@ (enable_in, d_in)
begin
if (~enable_in)
case (d_in)
2'b00: y_out = 4'b1110;
2'b01: y_out = 4'b1101;
2'b10: y_out = 4'b1011;
2'b11: y_out = 4'b0111;
endcase
else
y_out = 4'b1111;
end
endmodule
Verilog Code (Using continuous assignments)

module 2_4_decoder ( input enable_in, [1:0] d_in, output [3:0] y_out);


assign y_out[0] = enable_in & (~ d_in[1]) & (~ d_in[0]) ;
assign y_out[1] = enable_in & (~ d_in[1]) & ( d_in[0]) ;
assign y_out[2] = enable_in & ( d_in[1]) & (~ d_in[0]) ;
assign y_out[3] = enable_in & (d_in[1]) & (d_in[0]) ;
endmodule

Verilog Code (Using Shift operators )

module decoder_2_4 ( input enable_in, [1:0] d_in, output reg [3:0] y_out);
always @ *
begin
if (~ enable_in)
y_out = 4'b0000;
else
y_out = (4'b0001 << d_in);
end
endmodule
2. 4 to 16 decoder using 2 to 4 decoders:

VERILOG CODE:

module decoder_4_16 (input enable_in, [3:0] d_in, output [15:0] y_out);


reg [3:0] tmp_enable;

always@*
begin
if(~enable_in)
tmp_enable = 4'b0000;
else
tmp_enable = 4'b0001 << d_in [3:2];
end
always@*
begin
if(~tmp_enable[0])
y_out[3:0] = 4'b0000;
else
y_out[3:0] = (4'b0001<<d_in[1:0]);
end

always@*
begin
if(~tmp_enable[1])
y_out[7:4] = 4'b0000;
else
y_out[7:4] = (4'b0001<<d_in[1:0]);
end

always@*
begin
if(~tmp_enable[2])
y_out[11:8] = 4'b0000;
else
y_out[11:8] = (4'b0001<<d_in[1:0]);
end
always@*
begin
if(~tmp_enable[3])
y_out[15:12] = 4'b0000;
else
y_out[15:12] = (4'b0001<<d_in[1:0]);
end
endmodule
ENCODERS:

1. 4:2 Encoder

Input(s) Output(s)
d_in[3] d_in[2] d_in[1] d_in[0] y_out[1] y_out[0] invalid_data
1 0 0 0 1 1 0
0 1 0 0 1 0 0
0 0 1 0 0 1 0
0 0 0 1 0 0 0
0 0 0 0 0 0 1

VERILOG CODE

module encoder_4_2 ( input [3:0] d_in, output reg [1:0] y_out, output reg invalid_data);
always@*
begin
case(d_in)
4'b0001: {invalid_data, y_out} = 3'b000;
4'b0010: {invalid_data, y_out} = 3'b001;
4'b0100: {invalid_data, y_out} = 3'b010;
4'b1000: {invalid_data, y_out} = 3'b011;
default : {invalid_data, y_out} = 3'b100;
endcase
end
endmodule
2. 4_2_PRIORITY ENCODER:

Input(s) Output(s)
d_in[3] d_in[2] d_in[1] d_in[0] y_out[1] y_out[0] invalid_data
1 X X X 1 1 0
0 1 X X 1 0 0
0 0 1 X 0 1 0
0 0 0 1 0 0 0
0 0 0 0 0 0 1

VERILOG CODE

module priority_encoder_4_2(input [3:0] d_in, output reg [1:0] y_out, output reg
invalid_data);
always@*
begin
if (d_in[0])
{invalid_data, y_out} = 3'b000;
elseif (d_in[1])
{invalid_data, y_out} = 3'b001;
elseif (d_in[2])
{invalid_data, y_out} = 3'b010;
elseif (d_in[3])
{invalid_data, y_out} = 3'b011;
else
{invalid_data, y_out} = 3'b100;
end
endmodule
Unintentional Latch formation:

Example_1: Design of AND gate using always construct.

Verilog code:

module and_logic_design (input a_in, b_in, output reg y_out );


always@*
begin
if (a_in == 1 && b_in==1)
y_out=1;
end
endmodule
Unintentional Latch formation:

Example 2:

always @ (c_in)
begin
if (c_in ==1)
begin
a_in = 1'b1;
b_in = 1'b1;
end
else
begin
a_in =1'b0;
end
end
Unintentional Latch formation:

Example 3:

module decoder_2to4( input [1:0] sel_in, input enable_in, output reg [3:0] y_out);
always @*
begin
if(enable_in)
case(sel_in)
2'b00: y_out = 4'b0001;
2'b01:y_out = 4'b0010;
2'b10: y_out = 4'b0100;
endcase
else
y_out = 4'b0000;
end
endmodule

Example 4:

module mux_4to1(output reg y_out, input [3:0] d_in, input [1:0] s_in);
always@*
begin
if(s_in == 2'b00)
y_out = d_in[0];
else if(s_in==2'b01)
y_out = d_in[1];
else if(s_in==2'b10)
y_out=d_in[2];
else if (s_in==2'b11)
y_out = d_in[3];
end
endmodule
COMBINATIONAL LOOPS:

Example-1:

module loop_combinational (input a_in, b_in, output reg y_out);


always @ *
begin
y_out = a_in & b_in & y_out;
end
endmodule
Example 2:

always @ (a)
begin
b=a;
end
always@ (b)
begin
a=b;
end

How to avoid combinational loop - Use non-blocking assignments


always @ (posedge clk)
begin
b<=a;
end
always@ (posedge clk)
begin
a<=b;
end
MULTIPLE DRIVER ASSIGNMENT ERROR:

Example:

wire y_tmp;
assign y_tmp = a_in ^ b_in ;
assign y_tmp = a_in & b_in ;
POSITIVE LEVEL SENSITIVE D-LATCH

Inputs output
Latch Enable D Qn+1
1 0 0
1 1 1
0 x Qn

module latch (input D, input LE, output reg Q);


always @*
begin
if (LE)
Q <=D;
end
endmodule
NEGATIVE LEVEL SENSITIVE D-LATCH

Inputs output
Latch Enable D Qn+1
0 0 0
0 1 1
1 x Qn

module latch (input D, input LE, output reg Q);


always @*
begin
if (~LE)
Q <=D;
end
endmodule
D-Flip flop with asynchronous active low reset input

module d_flip_flop (input d_in, input clk, input reset, output reg q_out);
always @(posedge clk, negedge reset)
begin
if(~reset)
q_out<=1'b0;
else
q_out<=d_in;
end
endmodule
D-Flip flop with synchronous reset input

module d_flip_flop (input d_in, input clk, input reset, output reg q_out);
always @(posedge clk)
begin
if(~reset)
q_out<=1'b0;
else
q_out<=d_in;
end
endmodule
VERILOG CODE - GATED D LATCH

module D_latch (D, Clk, Q);


input D, Clk;
output reg Q;
always @(D, Clk)
if(Clk)
Q=D;
endmodule

VERILOG CODE - D FLIP FLOP


module flip_flop (D, Clk, Q);
input D, Clk;
output reg Q;
always @(posedge Clk)
Q=D;
endmodule
module example (D, Clock, Q1, Q2);
input D, Clock;
output reg Q1, Q2;
always @(posedge Clock)
begin
Q1 = D;
Q2 = Q1;
end
endmodule
module example (D, Clock, Q1, Q2);
input D, Clock;
output reg Q1, Q2;
always @(posedge Clock)
begin
Q1 < = D;
Q2 < = Q1;
end
endmodule
module example (x1, x2, x3, Clock, f, g);
input x1, x2, x3, Clock;
output reg f, g;
always @(posedge Clock)
begin
f = x1 & x2;
g = f | x3;
end
endmodule
module example (x1, x2, x3, Clock, f, g);
input x1, x2, x3, Clock;
output reg f, g;
always @(posedge Clock)
begin
f < = x1 & x2;
g < = f | x3;
end
endmodule
Non-Blocking Assignments for Combinational Circuits

A natural question at this point is whether non-blocking assignments can be used for combi
national circuits. The answer is that they can be used in most situations, but when subsequent
assignments in an always block depend on the results of previous assignments, the non-blocking
assignments can generate nonsensical circuits. As an example, assume that we have a three-bit
vector A = a2a1a0, and we wish to generate a combinational function f that is equal to 1 when
there are two adjacent bits in A that have the value 1. One way to specify this function with
blocking assignments is
always @(A)
begin
f = A[1] & A[0];
f = f | (A[2] & A[1]);
end

These statements produce the desired logic function, which is f = a1a0 + a2a1. Consider
now changing the code to use the non-blocking assignments
f <= A[1] & A[0];
f <= f | (A[2] & A[1]);
There are two key aspects of the Verilog semantics relevant to this code:
1. The results of non-blocking assignments are visible only after all of the statements in
the always block have been evaluated.
2. When there are multiple assignments to the same variable inside an always block, the
result of the last assignment is maintained.
In this example, f has an unspecified initial value when we enter the always block. The first
statement assigns f = a1a0, but this result is not visible to the second statement. It still sees the
original unspecified value of f . The second assignment overrides (deletes!) the first assignment
and produces the logic function f = f + a2a1. This expression does not correspond to a
combinational circuit, because it represents an AND-OR circuit in which the OR-gate is fed back
to itself. It is best to use blocking assignments when describing combinational circuits, so as to
avoid accidentally creating a sequential circuit.
Guidelines in usage of Blocking & Non-Blocking Assignments:

Guideline #1: When modeling sequential logic, use nonblocking assignments.


Guideline #2: When modeling latches, use nonblocking assignments.
Guideline #3: When modeling combinational logic with an always block, use blocking
assignments.
Guideline #4: When modeling both sequential and combinational logic within the same always
block, use nonblocking assignments.
Guideline #5: Do not mix blocking and nonblocking assignments in the same always block.
Guideline #6: Do not make assignments to the same variable from more than one always block.
Guideline #7: Use $strobe to display values that have been assigned using nonblocking
assignments.
Guideline #8: Do not make assignments using #0 delays.
Following the above guidelines will accurately model synthesizable hardware while eliminating
90-100% of the most common Verilog simulation race conditions.

List of Reference(s):

1. Digital Logic Design using Verilog, Coding and RTL Synthesis - Vaibbhav Taraate
2. Digital Logic Design using Verilog HDL, Stephen Brown and Zvonko Vranesic
3. Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill! by Clifford E
Cummings

You might also like