After reading this article, you’d be able to:
- Understand the Full subtractor,
- Explain Dataflow modeling in Verilog HDL,
- Write Verilog HDL code for full subtractor, and
- Simulate the hardware description language code to verify the output.
Contents
Full Subtractor
A full subtractor is a combinational circuit that performs the subtraction of three bits. It consists of three inputs and two outputs.
Consider that we want to subtract three 1-bit numbers. The numbers are X, Y and Z then a difference bit (D) and a borrow bit (B) will get generated.
For example, if the numbers are 1, 1, and 0 then, the difference bit and the borrow bit will be both 0. If we calculate all such combinations of these three bits, then we would end up forming the following kind of a table known as the truth table for full subtractor.
X | Y | Z | B(Borrow) | D (Difference) |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 1 |
0 | 1 | 0 | 1 | 1 |
0 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 0 | 1 |
1 | 0 | 1 | 0 | 0 |
1 | 1 | 0 | 0 | 0 |
1 | 1 | 1 | 1 | 1 |
Now that we have got the truth table, we can form the boolean equations using K-map or simple minimization. We will get that:
- D = (X’Y’Z + X’YZ’ + XY’Z’ + XYZ) = X ⊕ Y ⊕ Z
- B = (X’Y’Z + X’YZ’ + X’YZ + XYZ) = X'(Y ⊕ Z) + YZ
Following the equations, we can design the circuit diagram of the full subtractor as follows.
Verilog Code for Full Subtractor using Dataflow Modeling
First of all, we declare the module. Remember that a module is a basic building block in Verilog. To declare the module, we have a keyword module
then we write the identifier or the name of the module in this way:
module Full_Subtractor_3();
Always remember to put a semicolon at the end of a statement in Verilog. When you declare a module, don’t forget to end the module by writing:
endmodule
We will now write our complete code in this block for full subtractor.
Next, we mention the input and output ports in the port declaration. By checking the input and output from the circuit shown above, we can easily write-
module Full_Subtractor_3(output D, B, input X, Y, Z);
As we are using dataflow modeling, we will use assignment statements to design. Hence, we write:
assign D = X^Y^Z; assign B = ~X & (Y^Z) | Y & Z;
^ stands for xor, & for and, | for or operation. To end module, we write
endmodule
Here is the complete code:
module Full_Subtractor_3(output D, B, input X, Y, Z); assign D = X ^ Y ^ Z; assign B = ~X & (Y^Z) | Y & Z; endmodule
Testbench for Full Subtractor in Verilog
The testbench is a provision to provide inputs to our design and view the corresponding output to test our Verilog source code. The testbench for the full subtractor is written as follows:
First, we include the pre-written file using 'include
and the file name in inverted commas.
`include "Full_Subtractor_3.v"
Now we name the present testbench module as follows:
module Full_Subtractor_3_tb;
module
is the keyword used for declaration and the identifier is Full_Subtractor_3_tb
.
To instantiate a module in another, we write
wire D, B; reg X, Y, Z; Full_Subtractor_3 Instance0 (D, B, X, Y, Z);
Note that the inputs in the circuit here become the reg
datatypes and the outputs are specified as wire
. The reg
data object holds its value from one procedural assignment statement to the next. A continuous assignment statement assigns values to the wire
datatype and makes a connection to an actual wire in the circuit.
Then to instantiate Full_Subtractor_3
we have the identifier Instance0
with D, B, X, Y, Z
as the ports.
Now we will provide the test cases in an initial
block as follows:
initial begin X = 0; Y = 0; Z = 0; #1 X = 0; Y = 0; Z = 1; #1 X = 0; Y = 1; Z = 0; #1 X = 0; Y = 1; Z = 1; #1 X = 1; Y = 0; Z = 0; #1 X = 1; Y = 0; Z = 1; #1 X = 1; Y = 1; Z = 0; #1 X = 1; Y = 1; Z = 1; end
#1
gives a delay of one unit of time in between the test cases. begin
is used to start and end
concludes any block in Verilog. Now we observe and check the obtained output using $monitor
. Write initial begin
to start a block and end
at last.
initial begin $monitor ("%t, X = %d| Y = %d| Z = %d| B = %d| D = %d", $time, X, Y, Z, B, D); $dumpfile("dump.vcd"); $dumpvars(); end
Inside monitor, we mention the arguments that we want to view on the console. %t
is the format specifier for time, %b
is for binary, %d
for decimal.
The port names after inverted commas are given in the same order as required while assigning values. The $dumpvars
is used to specify which variables are to be dumped in the file mentioned by $dumpfile
.
Here is the complete testbench for a full subtractor.
`include "Full_Subtractor_3.v" module Full_Subtractor_3_tb; wire D, B; reg X, Y, Z; Full_Subtractor_3 Instance0 (D, B, X, Y, Z); initial begin X = 0; Y = 0; Z = 0; #1 X = 0; Y = 0; Z = 1; #1 X = 0; Y = 1; Z = 0; #1 X = 0; Y = 1; Z = 1; #1 X = 1; Y = 0; Z = 0; #1 X = 1; Y = 0; Z = 1; #1 X = 1; Y = 1; Z = 0; #1 X = 1; Y = 1; Z = 1; end initial begin $monitor ("%t, X = %d| Y = %d| Z = %d| B = %d| D = %d", $time, X, Y, Z, B, D); $dumpfile("dump.vcd"); $dumpvars(); end endmodule
Hardware Schematic
Here is the schematic, as viewed in Xilinx Vivado.