`define SYN_SEQ

// Sample Questions for LSU EE 4702 Spring 2000 Final Exam

// Includes questions not covered in the 5 May class.

////////////////////////////////////////////////////////////////////////////////
// Problem 1:
// -----------------------------------------------------------------------------
// (a.1) Convert the behavior multiplier description to a synthesizable
// description that synthesizes into combinational logic.


`ifdef BEHAVIORAL_NON_SYN
module multiplier(product,a,b);
   input a,b;
   output product;

   wire [15:0] a, b;
   reg [31:0]  product, a_left;
   reg [15:0]  b_right;

   always @( a or b ) begin:MULT

      a_left = {16'd0,a};
      b_right = b;
      product = 0;

      forever begin
         if( !b_right ) disable MULT;

         if( b_right[0] ) product = product + a_left;

         a_left = a_left << 1;
         b_right = b_right >> 1;
         
      end
      
   end

endmodule // multiplier
`endif // ifdef BEHAVIORAL_NON_SYN

//
// Solution to 1(a.1)
//

`ifdef SYN_COMB
module multiplier(product,a,b);
   input a,b;
   output product;

   wire [15:0] a, b;
   reg [31:0]  product, a_left;
   reg [15:0]  b_right;
   integer     i;

   always @( a or b ) begin:MULT

      a_left = {16'd0,a};
      b_right = b;
      product = 0;

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

         if( b_right[0] ) product = product + a_left;

         a_left = a_left << 1;
         b_right = b_right >> 1;
         
      end
      
   end

endmodule // multiplier
`endif

// -----------------------------------------------------------------------------
// (a.2) Draw a schematic that will look something like the
// synthesized design.  Use basic components such as gates and
// multiplexors, you don't have to use the exact components chosen by
// the synthesis program.

//
// Solution to 1(a.2)
//

// Note. An actual solution would consist of a schematic.  A lengthy
// verbal description like the one below is not necessary, it is
// there to help study for the exam.

// Since the code is combinational separate "iteration" hardware
// things will be synthesized for each iteration of the loop.  The
// index (i) will not be synthesized since its value is constant
// within the hardware that represents an iteration.

// The inputs to an "iteration" hardware thing are "product", "a_left",
// and "b_right".  The outputs are new versions of  "product", "a_left",
// and "b_right";  the outputs go to the inputs of the next iteration
// hardware thing.  The inputs to the first iteration hardware thing
// are "a" and "b" (the module ports), and the constant "0" (for product).
// Output "product" of the last iteration hardware thing goes to the
// product output port of the module.  Outputs "a_left" and "b_right"
// are ignored.

// Each iteration consists of the following:

//   The line below

//     if( b_right[0] ) product = product + a_left;

//   synthesizes into a multiplexor feeding an adder. One input to the mux
//   is "product + a_left" the other input is "product".  The control
//   input is b_right[0].

//   The lines below

//         a_left = a_left << 1;
//         b_right = b_right >> 1;

//   don't generate any logic. The most significant bit of a_left is
//   discarded and the constant zero is put in the least significant
//   position.  b_right is handled similarly.


// -----------------------------------------------------------------------------

// (b.1) Convert the behavioral multiplier description to a synthesizable
// description that uses a clock and that synthesizable into sequential
// logic. The area (number of gates) should be lower than part (a).

//
// Solution
//

`ifdef SYN_SEQ
module multiplier(product,a,b,clk);
   input a,b, clk;
   output product;

   wire [15:0] a, b;
   reg [31:0]  product, a_left, product_temp;
   reg [15:0]  b_right;
   integer     i;

   // Note form 3, an implicit state machine is used.

   always @( posedge clk ) begin

      a_left = {16'd0,a};
      b_right = b;
      // Use a temp variable because it will take several cycles
      // to update the output and we don't want intermediate results
      // at the outputs.
      product_temp = 0;

      // Insert a posedge clk. Necessary for form 3.
      begin:MULT_LOOP forever @( posedge clk ) begin

         // Disable is allowable in form 3. (Though the output is
         // updated sooner by using the disable, this isn't useful
         // because there is no ready signal.  External circuitry
         // must wait about 34 clock cycles. (With a start signal, would
         // wait only 17 cycles.)
         
         if( !b_right ) disable MULT_LOOP;
         
         if( b_right[0] ) product_temp = product_temp + a_left;

         a_left = a_left << 1;
         b_right = b_right >> 1;
         
      end end

      product = product_temp;

   end // block: MULT

endmodule // multiplier
`endif

// -----------------------------------------------------------------------------

// (b.2) Draw a schematic that will look something like the
// synthesized design.  Use basic components such as gates,
// multiplexors, and flip-flops, you don't have to use the exact
// components chosen by the synthesis program.

//
// Solution
//

// Use one copy of the iteration hardware thing described in 1.a.2.
// Add registers for product_temp, product, a_left, and a_right.  Also
// add a register for the implicit state variable inferred by the
// synthesizer.

// The outputs of the iteration thing connect to the data inputs of
// the register a_left, a_right, and product_temp.
// Multiplexor are connected to the inputs of registers a_left, a_right;
// one input is from the output of the iteration hardware, the
// other is from the module ports.  The inputs of product_temp
// are connected to the iteration hardware output.

// The inputs of register product are connected to the outputs
// of product_temp.

//
// Another Study Question
//

// Create an explicit state machine representation of the multiplier.


// -----------------------------------------------------------------------------

// (c) First, suppose the synthesis program was not smart enough to
// figure out that the synthesizable descriptions were multipliers.
// Suppose that the implicit structural description is synthesizable
// (it is, by Leonardo) and that a combinational version will be
// synthesized.  How would the result compare to the synthesizable
// version from the previous part?

`ifdef IMPLICIT_STR
module multiplier(product,a,b);
   input a,b;
   output product;

   wire [15:0] a, b;
   wire [31:0] product = a * b;

endmodule // multiplier
`endif

//
// Solution
//

// The synthesis program would infer a multiplier. (A no-brainer
// in this case, since the multiply operator is used.) That
// would be mapped to a target-technology-optimized multiplier,
// that would probably be better than the hand coded versions.

// Note: the synthesis program can create sequential multipliers too.


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

// Why would many synthesis programs not synthesize this:

module t1(a,clk);
   input clk;
   output a;
   reg    a;

   always @( posedge clk ) begin
      a = 1;
      #1;
      a = 0;
   end
   
endmodule

// ... but would have no problem with  

module t2(a,clk);
   input clk;
   output a;
   reg    a;

   always @( posedge clk ) begin
      a = 1;
      @( posedge clk );
      a = 0;
   end
   
endmodule // t

// Solution

// The first module requires the synthesis of hardware that can
// generate a 1 unit (default 1 nanosecond) delay.  Though this could
// be done in principle it would require alot of hardware so such a
// feature would rarely be used.  The delay in the second module
// is implemented by using an implicit state variable, just one bit.


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

// -----------------------------------------------------------------------------
// (a) Show examples of two case statements, one where the parallel_case
// directive is needed, and one where it's not.

// Solution

`ifdef DONTDEFINEME

// Needed:

// Possible values for op: 100, 010, 001

wire [2:0] op;

// Needed because the synthesizer doesn't know that if the middle bit
// is 1 the leftmost bit must be zero.  (It can't according to the
// comment, which IS PART OF THE SOLUTION.)

// exemplar parallel_case
casez(op)
  3'b1??: a = 1;
  3'b?1?: b = 1;
  3'b??1: c = 1;
endcase // casez(op)


// Not Needed:

// Possible values for op: 00 01 10 11

wire [1:0] op;

case(op)
  3'b00: foo;
  3'b01: bar;
  3'b10: foobar;
  3'b11: snafu;
endcase // case(op)

`endif

// -----------------------------------------------------------------------------
// (b) How will the synthesized hardware be affected if parallel case
// is omitted where it should be used.

// Solution

// Using the solution as an example, if parallel case *is* used,
// the enable signal to register b (if thats what it is) is just
// based on op[1].  If parallel case is omitted, the enable
// signal must be (!op[2] && op[1]).







  


// exemplar translate_off
module test_mult();

   wire [31:0] p;
   reg [15:0]  a, b;
   reg         clk;
   
   multiplier m1(p,a,b,clk);

   integer     i;

   initial begin

      clk = 0;

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

         a = $random; b = $random;
         a = a >> ( $random & 15 );
         b = b >> ( $random & 15 );

         #70;

         if( a*b != p ) begin
            $display("Error: %d %d = %d",a,b,p);
            $stop;
         end
         
      end // for (i=0; i<1000; i=i+1)

      $stop;
      
   end // initial begin

   always #1 clk = ~clk;

endmodule // test_mult
// exemplar translate_on