View Course Path

Verilog Code for Full Subtractor using Dataflow Modeling

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.

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.

Logic diagram of full subtractor
Logic diagram of full subtractor

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.

schematic of a full adder RTL

Simulation of the Verilog code for the Full-subtractor using dataflow modelling

output waveform of full subtractor

Thanks for reading! If you have any queries, let us know in the comments section below!

One thought on “Verilog Code for Full Subtractor using Dataflow Modeling

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.