Difference between revisions of "Xilinx ISE Four-Bit Adder in Verilog"

From dftwiki3
Jump to: navigation, search
(A 4-Bit Adder)
(Test Module)
 
(13 intermediate revisions by the same user not shown)
Line 17: Line 17:
 
==New Project==
 
==New Project==
 
* The first task is start the Xilinx ISE and '''create a New Project'''.  Let's call it ''FourBitAdder''.
 
* The first task is start the Xilinx ISE and '''create a New Project'''.  Let's call it ''FourBitAdder''.
* Once the Project is created, add a '''New Source''', of type '''Verilog Module'''.  Call it ''MultiStages''.  It will contain 2 modules.  The first one will be the 3-bit full adder.
+
* Once the Project is created, add a '''New Source''', of type '''Verilog Module'''.  Call it ''SingleStage''.  It will contain the full-adder for 2 bits.
 
* Define the ports as follows:
 
* Define the ports as follows:
 
** a, ''input''
 
** a, ''input''
Line 25: Line 25:
 
** cout, ''output''
 
** cout, ''output''
  
We now have several options to define the adder.  One is ''functional'', as illustrated in the next subsection.  Next is a ''logical'' description, where we express the outputs in terms of their logical equation.  The final is a ''gate level'' description.  Pick the one that seem most interesting to you.  They should all yield the same result in the next section, where we test them.
+
We now have several options to define this adder.  One is ''functional'', as illustrated in the next subsection.  Next is a ''logical'' description, where we express the outputs in terms of their logical equation.  The final is a ''gate level'' description.  Pick the one that seem most interesting to you.  They should all yield the same result in the next section, where we test them.
  
 
==Functional Description of Full Adder==
 
==Functional Description of Full Adder==
Line 32: Line 32:
 
`timescale 1ns / 1ps
 
`timescale 1ns / 1ps
 
//////////////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////////////////////////////
// MultiStages.v
+
// SingleStage.v
 
//
 
//
 
//////////////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////////////////////////////
Line 46: Line 46:
 
endmodule
 
endmodule
  
module MultiStages(
 
    input [3:0] a,
 
    input [3:0] b,
 
    output [3:0] sum,
 
    output carry
 
    );
 
 
endmodule
 
  
 
</source>
 
</source>
Line 63: Line 55:
 
`timescale 1ns / 1ps
 
`timescale 1ns / 1ps
 
//////////////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////////////////////////////
// MultiStages.v
+
// SingleStage.v
 
//
 
//
 
//////////////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////////////////////////////
Line 78: Line 70:
 
endmodule
 
endmodule
  
module MultiStages(
 
    input [3:0] a,
 
    input [3:0] b,
 
    output [3:0] sum,
 
    output carry
 
    );
 
 
endmodule
 
  
 
</source>
 
</source>
Line 95: Line 79:
 
`timescale 1ns / 1ps
 
`timescale 1ns / 1ps
 
//////////////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////////////////////////////
// MultiStages.v
+
// SingleStage.v
 
//
 
//
 
//////////////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////////////////////////////
Line 118: Line 102:
  
 
endmodule
 
endmodule
 
 
module MultiStages(
 
    input [3:0] a,
 
    input [3:0] b,
 
    output [3:0] sum,
 
    output carry
 
    );
 
 
endmodule
 
 
  
 
</source>
 
</source>
Line 146: Line 119:
 
* Add a '''New Source''' to the project, of type '''Verilog Test Fixture'''.   
 
* Add a '''New Source''' to the project, of type '''Verilog Test Fixture'''.   
 
* Call it '''test'''.
 
* Call it '''test'''.
* Specify '''singleStage''' as the target of the testing (be careful there will be two targets as you have two modules in your main file).
+
* Specify '''SingleStage''' as the target of the testing.
 
* Edit the '''test.v''' file  as illustrated below:
 
* Edit the '''test.v''' file  as illustrated below:
 
<br />
 
<br />
Line 173: Line 146:
 
 
 
// Instantiate the Unit Under Test (UUT)
 
// Instantiate the Unit Under Test (UUT)
singleStage uut (
+
SingleStage uut (
 
.a(a),  
 
.a(a),  
 
.b(b),  
 
.b(b),  
Line 280: Line 253:
 
=A 4-Bit Adder=
 
=A 4-Bit Adder=
  
We will now flesh out the main module of our '''MultiStages.v''' Verilog file to create a full 4-bit adder.
+
We will now create a '''new Verilog module''' called  ''MultiStages.v'' to create a full 4-bit adder.
  
 
The idea is simple.  We want to add a 4-bit word to another 4-bit word and get a 4-bit sum, and a carry out.
 
The idea is simple.  We want to add a 4-bit word to another 4-bit word and get a 4-bit sum, and a carry out.
Line 287: Line 260:
  
 
<br />
 
<br />
All we need to do is write Verilog code that will replicate the previous full-adder 4 times, and let the carry ''ripple'' from one stage to the next.
+
==New Verilog Module==
 +
All we need to do is write Verilog code that will replicate the full-adder encapsulated in '''SingleStage''' 4 times, and let the carry ''ripple'' from one stage to the next.
  
* Go back to editing '''MultiStages.v'''  
+
* Create a '''New Source''' of type ''Verilog Module'' and call it ''MultiStage''
* Flesh out the empty module so that it looks like this:
+
* Its ports should be defined as follows:
  
 +
<br /><center>[[Image:XilinxVerilog4BitAdderPorts.png|500px]]</center>
 +
<br />
 +
*Edit the code of the new module and replicate the code showed below:
 
<br />
 
<br />
<source lang="verilog" highlight="8-14">
+
<source lang="verilog" highlight="7-13">
  
 
module MultiStages(
 
module MultiStages(
Line 304: Line 281:
 
 
 
assign cin = 1'b0;
 
assign cin = 1'b0;
singleStage s0( .a( a[0] ), .b( b[0]), .cin( cin ), .s( sum[0]), .cout( ripple0 ) );
+
SingleStage s0( .a( a[0] ), .b( b[0]), .cin( cin ), .s( sum[0]), .cout( ripple0 ) );
singleStage s1( .a( a[1] ), .b( b[1]), .cin( ripple0 ), .s( sum[1]), .cout( ripple1 ) );
+
SingleStage s1( .a( a[1] ), .b( b[1]), .cin( ripple0 ), .s( sum[1]), .cout( ripple1 ) );
singleStage s2( .a( a[2] ), .b( b[2]), .cin( ripple1 ), .s( sum[2]), .cout( ripple2 ) );
+
SingleStage s2( .a( a[2] ), .b( b[2]), .cin( ripple1 ), .s( sum[2]), .cout( ripple2 ) );
singleStage s3( .a( a[3] ), .b( b[3]), .cin( ripple2 ), .s( sum[3]), .cout( carry ) );
+
SingleStage s3( .a( a[3] ), .b( b[3]), .cin( ripple2 ), .s( sum[3]), .cout( carry ) );
  
 
endmodule
 
endmodule
Line 313: Line 290:
 
</source>
 
</source>
 
<br />
 
<br />
 +
* Check the syntax of your module and fix any bugs you discover!
 +
 +
===Explanations===
 +
; '''wire cin'''<br />'''assign cin = 1'b0'''
 +
: The first stage of the adder, the one adding the Least Significant bits should have a 0 coming in on its ''carry-in'' input.  This is done by creating this wire, which we set equal to 0 all the time in the next statement.  The '''1'b0''' notation means '''1 bit''', with '''b'''inary value '''0'''.
 +
 +
;SingleStage( ...  '''.cout( ripple1 )...)'''<br />SingleStage( ... '''.cin( ripple1 ) ...)
 +
: The '''carry-out''' of one stage is directly connected to the '''carry-in''' of the next stage.  We need a wire for this purpose.  We could have defined '''ripple1''' as a wire, but Verilog allows one to not declare wires that are ''internal'' to the circuit, connecting one block to another.
 +
 +
==Test Module==
 +
 +
* Add a '''New Source''' file of type ''Verilog Test Fixture'' and call it '''test4'''.
 +
* Attach it to '''MultiStages'''
 +
* Edit the module as shown below:
 +
 +
<br />
 +
<source lang="Verilog">
 +
 +
`timescale 1ns / 1ps
 +
 +
////////////////////////////////////////////////////////////////////////////////
 +
//
 +
// Verilog Test Fixture created by ISE for module: MultiStages
 +
////////////////////////////////////////////////////////////////////////////////
 +
 +
module test4;
 +
 +
// Inputs
 +
reg [3:0] a;
 +
reg [3:0] b;
 +
 +
// Outputs
 +
wire [3:0] sum;
 +
wire carry;
 +
 +
// vars
 +
integer i;
 +
 +
// Instantiate the Unit Under Test (UUT)
 +
MultiStages uut (
 +
.a(a),
 +
.b(b),
 +
.sum(sum),
 +
.carry(carry)
 +
);
 +
 +
initial begin
 +
// Initialize Inputs
 +
a = 0;
 +
b = 0;
 +
end
 +
 +
initial
 +
$monitor( "a(%b) + b(%b)  = carry sum(%b %b)", a, b, carry, sum );
 +
 +
 +
always @(a or b)
 +
begin
 +
for ( i=0; i< 16 * 16; i = i + 1 )
 +
#1 {a, b} = i;
 +
 +
#10 $stop;
 +
end
 +
     
 +
endmodule
 +
</source>
 +
<br />
 +
You should be able to recognize the main features of the test module by now.  The one that might be surprising is the '''for loop'''.  The '''16 * 16''' terms simply means that we want to test all the combinations of a added to b.  Since a and b are 4 bits, each can be one of 16 possible configurations, hence 16 * 16.
 +
 +
* Check the '''Behavioral Syntax''' of your module and fix bugs if necessary.
 +
* RUn the '''Behavioral Simulation Module'''
 +
* Verify that you get an output similar to the one illustrated below.
 +
 +
<br />
 +
<center>[[Image:Xilinx4BitAdderTimingDiagram.png|700px]]<br /><br /></center>
 +
<br />
 +
<code><pre>
 +
 +
ISim O.87xd (signature 0x2f00eba5)
 +
WARNING: A WEBPACK license was found.
 +
WARNING: Please use Xilinx License Configuration Manager to check out a full ISim license.
 +
WARNING: ISim will run in Lite mode. Please [...] Full version.
 +
This is a Lite version of ISim.
 +
Time resolution is 1 ps
 +
Simulator is doing circuit initialization process.
 +
Finished circuit initialization process.
 +
a(0000) + b(0000)  = carry sum(0 0000)
 +
a(0000) + b(0001)  = carry sum(0 0001)
 +
a(0000) + b(0010)  = carry sum(0 0010)
 +
a(0000) + b(0011)  = carry sum(0 0011)
 +
a(0000) + b(0100)  = carry sum(0 0100)
 +
a(0000) + b(0101)  = carry sum(0 0101)
 +
a(0000) + b(0110)  = carry sum(0 0110)
 +
a(0000) + b(0111)  = carry sum(0 0111)
 +
a(0000) + b(1000)  = carry sum(0 1000)
 +
a(0000) + b(1001)  = carry sum(0 1001)
 +
a(0000) + b(1010)  = carry sum(0 1010)
 +
a(0000) + b(1011)  = carry sum(0 1011)
 +
a(0000) + b(1100)  = carry sum(0 1100)
 +
a(0000) + b(1101)  = carry sum(0 1101)
 +
a(0000) + b(1110)  = carry sum(0 1110)
 +
a(0000) + b(1111)  = carry sum(0 1111)
 +
a(0001) + b(0000)  = carry sum(0 0001)
 +
 +
...
 +
 +
a(1111) + b(1110)  = carry sum(1 1101)
 +
a(1111) + b(1111)  = carry sum(1 1110)
 +
Stopped at time : 266 ns :  in File "//psf/Home/Desktop/Xilinx Stuff/Projects/NBitAdder/test4.v" Line 61
 +
ISim> 
 +
</pre></code>
 +
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
[[Category:Xilinx]][[Category:CPLD]][[Category:Labs]][[Category:Tutorials]]

Latest revision as of 06:59, 6 April 2017

--D. Thiebaut 11:03, 24 April 2012 (EDT)


This lab should be done after the introduction lab on Verilog. It shows how to use two modules, one for the basic 3-bit full-adder (adding a to b with carry-in), and one that uses 4 of them to create a 4-bit adder with an output carry.

Full-Adder in Verilog

Review

A full adder is a combinational logic that takes 3 bits, a, b, and carry-in, and outputs their sum, in the form of two bits, carry-out, and sum.

The figure below illustrates the circuit:


FullAdder3Bits.png


New Project

  • The first task is start the Xilinx ISE and create a New Project. Let's call it FourBitAdder.
  • Once the Project is created, add a New Source, of type Verilog Module. Call it SingleStage. It will contain the full-adder for 2 bits.
  • Define the ports as follows:
    • a, input
    • b, input
    • cin, input
    • s, output
    • cout, output

We now have several options to define this adder. One is functional, as illustrated in the next subsection. Next is a logical description, where we express the outputs in terms of their logical equation. The final is a gate level description. Pick the one that seem most interesting to you. They should all yield the same result in the next section, where we test them.

Functional Description of Full Adder


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// SingleStage.v
//
//////////////////////////////////////////////////////////////////////////////////
module singleStage (
	 input a,
	 input b,
	 input cin,
	 output s,
	 output cout );
	 
	assign {cout,s} = a + b + cin;

endmodule


Logical Description of Full Adder

  • Complete the code of the module so that it looks like this:


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// SingleStage.v
//
//////////////////////////////////////////////////////////////////////////////////
module singleStage (
	 input a,
	 input b,
	 input cin,
	 output s,
	 output cout );
	 
         assign s = a ^ b ^ cin;
	 assign cout = (a & b)  |  (a & cin)  |  (b & cin);

endmodule


Gate-Level Description of Full Adder


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// SingleStage.v
//
//////////////////////////////////////////////////////////////////////////////////
module singleStage (
	 input a,
	 input b,
	 input cin,
	 output s,
	 output cout );
	 
         // wires (from ands to or)
	 wire w1, w2, w3;
	 
         // carry-out circuitry
	 and( w1, a, b );
	 and( w2, a, cin );
	 and( w3, b, cin );
	 or( cout, w1, w2, w3 );
	 
         // sum
	 xor( s, a, b, cin );

endmodule


Check Module for Syntax Errors

  • Click on the module file and select it in the Implementation window, and
  • In the Process window, below the implementation window, double click on Synthesize, in the Implement Design menu.
  • You should get this message in the console:
  Process "Simulate Behavioral Model" completed successfully
(If not, fix the bugs and retry!)

Generate a Test Module

  • Add a New Source to the project, of type Verilog Test Fixture.
  • Call it test.
  • Specify SingleStage as the target of the testing.
  • Edit the test.v file as illustrated below:


`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Module Name:   Y:/Desktop/Xilinx Stuff/Projects/NBitAdder/test.v
// 
////////////////////////////////////////////////////////////////////////////////

module test;

	// Inputs
	reg a;
	reg b;
	reg cin;

	// Outputs
	wire s;
	wire cout;

	integer i;
	
	// Instantiate the Unit Under Test (UUT)
	SingleStage uut (
		.a(a), 
		.b(b), 
		.cin(cin), 
		.s(s), 
		.cout(cout)
	);

	initial begin
		// Initialize Inputs
		a = 0;
		b = 0;
		cin = 0;
	end

	always @ ( a, b, cin )
		begin
       
                // generate truth table
		for ( i = 0; i < 8; i = i + 1 )
                        // every 10 ns set a, b, and cin to the binary rep. of i
			#10 {a, b, cin} = i;
			
                // stop 10ns after last change of inputs
		#10 $stop;
		end

      
endmodule


Some explanations

integer i
this is necessary since we have a loop that is going 8 times
initial begin
an initial block is done only once, at the beginning of the simulation. Here we make sure all the signals are 0 when we start.
always @ ( a or b or cin )
an always block means that whenever a or b or cin are modified the inside of the block should be evaluated. In essence we mean that whatever is in this block is dynamic and should be evaluated at any signal change.
#10 {a, b, cin} = i
After a delay of 10 ns, we take the bits that form the integer i (by default an integer contains 32 bits) and assign the lower ones to the three bits a, b, and cin. It's an easy way to generate a truth table.
#10 $stop
10 ns after the loop has terminated, stop the simulation.

Simulation

  • Click on the Simulation button at the top of the Design Window,
  • Select test.v as target
  • Click on Behavioral Check Syntax and fix any bugs you may have.
  • Finally, double click on Simulate Behavioral Model
  • Verify that you obtain a timing diagram that demonstrates the correct operation of your adder:

Xilinx Verilog FullAdder Simulation Timing.png


Better Simulation Output

The timing diagram is fine, but a bit hard to read. A simpler test would be to have the simulation print out the value of the signals. This can be done by calling the predefined $monitor( ) function that will print to the console whenever there is a change in any of the signals.

    $monitor( "%d ns: a + b + cin = %b + %b + %b = cout sum = %b %b", $time, a, b, cin, cout, s );


Simply add the $monitor statement inside the always block:

always @ ( a or b or cin )
		begin
		// Wait 100 ns for global reset to finish
		for ( i = 0; i < 8; i = i + 1 )
			begin
			#10 {a, b, cin} = i;
			$monitor( "%d ns: a + b + cin = %b + %b + %b = cout sum = %b %b",
						 $time, a, b, cin, cout, s );
			end 
		#10 $stop; 
		end


Rerun the simulation and observe the output in the console of the ISim application:

ISim O.87xd (signature 0x2f00eba5)
WARNING: A WEBPACK license was found.
WARNING: Please use Xilinx License Configuration Manager to check out a full ISim license.
WARNING: ISim will run in Lite mode. Please [...] Full version.
This is a Lite version of ISim.
Time resolution is 1 ps
Simulator is doing circuit initialization process.
Finished circuit initialization process.
                  10 ns: a + b + cin = 0 + 0 + 0 = cout sum = 0 0
                  20 ns: a + b + cin = 0 + 0 + 1 = cout sum = 0 1
                  30 ns: a + b + cin = 0 + 1 + 0 = cout sum = 0 1
                  40 ns: a + b + cin = 0 + 1 + 1 = cout sum = 1 0
                  50 ns: a + b + cin = 1 + 0 + 0 = cout sum = 0 1
                  60 ns: a + b + cin = 1 + 0 + 1 = cout sum = 1 0
                  70 ns: a + b + cin = 1 + 1 + 0 = cout sum = 1 0
                  80 ns: a + b + cin = 1 + 1 + 1 = cout sum = 1 1
Stopped at time : 90 ns :  in File "//psf/Home/Desktop/Xilinx Stuff/Projects/NBitAdder/test.v" Line 62 

A 4-Bit Adder

We will now create a new Verilog module called MultiStages.v to create a full 4-bit adder.

The idea is simple. We want to add a 4-bit word to another 4-bit word and get a 4-bit sum, and a carry out.

4BitAdderBlockDiagram.jpg
(Image taken from http://cpuville.com/adder.htm)


New Verilog Module

All we need to do is write Verilog code that will replicate the full-adder encapsulated in SingleStage 4 times, and let the carry ripple from one stage to the next.

  • Create a New Source of type Verilog Module and call it MultiStage
  • Its ports should be defined as follows:

XilinxVerilog4BitAdderPorts.png


  • Edit the code of the new module and replicate the code showed below:


module MultiStages(
    input [3:0] a,
    input [3:0] b,
    output [3:0] sum,
    output carry
    );
	wire cin;
	
	assign cin = 1'b0;
	SingleStage s0( .a( a[0] ), .b( b[0]), .cin( cin ), .s( sum[0]), .cout( ripple0 ) );
	SingleStage s1( .a( a[1] ), .b( b[1]), .cin( ripple0 ), .s( sum[1]), .cout( ripple1 ) );
	SingleStage s2( .a( a[2] ), .b( b[2]), .cin( ripple1 ), .s( sum[2]), .cout( ripple2 ) );
	SingleStage s3( .a( a[3] ), .b( b[3]), .cin( ripple2 ), .s( sum[3]), .cout( carry ) );

endmodule


  • Check the syntax of your module and fix any bugs you discover!

Explanations

wire cin
assign cin = 1'b0
The first stage of the adder, the one adding the Least Significant bits should have a 0 coming in on its carry-in input. This is done by creating this wire, which we set equal to 0 all the time in the next statement. The 1'b0 notation means 1 bit, with binary value 0.
SingleStage( ... .cout( ripple1 )...)
SingleStage( ... .cin( ripple1 ) ...)
The carry-out of one stage is directly connected to the carry-in of the next stage. We need a wire for this purpose. We could have defined ripple1 as a wire, but Verilog allows one to not declare wires that are internal to the circuit, connecting one block to another.

Test Module

  • Add a New Source file of type Verilog Test Fixture and call it test4.
  • Attach it to MultiStages
  • Edit the module as shown below:


`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
//
// Verilog Test Fixture created by ISE for module: MultiStages
////////////////////////////////////////////////////////////////////////////////

module test4;

	// Inputs
	reg [3:0] a;
	reg [3:0] b;

	// Outputs
	wire [3:0] sum;
	wire carry;

	// vars
	integer i;
	
	// Instantiate the Unit Under Test (UUT)
	MultiStages uut (
		.a(a), 
		.b(b), 
		.sum(sum), 
		.carry(carry)
	);

	initial begin
		// Initialize Inputs
		a = 0;
		b = 0;
	end
	
	initial
		$monitor( "a(%b) + b(%b)  = carry sum(%b %b)", a, b, carry, sum );

		
	always @(a or b)
		begin
		for ( i=0; i< 16 * 16; i = i + 1 ) 
			#1 {a, b} = i; 
			
		#10 $stop;
		end
      
endmodule


You should be able to recognize the main features of the test module by now. The one that might be surprising is the for loop. The 16 * 16 terms simply means that we want to test all the combinations of a added to b. Since a and b are 4 bits, each can be one of 16 possible configurations, hence 16 * 16.

  • Check the Behavioral Syntax of your module and fix bugs if necessary.
  • RUn the Behavioral Simulation Module
  • Verify that you get an output similar to the one illustrated below.


Xilinx4BitAdderTimingDiagram.png



ISim O.87xd (signature 0x2f00eba5)
WARNING: A WEBPACK license was found.
WARNING: Please use Xilinx License Configuration Manager to check out a full ISim license.
WARNING: ISim will run in Lite mode. Please [...] Full version.
This is a Lite version of ISim.
Time resolution is 1 ps
Simulator is doing circuit initialization process.
Finished circuit initialization process.
a(0000) + b(0000)  = carry sum(0 0000)
a(0000) + b(0001)  = carry sum(0 0001)
a(0000) + b(0010)  = carry sum(0 0010)
a(0000) + b(0011)  = carry sum(0 0011)
a(0000) + b(0100)  = carry sum(0 0100)
a(0000) + b(0101)  = carry sum(0 0101)
a(0000) + b(0110)  = carry sum(0 0110)
a(0000) + b(0111)  = carry sum(0 0111)
a(0000) + b(1000)  = carry sum(0 1000)
a(0000) + b(1001)  = carry sum(0 1001)
a(0000) + b(1010)  = carry sum(0 1010)
a(0000) + b(1011)  = carry sum(0 1011)
a(0000) + b(1100)  = carry sum(0 1100)
a(0000) + b(1101)  = carry sum(0 1101)
a(0000) + b(1110)  = carry sum(0 1110)
a(0000) + b(1111)  = carry sum(0 1111)
a(0001) + b(0000)  = carry sum(0 0001)

...

a(1111) + b(1110)  = carry sum(1 1101)
a(1111) + b(1111)  = carry sum(1 1110)
Stopped at time : 266 ns :  in File "//psf/Home/Desktop/Xilinx Stuff/Projects/NBitAdder/test4.v" Line 61 
ISim>