```////////////////////////////////////////////////////////////////////////////////
///
/// Template for LSU EE 3755 Spring 2002 Homework 4
///

/// Due: Monday, 25 March 2002

/// Name:

/// Instructions:
//
// Copy this to a file named hw04.v to directory ~/hw in your
// class account. (~ is your home directory.)  Use this
// this file.
//
// Do not rename the modules in this file and be sure to use the
// directory and filename given above.

// Local copy of this file:
//     /home/classes/ee3755/com/v/hw04.v
//
// Instruction on Simulator, Emacs, etc:
//    http://www.ece.lsu.edu/ee3755/proc.html
//
// Documentation for Simulator, Unix, etc.
//    http://www.ece.lsu.edu/ee3755/ref.html

// See problems below for further instructions.

// Warning: Problem 3 is more difficult than 1 and 2.

//
//   Passes the testbench.
//   If it fails, partial credit will be given based on the type of
//   problem.  A large amount of credit will be deducted for
//   compilation errors.
//
//   Follows the guidelines.
//   Be sure to instantiate the correct number of modules per module.
//
//   Coded cleanly.
//   Points will be deducted for code that is correct but much more
//   complex, unreadable, or inefficient than it has to be.
//   For example, points would be deducted for the second assign below.
`ifdef XXX
assign x = a & b;  // Use assign on this line instead of one on line below.
assign x = a == 1'b1 ? ( b == 1'b1 ? 1'b1 : 1'b0 ) : ( b == 1'b1 ? 1'b0 : 1'b0 );
`endif

////////////////////////////////////////////////////////////////////////////////
/// 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
// http://www.ece.lsu.edu/ee3755/2002/l07.html, also further down in
// this file) to radix 8.

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

/// Implement a 18 x 9 unsigned integer multiplier
//
//  [ ] Can use structural and synthesizable behavioral code.
//  [ ] Do not instantiate other modules.
//  [ ] Solution can use the addition operator.
//  [ ] Solution CANNOT use the multiplication operator.
//  [ ] Test using module test_8.
//
//  Can be solved by adding 8 lines to imult_ord_radix_4 (in this
//  file) and modifying several other lines.

endmodule

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

// Complete the module below so that it performs an 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;

// Implement an 18 x 18 bit multiplier using two 18 x 9 bit multipliers.
//
// [ ] Instantiate TWO mult_prob_2 modules.
// [ ] Can use structural and synthesizable procedural code.
// [ ] Can use + operator, and can assume addition is very fast.
// [ ] The two 18 x 9 bit multipliers must work simultaneously.
// [ ] Assume that the two multipliers take the same amount of time.
// [ ] Test using test_faster.
//
// Can be solved with just one line of code, plus declarations.

endmodule

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

// Complete the module below so that it performs an 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 instantiated multiplier.

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

// Implement an 18 x 18 bit multiplier using one 18 x 9 bit multiplier.
//
// [ ] Instantiate ONE mult_prob_3 module.
// [ ] Do not assume that mult_prob_3 takes a fixed amount of time.
// [ ] Can use structural and synthesizable procedural code.
// [ ] Can use + operator, and can assume addition is very fast.
// [ ] Test using test_cheaper.
//
// A straightforward solution uses 18 lines of code, plus declarations.

endmodule

////////////////////////////////////////////////////////////////////////////////
///

// The solution to Problem 1 above can be based on the module below.

input [15:0]  multiplicand, multiplier;
input         start, clk;
output        prod;

reg [32:0]    product;
wire [31:0]   prod = product[31:0];

reg [4:0]     bit;

reg [17:0]    pp;

initial bit = 0;

wire [17:0]   multiplicand_X_1 = {1'b0,multiplicand};
wire [17:0]   multiplicand_X_2 = {multiplicand,1'b0};
wire [17:0]   multiplicand_X_3 = multiplicand_X_2 + multiplicand_X_1;

always @( posedge clk )

if( ready && start ) begin

bit     = 8;
product = { 16'd0, multiplier };

end else if( bit ) begin

case ( {product[1:0]} )
2'd0: pp = {2'b0, product[31:16] };
2'd1: pp = {2'b0, product[31:16] } + multiplicand_X_1;
2'd2: pp = {2'b0, product[31:16] } + multiplicand_X_2;
2'd3: pp = {2'b0, product[31:16] } + multiplicand_X_3;
endcase

product = { pp, product[15:2] };
bit     = bit - 1;

end

endmodule

////////////////////////////////////////////////////////////////////////////////
/// Modules Instantiated In Solutions
///

// 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

////////////////////////////////////////////////////////////////////////////////
/// Testbench Code
///

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
```