```////////////////////////////////////////////////////////////////////////////////
///
/// Solution to LSU EE 3755 Spring 2002 Homework 4
///

////////////////////////////////////////////////////////////////////////////////
/// Problem 1
///

// Complete the module below so that it performs 18 bit x 9 bit
// unsigned integer multiplication using a radix-8 multiplier using
// the same handshaking as mult_18x9_sim (and other modules presented
// in class).
//
// Hint: The solution is a straightforward extension of imult_ord_radix_4
// in l07 http://www.ece.lsu.edu/ee3755/2002/l07.html) to radix 8.

input [17:0]  cand;
input [8:0]   multiplier;
input         start, clk;
output        prod;

reg [29:0]    product;
wire [26:0]   prod = product[26:0];

reg [1:0]     bit;

initial bit = 0;

wire [18:0]   candx2 = cand << 1;
wire [19:0]   candx3 = candx2 + cand;
wire [19:0]   candx4 = cand << 2;
wire [20:0]   candx5 = candx4 + cand;
wire [20:0]   candx6 = candx4 + candx2;
wire [20:0]   candx7 = candx6 + cand;

always @( posedge clk )

if( ready && start ) begin

bit     = 3;
product = { 19'd0, multiplier };

end else if( bit ) begin

case ( product[2:0] )

3'b000: product[29:9] = product[29:9];
3'b001: product[29:9] = product[29:9] + cand;
3'b010: product[29:9] = product[29:9] + candx2;
3'b011: product[29:9] = product[29:9] + candx3;
3'b100: product[29:9] = product[29:9] + candx4;
3'b101: product[29:9] = product[29:9] + candx5;
3'b110: product[29:9] = product[29:9] + candx6;
3'b111: product[29:9] = product[29:9] + candx7;

endcase

product = product >> 3;
bit     = bit - 1;

end

endmodule

////////////////////////////////////////////////////////////////////////////////
/// Problem 2
///

// Complete the module below so that it performs a 18 x 18 bit
// unsigned integer multiplication using two mult_prob_2 18 x 9 bit
// multiplier modules.  All modules use the same handshaking.

input [17:0]  cand;
input [17:0]  multiplier;
input         start, clk;
output [35:0] prod;

wire [26:0]    prod_lo, prod_hi;
wire           rdy_1;

mult_prob_2 m1(prod_lo,rdy_1,cand,multiplier[8:0], start,clk);

assign prod = prod_lo + ( prod_hi << 9 );

endmodule

////////////////////////////////////////////////////////////////////////////////
/// Problem 3
///

// Complete the module below so that it performs a 18 x 18 bit
// unsigned integer multiplication using one mult_prob_3 18 x 9 bit
// multiplier module.  All modules use the same handshaking.
//
// Hint: Use a state machine to control the two modules.

input [17:0]  cand;
input [17:0]  multiplier;
input         start, clk;
output [35:0] prod;

parameter     ST_rdy    = 3'd0;
parameter     ST_m1_rdy = 3'd1;
parameter     ST_m1_cmp = 3'd2;
parameter     ST_m2_rdy = 3'd4;
parameter     ST_m2_cmp = 3'd5;

reg [2:0]     state;

wire [8:0]    lier = state[2] ? multiplier[17:9] : multiplier[8:0];

reg [26:0]    first_prod;

wire [26:0]   prod_m;
reg           start_m;

assign        ready = state == ST_rdy;
assign        prod  = first_prod + ( prod_m << 9 );

always @( state or start )
case( state )
ST_rdy               : start_m = start;
ST_m1_rdy, ST_m2_rdy : start_m = 1;
default              : start_m = 0;
endcase

always @( posedge clk )
case( state )
ST_rdy    : if( start    ) state = ST_m1_rdy;
ST_m1_rdy : if( ~ready_m ) state = ST_m1_cmp;
ST_m1_cmp : if( ready_m  ) begin first_prod=prod_m;  state=ST_m2_rdy; end
ST_m2_rdy : if( ~ready_m ) state = ST_m2_cmp;
ST_m2_cmp : if( ready_m  ) state = ST_rdy;
default   : if( ready_m  ) state = ST_rdy;
endcase

endmodule

// exemplar translate_off

input [17:0]  cand;
input [8:0]   multiplier;
input         start, clk;
output [26:0] prod;

endmodule

input [17:0]  cand;
input [8:0]   multiplier;
input         start, clk;
output [26:0] prod;

endmodule

input [17:0]  cand;
input [8:0]   multiplier;
input         start, clk;
output [26:0] prod;

parameter     random_delay = 0;

reg [26:0]    prod;

reg [3:0]     bit;  // Not necessarily size needed for other modules.

initial bit <= 0;

always @( posedge clk )

if( ready && start ) begin

bit <= random_delay ? 1 + \$random : 3;

end else if( bit ) begin

bit <= bit - 1;
if( bit == 1 ) prod <= cand * multiplier;

end

endmodule

module test_faster();
testmults #(0) tm();
endmodule

module test_cheaper();
testmults #(1) tm();
endmodule

module test_8();
testmults #(2) tm();
endmodule

module testmults();

parameter DUT = 0;

parameter stop_on_error = 1;

parameter DUT_faster = 0;
parameter DUT_cheaper = 1;
parameter DUT_eight = 2;

reg [35:0] product;
wire [35:0] product_c, product_f;
wire [26:0]  product_8;
reg [17:0]  multiplier;
reg [17:0]  multiplicand;
reg         start, clk;

integer     i;

always @( product_c or product_f or product_8
case( DUT )
endcase

always #10 clk = !clk;

real cycles;
initial begin cycles = 0; forever @( posedge clk ) cycles <= cycles + 1; end

reg [7*8-1:0] name;
real          start_time;
real          cpm;

integer       err;

initial begin

case( DUT )
DUT_faster:  begin  lier_mask = 18'o777777; name = "Faster"; end
DUT_cheaper: begin  lier_mask = 18'o777777; name = "Cheaper"; end
endcase

clk = 0;
start = 0;
err = 0;

#25;

start_time = cycles;

\$display("Starting test for %s",name);

for(i=0; i<1000; i=i+1) begin

#5;

multiplicand = \$random & 18'o777777;

#1;

start = 1;
start = 0;
#1;

if( shadow_product !== product ) begin
\$display("FAIL: %s %o x %o = %o(correct) != %o\n",
name,
multiplier, multiplicand,
err = err + 1;
if( stop_on_error && err >= stop_on_error ) \$stop;
end

end

cpm = (cycles - start_time) / ( i ? i : 1 );

\$display("Finished at speed of %f cycles per multiplication.", cpm);

case ( DUT )
DUT_faster:
if( cpm > 5.1 ) begin
\$display("FAIL: Faster multiplier taking too long.");
err = err + 1;
end else if ( cpm < 3.0 ) begin
\$display("FAIL: Faster multiplier too fast.");
err = err + 1;
end
DUT_eight:
if( cpm > 4.1 ) begin
\$display("FAIL: Radix 8 multiplier taking too long.");
err = err + 1;
end else if ( cpm < 3.0 ) begin
\$display("FAIL: Radix 8 multiplier too fast.");
err = err + 1;
end
DUT_cheaper:
if( cpm > 22 ) begin
\$display("FAIL: Cheaper multiplier taking too long.");
err = err + 1;
end else if ( cpm < 15 ) begin
\$display("FAIL: Cheaper multiplier too fast.");
err = err + 1;
end
endcase

if( err )
\$display("FAIL: %s, encountered %d errors.",name,err);
else
\$display("PASS: %s, no errors found.",name);

\$display("Done with tests.");

\$stop;

end

endmodule

// exemplar translate_on
```