`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