DSD Material
DSD Material
Input(s) Output(s)
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
0 0 d_in[0]
0 1 d_in[1]
1 0 d_in[2]
1 1 d_in[3]
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 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:
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:
Verilog code:
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:
always @ (a)
begin
b=a;
end
always@ (b)
begin
a=b;
end
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
Inputs output
Latch Enable D Qn+1
0 0 0
0 1 1
1 x Qn
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
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:
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