0
votes

I have a homework problem where I'm supposed to create a module for single-precision IEEE-754 floating point multiplication. This is the module:

module prob3(a, b, s);

input [31:0] a, b; // operands
output reg [31:0] s; // sum - Could potentially use wire instead
integer i; // loop variable
reg [8:0] temp;
reg [47:0] intProd; // intermediate product
reg [23:0] tempA;
reg [23:0] tempB;

initial begin

    //Initialization
    for (i = 0; i < 48; i = i + 1) begin
        intProd[i] = 0;
    end

    //Compute the sign for the result
    if (a[31]^b[31] == 0) begin
        s[31] = 0;
    end
    else begin
        s[31] = 1; 
    end

    //Compute the exponent for the result
    #10 temp = a[30:23] + b[30:23] - 8'b11111111;
    //Case for overflow
    if(temp > 8'b11111110) begin
        s[30:23] = 8'b11111111;
        for (i = 0; i < 23; i = i + 1) begin
            s[i] = 0;
        end
        $finish; 
    end
    //Case for underflow
    else if (temp < 8'b00000001) begin
        for (i = 0; i < 31; i = i + 1) begin
            s[i] = 0;
        end
        $finish;
    end
    else begin
        s[30:23] = temp[7:0];
    end

    //Mutliply the signficands

    //Make implicit one explicit
    tempA[23] = 1;
    tempB[23] = 1;

    //Make operands 24 bits
    for(i = 0; i < 23; i = i + 1) begin
        tempA[i] = a[i];
        tempB[i] = b[i];
    end

    //Compute product of signficands
    intProd = tempA * tempB;

    //Check and see if we need to normalize
    if(intProd[47:46] >= 2'b10) begin
        intProd = intProd >> 1;
        temp = s[30:23] + 1'b1;
        if(temp > 8'b11111110) begin
            s[30:23] = 8'b11111111;
            for (i = 0; i < 23; i = i + 1) begin
                s[i] = 0;
            end
            $finish;  
        end
        else
            s[30:23] = temp[7:0];
    end
    s[22:0] = intProd[47:25];
end
endmodule

Here is my testbench:

module prob4;

reg [31:0] a, b;
wire [31:0] s;

// instantiate the floating point multiplier
prob3 f1(a, b, s);

initial begin

    assign a = 32'h42055555;
    assign b = 32'hBDCCCCCD;

    #10 $monitor("s = %h", s);

    assign a = 32'hBF555555;
    assign b = 32'hCAB71B00;

    #10 $monitor("s = %h", s);


    a = 32'hFF500000;
    b = 32'h7E700000;

    #10 $display("s = %b", s);

    a = 32'h01700000;
    b = 32'h02F00000;

    #10 $display("s = %b", s);

    a = 32'hBE000000;
    b = 32'h455F36DB;

    #10 $display("s = %b", s);

    a = 32'h3C800000;
    b = 32'h3A800000;

    #10 $display("s = %b", s);

    a = 32'hC797E880;
    b = 32'hB7FBA927;

    #10 $display("s = %b", s);

end

endmodule

It displays the first value of s, but that is it. I'm honestly not too familiar with Verilog, so any clarification on why this might be happening would be truly appreciated.

1

1 Answers

1
votes

The reason you are seeing only a single value for s is because all of your floating point logic (all the stuff in the prob3 module) is inside an initial block. Thus, you only run that code once; it starts at time 0, has a pause for 10 time units and finishes; never to run again. Here are a few tips for implementing the unit (assuming the module is suppose to be synthesizable and not just a functional verification model):

  • Place your combinational logic in an always @(*) block, not an initial block.

  • As toolic mentioned, only call $monitor once, and it will inform you whenever s or any other variables given as arguments change; thus you do not need the $display statements either unless you want to know the value of s at that point of execution (whether it changed or not and inline with the processes, so not necessarily the final value either). So typically your testbench main stimulus initial block would have $monitor() as the first line.

  • Don't call $finish inside your logic; ideally, you should set an error signal instead that the testbench might then choose to call $finish if it sees that error signal asserted.

  • Don't use assign inside procedural blocks (always, initial, etc), just say a = ... not assign a = ...