//////////////////////////////////////////////////////////////////////////////// /// /// Solution to LSU EE 3755 Fall 2001 Homework 5 /// //////////////////////////////////////////////////////////////////////////////// /// Problem 1 Solution /// module itod(double,int); input [51:0] int; output [63:0] double; reg [51:0] abs_int; reg sign; reg [10:0] exp; reg [51:0] frac; wire [5:0] lz; clz60 c1(lz,{abs_int,8'b0}); assign double = {sign, exp, frac }; always @( int or lz ) begin sign = int[51]; abs_int = sign ? -int : int; frac = abs_int << lz + 1; exp = int ? 1023 + 51 - lz : 0; end endmodule //////////////////////////////////////////////////////////////////////////////// /// Problem 2 Solution /// module pop64(p,n,clk); input [63:0] n; input clk; output [6:0] p; reg [6:0] p; reg [31:0] n32; reg [5:0] pfirst; wire [5:0] p32; reg state; pop32 my_instance_of_module_pop32(p32,n32); initial state = 0; always @( posedge clk ) case( state ) 0: begin p = pfirst + p32; n32 = n[63:32]; state = 1; end 1: begin pfirst = p32; n32 = n[31:0]; state = 0; end endcase endmodule //////////////////////////////////////////////////////////////////////////////// /// Modules Needed for Solutions // module clz60(lz,r); input [59:0] r; output [5:0] lz; // Set LZ to the number of leading zeros in r. reg [5:0] lz; reg [63:0] rcopy, mask; integer i; reg [7:0] j; always @( r ) begin rcopy = {r,4'h8}; for(i=5; i>=0; i=i-1) begin for(j=0; j<64; j=j+1) mask[63-j] = j[i]; lz[i] = ( rcopy & ~mask ) == 0; rcopy = lz[i] ? rcopy & mask : rcopy & ~mask; end end endmodule module pop32(p,n); input [31:0] n; output [5:0] p; // Set p to the number of 1's in n. reg [5:0] p; integer i; always @( n ) begin p = 0; for( i=0; i<32; i=i+1 ) p = p + n[i]; end endmodule //////////////////////////////////////////////////////////////////////////////// /// Problem 1 Testbench /// module test_itod(); parameter stop_on_error = 1; parameter verbose = 0; reg [51:0] int; wire [63:0] dbl; wire [5:0] lz; itod i1(dbl,int); clz60 c(lz,{int,8'b0}); integer i, z, err; real dshadow; initial begin err = 0; for(i=0; i<1000; i=i+1) begin z = ( $random >> 1 )% 52; int[50:0] = i ? {$random,$random} >> z : 0; int[51] = 0; if( int && $random & 1 ) begin dshadow = int * -1.0; int = -int; end else begin dshadow = int; end #1; if( verbose ) $display("int 0x%x lz %d, Conversion %.f, %h = %h", int,lz,dshadow, dbl, $realtobits(dshadow)); if( dbl !== $realtobits(dshadow) ) begin $display("FAIL: Wrong conversion %f, %h != %h", dshadow, dbl, $realtobits(dshadow)); err = err + 1; if( stop_on_error) $stop; end end if( err == 0 ) $write("PASS: "); $display("All tests done, %d error%s detected.", err, err == 1 ? "" : "s"); end endmodule module test_pop(); parameter show_count = 4; parameter stop_on_error = 1; reg [63:0] n; wire [6:0] p; reg clk; pop64 p64(p,n,clk); reg [6:0] shadow_p; integer errs, i; always begin clk = 0; #5; clk = 1; #5; end initial begin errs = 0; n = 64'b0; @( negedge clk ); for(i=0; i<1000; i=i+1) begin:B integer s; reg bit; bit = $random; shadow_p = 0; for(s=0; s < 64; s = s ) begin:A integer r, e; case( 1 ) i==0: begin bit = 0; r = 64; end i==1: begin bit = 1; r = 64; end i & 1: r = ( $random & 'h7 ) + 1; default: r = ( $random & 'h3f ) + 1; endcase if( r + s > 64 ) r = 64 - s; for( e = s + r; s < e; s = s + 1 ) n[s] = bit; if( bit ) shadow_p = shadow_p + r; bit = ~bit; end repeat( 4 ) @( negedge clk ); if( p !== shadow_p ) begin errs = errs + 1; if( show_count >= errs ) $display("FAIL: Wrong output for 0x%h: %d (correct) != %d (wrong)\n", n, shadow_p, p); if( stop_on_error ) $stop; end end if( errs == 0 ) $write("PASS: "); $display("All %d tests completed, %d error%s found.\n", i, errs, errs == 1 ? "" : "s"); $stop; end endmodule