`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