Lab 10: An Introduction to High-Speed Addition Deanna Sessions ECEN 248-511 TA: Priya Venkatas Date: November 6, 2013
Objectives: This lab is designed to teach us wh y certain circuits are used for certain purposes. In particular we are going to be looking at carry-lookahead addition for fast addition in high speed arithmetic units. This particular circuit is better than a ripple carry adder when it comes to high speed addition and it minimizes the delay that would be encountered in the ripple carry. This will involve the implementation of dataflow of structural Verilog.
Design: Below is the source code for all of the different modules that are used in this lab . //clu `timescale 1ns/1ps `default_nettype none module carry_lookahead_unit (C, G, P, C0); output wire [4:1] C; input wire [3:0] G, P; input wire C0;
//Assigning each input and output wire
//creating the internal structure of the circuit by logic statements assign #4 C[1] = G[0] | P[0] & C0; assign #4 C[2] = G[1] | P[1] & G[0] | P[1] & P[0] & C0; assign #4 C[3] = G[2] | P[2] & G[1] | P[2] & P[1] & G[0] | P[2] & P[1] & P[0] & C0; assign #4 C[4] = G[3] | P[3] & G[2] | P[3] & P[2] & G[1] | P[3] & P[2] & P[1] & G[0] | P[3] & P[2] & P[1] & P[0] & C0; endmodule //gpu `timescale 1ns/1ps `default_nettype none module generate_propagate_unit (G, P, X, Y); output wire [15:0] G, P; input wire [15:0] X, Y; assign #2 G = X & Y; assign #2 P = X ^ Y;
//defining each input or output
//internal structure with included time delays
endmodule //cla_4bit `timescale 1ns/1ps `default_nettype none module carry_lookahead_4bit ( Cout, S, X, Y, Cin); output wire Cout; //Assigns input and output wires output wire [3:0] S; input wire [3:0] X, Y; input wire Cin; wire [3:0] G, P; wire [4:0] C;
//Assigns internal wires
assign C[0] = Cin; generate_propagate_unit gp0 ( G, P, X, Y); carry_lookahead_unit cl0 (C[4:1], G, P, Cin); summation_unit s0 (S, P, C[3:0]); assign Cout = C[4];
//calls the generate/propagate unit //calls the carry lookahead unit //calls the summation unit //Assigns the output of Cout to be the last C
endmodule //block_carry_lookahead_unit `timescale 1 ns/ 1 ps `default_nettype none module block_carry_lookahead_unit(G_star, P_star, C, G, P, C0); output wire G_star, P_star; output wire [3:1] C; input wire [3:0] G, P; input wire C0;
//defining all of the inputs and outputs
//assigning each all of the internal structures of the circuit assign #4 C[1] = G[0]|P[0]&C0; assign #4 C[2] = G[1]|P[1]&G[0]|P[1]&P[0]&C0; assign #4 C[3] = G[2]|P[2]&G[1]|P[2]&P[1]&G[0]|P[2]&P[1]&P[0]&C0; assign #4 G_star = G[3]|P[3]&G[2]|P[3]&P[2]&G[1]|P[3]&P[2]&P[1]&G[0]; assign #2 P_star = P[3]&P[2]&P[1]&P[0]; endmodule //carry_lookahead_16bit `timescale 1 ns/ 1 ps `default_nettype none module carry_lookahead_16bit(Cout, S, X, Y, Cin); output wire Cout; output wire [15:0] S; input wire [15:0] X, Y; input wire Cin;
//defining input and output wires
wire [16:0] C; wire [15:0] P, G; wire [3:0] P_star, G_star;
//internal wires to be used in the units called later on
assign C[0] = Cin;
//assigning Cin to be the first bit of the C wire
//each of the units called from this point forward are set up based on the schematic from the manual generate_propagate_unit GPU(G, P, X, Y); block_carry_lookahead_unit BCLAU0( //calling the block-carry-lookahead and setting up variables .G_star (G_star[0]), .P_star (P_star[0]), .C (C[3:1]), .G (G[3:0]), .P (P[3:0]), .C0 (C[0])
); block_carry_lookahead_unit BCLAU1( .G_star (G_star[1]), .P_star (P_star[1]), .C (C[7:5]), .G (G[7:4]), .P (P[7:4]), .C0 (C[4]) ); block_carry_lookahead_unit BCLAU2( .G_star (G_star[2]), .P_star (P_star[2]), .C (C[11:9]), .G (G[11:8]), .P (P[11:8]), .C0 (C[8]) ); block_carry_lookahead_unit BCLAU3( .G_star (G_star[3]), .P_star (P_star[3]), .C (C[15:13]), .G (G[15:12]), .P (P[15:12]), .C0 (C[12]) ); carry_lookahead_unit CLAU( .C({C[16], C[12], C[8], C[4]}), .G(G_star[3:0]), .P(P_star[3:0]), .C0(C[0]) );
//calling second block carry lookahead unit
//calling third block carry lookahead unit
//calling the fourth lookahead unit
//carry lookahead unit
summation_unit SU( .S(S[15:0]), .P(P[15:0]), .C(C[15:0]) );
//summation unit
assign Cout=C[16];
//assigning Cout to be the last bit of the C wire
endmodule
Results and Conclusion: All of the code successfully worked in the way that I had intended it to work and the new 16-bit carry look-ahead adder made for a very interesting test to see how much faster it is than the ripple carry adder. The significant difference in propagation delay begs the question of why we would ever use a ripple carry adder in the first place. It became apparent that the carry lookahead adder works much faster because it is configured in parallel as opposed to the series configuration of full adders in the ripple carry adder. This high speed addition circuit has minimal propagation delay and the entire timing diagrams can be seen in the waveforms below.
Figure 1: Experiment 1 4-bit Carry Look-Ahead Adder
Figure 2: Experiment 1 4-bit Carry Look-Ahead Adder zoomed in on earlier timing
Figure 3: Experiment 1 Propagation delay with markers
Figure 4: Experiment 1Waveform in its entirety
Figure 5: Experiment 2 Test-Delay 14 (Failed tests)
Figure 6: Experiment 2 Test-Delay 16 (Passed all tests)
Questions:
1. Source code can be seen in the design section. 2. Screenshots can be seen in the results section. 3. Questions throughout lab manual: a. Experiment 2: If your calculations in the prelab are correct and you correctly added delays to your sub-modules, you should find that the computed delay matches the measure delay. Is this the case? i. Yes it is the case. I calculated delta-g to be 2 ns and that the coefficient was 8. This time delay of 16 ns was exactly what the time delay ended up being for this circuit. 4. How does the gate-count of the 16-bit carry lookahead adder compare to that of a ripplecarry adder of the same size? a. The 16-bit carry look-ahead adder has 82 gates in it and a 16-bit ripple carry adder has about 80 gates (varying depending on the internal components of the full-adders.) However, for roughly the same amount of gates the 16-bit carry look-ahead adder as the ripple-carry adder, but the carry look-ahead works at a significantly higher speed. 5. How does the propagation delay of the 4-bit carry lookahead adder compare to that of a ripple-carry adder of the same size. Similarly, how does the 16-bit carry lookahead adder compare to that of a ripple carry adder of the same size. a. The 4-bit carry look-ahead adder the propagation delay is 3Δg. The 4-bit ripple carry adder has a delay of 9Δg. For the 16-bit carry look-ahead adder there is a delay of 8Δg and for a 16 bit ripple carry adder the delay is upwards of 33Δg because it has upwards of 80 gates lined up in series for the most part. The carry look-ahead adder has a smaller delay in both instances because it works in a more efficient manner than the ripple carry adder. This is due to the usage of different block units strung together to achieve a common goal using parallel circuitry rather than a long string of full adders in se ries like the ripple carry adder.
Student Feedback: 1. I liked working with Verilog again. It’s really a wonderful program. I disliked that some of this stuff is confusing to look at and plug into Verilog. 2. Nothing was unclear. 3. I don’t really have any suggestions other than possibly a bit more guidance about what Cin and Cout should be assigned to seeing as that gave me a bit of grief.