////////////////////////////////////////////////////////////////////////////////
///
/// Solution to LSU EE 3755 Fall 2001 Homework 3
///

// Additional material in 
http://www.ece.lsu.edu/ee3755/2001f/hw03sol.pdf
/// Problem 1 module prob1(sum,a,b); input [29:0] a; input [9:0] b; output [30:0] sum; // Sign extend the operands to the same size as the sum. assign sum = {a[29],a} + { b[9] ? 21'h1ffff : 21'h0, b }; endmodule /// Problem 3 // Solution module cla40(cout,sum,a,b); input [39:0] a, b; output [39:0] sum; output cout; // G[0] intentionally left unconnected. wire [3:0] G, P, cin; assign cin[0] = 0; assign cin[1] = G[0]; assign cin[2] = G[0] & P[1] | G[1]; assign cin[3] = G[0] & P[1] & P[2] | G[1] & P[2] | G[2]; assign cout = G[0] & P[1] & P[2] & P[3] | G[1] & P[2] & P[3] | G[2] & P[3] | G[3]; cla10 c0(G[0],P[0],sum[9:0], a[9:0], b[9:0],cin[0]); cla10 c1(G[1],P[1],sum[19:10], a[19:10], b[19:10],cin[1]); cla10 c2(G[2],P[2],sum[29:20], a[29:20], b[29:20],cin[2]); cla10 c3(G[3],P[3],sum[39:30], a[39:30], b[39:30],cin[3]); endmodule // Code needed to test solution. module cla10(G,P,sum,a,b,cin); input [9:0] a, b; input cin; output G, P; output [9:0] sum; // Note: This isn't really a CLA. (The problem didn't ask for one.) // It's here so that the testbench will run. assign sum = a + b + cin; assign P = ( a | b ) == 10'h3ff; wire [10:0] local_sum = a + b; assign G = local_sum[10]; endmodule module testcla40(); wire [40:0] sum; reg [40:0] shadow_sum; reg [39:0] a, b; integer i; cla40 ad(sum[40],sum[39:0],a,b); initial begin a = 0; b = 0; #1; for(i=0; i<5000; i=i+1) begin a[31:0] = $random; a[39:32] = $random; b[31:0] = $random; b[39:32] = $random; shadow_sum = a + b; #1; if( sum != shadow_sum ) begin $display("Wrong sum: %h + %h = %h != %h\n", a, b, shadow_sum, sum); $stop; end end $display("Tests completed."); end endmodule /// Problem 4 // Solution module streamlined_usmult(product,ready,multiplier,multiplicand,start,clk); input [15:0] multiplier, multiplicand; input start, clk; output product; output ready; reg [31:0] product; reg [4:0] bit; wire ready = !bit; initial bit = 0; always @( posedge clk ) if( ready && start ) begin bit = 16; product = { 16'd0, multiplier }; end else if( bit ) begin:A reg lsb; lsb = product[0]; product = {product[31],product[31:1]}; bit = bit - 1; if( lsb ) product[31:15] = product[31:15] + {multiplicand[15],multiplicand}; end endmodule // Testbench for problem 4 // Extend sign of vector n. `define sx(n) ( ((^((n)<<1))^(^(n))) ? -1^{(n)^~(n)}|(n) : (n) ) module testmult(); wire [31:0] product; wire ready; reg [15:0] multiplier, multiplicand; reg start, clk; integer shadow_product; integer i; streamlined_usmult m1(product,ready,multiplier,multiplicand,start,clk); parameter handshake = 1; parameter signedmult = 2; always #10 clk = !clk; initial begin:I clk = 0; start = 0; #25; for(i=0; i<10000; i=i+1) begin if( handshake ) wait( ready ); #5; multiplier = $random & 16'hffff; multiplicand = $random & 16'hffff; case( signedmult ) 0: shadow_product = multiplier * multiplicand; 1: shadow_product = `sx(multiplier) * `sx(multiplicand); 2: shadow_product = multiplier * `sx(multiplicand); endcase if( handshake ) begin start = 1; wait( !ready ); wait( ready ); end else begin #1; end if( shadow_product != product ) begin $display("Error %h x %h = %h != %h\n", multiplier, multiplicand, shadow_product, product ); case( signedmult ) 1: $display("Error %d x %d = %d != %d\n", `sx(multiplier), `sx(multiplicand), shadow_product, `sx(product) ); 2: $display("Error %d x %d = %d != %d\n", multiplier, `sx(multiplicand), shadow_product, `sx(product) ); 0: $display("Error %d x %d = %d != %d\n", multiplier, multiplicand, shadow_product, product ); endcase $stop; end end $display("Done with tests, no problems."); $stop; end endmodule