Adders in Verilog
The full adder is a digital circuit that performs the addition of three numbers. It is implemented using logic gates. A one-bit full adder adds three one-bit binary numbers (two input bits, mostly A and B, and one carry bit Cin being carried forward from previous addition) and outputs a sum and a carry bit.
A full adder can also be formed by using two half-adders and ORing their final outputs. A half adder adds two binary numbers. Since full adder is a combinational circuit, therefore it can be modelled in Verilog language.
Now, Verilog code for a full adder circuit with the behavioural style of modelling first demands the concept and working of a full adder.
A B and Cin are the input variables for two-bit binary numbers and carry input and S and Cout are the output variables for Sum and Carry.There are many different ways we can proceed with Verilog coding for full adder: here we three ways in behavioural style
- Using an always statement
- Case statements
- If-else statements
Verilog code for full adder – Using always statement
Procedural statements inside this always block gets executed once there’s any change in event A, B OR Cin. Then comes the logical expression which will be assigned to the output registers S and Cout. Remember that the left-hand side entities must always be a reg (register) since registers are data storing elements.
So the final code is:
`timescale 1ns / 1ps module full_adder( A, B, Cin, S, Cout); input wire A, B, Cin; output reg S, Cout; always @(A or B or Cin) begin S = A ^ B ^ Cin; Cout = A&B | (A^B) & Cin; end endmodule
Verilog code for full adder – Using case statement
case statement in Verilog is much similar to switch- case statement in C language.`timescale 1ns / 1ps module
full_adder(input wire A, B, Cin, output reg S, output reg Cout);
always @(A or B or Cin)
begin
case (A | B | Cin)
3'b000: begin S = 0; Cout = 0; end
3'b001: begin S = 1; Cout = 0; end
3'b010: begin S = 1; Cout = 0; end
3'b011: begin S = 0; Cout = 1; end
3'b100: begin S = 1; Cout = 0; end
3'b101: begin S = 0; Cout = 1; end
3'b110: begin S = 0; Cout = 1; end
3'b111: begin S = 1; Cout = 1; end
endcase
end
endmoduleVerilog code for full adder – Using if-else statement
`timescale 1ns / 1ps module full_adder( A, B, Cin, S, Cout); input wire A, B, Cin; output reg S, Cout; always @(A or B or Cin) begin if(A==0 && B==0 && Cin==0) begin S=0; Cout=0; end else if(A==0 && B==0 && Cin==1) begin S=1; Cout=0; end else if(A==0 && B==1 && Cin==0) begin S=1; Cout=0; end else if(A==0 && B==1 && Cin==1) begin S=0; Cout=1; end else if(A==1 && B==0 && Cin==0) begin S=1; Cout=0; end else if(A==1 && B==0 && Cin==1) begin S=0; Cout=1; end else if(A==1 && B==1 && Cin==0) begin S=0; Cout=1; end else if(A==1 && B==1 && Cin==1) begin S=1; Cout=1; end end endmodule
Testbench for full adder in Verilog
//timescale directive
`timescale 1ns / 1ps
module top;
//declare testbench variables
reg A_input, B_input, C_input;
wire Sum, C_output;
//instantiate the design module and connect to the testbench variables
full_adder instantiation(.A(A_input), .B(B_input), .Cin(C_input), .S(Sum), .Cout(C_output));
initial
begin
$dumpfile("xyz.vcd");
$dumpvars;
//set stimulus to test the code
A_input=0;
B_input=0;
C_input=0;
#100 $finish;
end
//provide the toggling input (just like truth table input)
//this acts as the clock input
always #40 A_input=~A_input;
always #20 B_input=~B_input;
always #10 C_input=~C_input;
//display output if there’s a change in the input event
always @(A_input or B_input or C_input)
$monitor("At TIME(in ns)=%t, A=%d B=%d C=%d Sum = %d Carry = %d", $time, A_input, B_input, C_input, Sum, C_output);
endmoduleFor writing the testbench:
- We’ll first add the timescale directive. It starts with a grave accent
`and does not end with a semicolon. Timescale directive is used for specifying the unit of time used in further modules and the time resolution (here one picosecond). The time resolution is the precision factor that determines the degree of accuracy of the time unit in the modules.
`timescale 1ns / 1ps
Next is the module and variable declaration.
- The register (
reg) type holds the value until a next value is being driven by the clock pulse onto it and is always underinitialoralwaysblock. It is used to apply a stimulus to the input. HenceA_inputB_inputandC_inputare declared as registers. - Wires(
wire) are declared for the variables which are passive in nature. Their values don’t change, and they can’t be assigned insidealwaysandinitialblock. Hence sumSumand carryC_Outputvariables are declared as wires.
module top; reg A_input, B_input, C_input; wire Sum, C_output;
Then comes the module instantiation.
- The test bench applies stimulus to the Device Under Test DUT. To do this, the DUT must be instantiated under the testbench. The syntax for instantiation is given below. Port mapping is the linking of testbench’s modules with that of the design modules.
name_of_module name_of_instance(port_map)
- Now we’ll give an initial stimulus to the input variables. This is done under the
initialblock. - We can also stop the simulation in a pre-mentioned delay time using
$finish.
initial begin A_input=0; B_input=0; C_input=0; #100 $finish; end
The additional thing over here is the use of two system tasks:
$dumpfileis used to dump the changes in the values of net and registers in a VCD file (value change dump file).$dumpvarsis used to specify which variables should be dumped in the file name specified by argument in the filename.
initial begin A_input=0; B_input=0; C_input=0; #100 $finish; end
- Now, it depends on the user whether he wants to display the simulation result on the TCL console or not. I have used
$monitorwhich displays the value of the signal whenever its value changes. - It is executed inside
alwaysblock, and the sensitivity list remains the same as explained in the above section. - The format specifier
%tgives us the current simulation time and%dis used to display the value of the variable in decimal.
always @(A_input or B_input or C_input)
$monitor("At TIME(in ns)=%t, A=%d B=%d C=%d Sum = %d Carry = %d", $time, A_input, B_input, C_input, Sum, C_output);
No comments:
Post a Comment