0
0
VerilogHow-ToIntermediate · 4 min read

Verilog Code for Floating Point Adder: Syntax and Example

A floating point adder in Verilog adds two floating point numbers by aligning exponents, adding mantissas, normalizing the result, and adjusting the exponent. The design typically involves modules for exponent comparison, mantissa addition, normalization, and rounding, all implemented using always blocks and bitwise operations.
📐

Syntax

The floating point adder module in Verilog usually has inputs for two floating point numbers and an output for the sum. It includes internal steps like exponent comparison, mantissa alignment, addition, normalization, and rounding.

Key parts:

  • Inputs: Two floating point numbers (usually IEEE 754 format).
  • Output: The floating point sum.
  • Internal registers: To hold exponent, mantissa, and sign bits.
  • Always blocks: For combinational logic to perform addition and normalization.
verilog
module fp_adder(
    input  [31:0] a, // First floating point number
    input  [31:0] b, // Second floating point number
    output [31:0] sum // Result of addition
);

// Internal signals for sign, exponent, mantissa
reg sign_a, sign_b, sign_sum;
reg [7:0] exp_a, exp_b, exp_diff, exp_sum;
reg [24:0] mant_a, mant_b, mant_sum;

always @(*) begin
    // Extract sign
    sign_a = a[31];
    sign_b = b[31];
    
    // Extract exponent
    exp_a = a[30:23];
    exp_b = b[30:23];
    
    // Extract mantissa and add implicit leading 1
    mant_a = {1'b1, a[22:0], 1'b0};
    mant_b = {1'b1, b[22:0], 1'b0};

    // Align mantissas by shifting the smaller exponent mantissa
    if (exp_a > exp_b) begin
        exp_diff = exp_a - exp_b;
        mant_b = mant_b >> exp_diff;
        exp_sum = exp_a;
    end else begin
        exp_diff = exp_b - exp_a;
        mant_a = mant_a >> exp_diff;
        exp_sum = exp_b;
    end

    // Add mantissas
    mant_sum = mant_a + mant_b;

    // Normalize result (if mantissa overflows)
    if (mant_sum[24]) begin
        mant_sum = mant_sum >> 1;
        exp_sum = exp_sum + 1;
    end

    // Assign sign (simple case: both signs same)
    sign_sum = sign_a; // For simplicity
end

// Compose final sum
assign sum = {sign_sum, exp_sum, mant_sum[23:1]};

endmodule
💻

Example

This example shows a simple floating point adder module that adds two 32-bit IEEE 754 floating point numbers. It extracts sign, exponent, and mantissa, aligns mantissas, adds them, normalizes the result, and outputs the sum.

verilog
module test_fp_adder;
    reg [31:0] a, b;
    wire [31:0] sum;

    fp_adder uut(.a(a), .b(b), .sum(sum));

    initial begin
        // Example values: 1.5 and 2.5 in IEEE 754
        a = 32'h3FC00000; // 1.5
        b = 32'h40200000; // 2.5

        #10;
        $display("a = %h, b = %h, sum = %h", a, b, sum);
        $finish;
    end
endmodule

module fp_adder(
    input  [31:0] a,
    input  [31:0] b,
    output [31:0] sum
);

reg sign_a, sign_b, sign_sum;
reg [7:0] exp_a, exp_b, exp_diff, exp_sum;
reg [24:0] mant_a, mant_b, mant_sum;

always @(*) begin
    sign_a = a[31];
    sign_b = b[31];
    exp_a = a[30:23];
    exp_b = b[30:23];
    mant_a = {1'b1, a[22:0], 1'b0};
    mant_b = {1'b1, b[22:0], 1'b0};

    if (exp_a > exp_b) begin
        exp_diff = exp_a - exp_b;
        mant_b = mant_b >> exp_diff;
        exp_sum = exp_a;
    end else begin
        exp_diff = exp_b - exp_a;
        mant_a = mant_a >> exp_diff;
        exp_sum = exp_b;
    end

    mant_sum = mant_a + mant_b;

    if (mant_sum[24]) begin
        mant_sum = mant_sum >> 1;
        exp_sum = exp_sum + 1;
    end

    sign_sum = sign_a;
end

assign sum = {sign_sum, exp_sum, mant_sum[23:1]};

endmodule
Output
a = 3fc00000, b = 40200000, sum = 40500000
⚠️

Common Pitfalls

Common mistakes when writing a floating point adder in Verilog include:

  • Not properly aligning mantissas before addition, which leads to incorrect sums.
  • Ignoring normalization after addition, causing mantissa overflow or incorrect exponent.
  • Not handling sign bits correctly, especially when inputs have different signs.
  • Skipping rounding steps, which affects precision.
  • Assuming simple addition without considering special cases like zero, infinity, or NaN.

Always carefully implement exponent comparison, mantissa shifting, normalization, and sign handling.

verilog
/* Wrong approach: Adding mantissas without alignment */
// mant_sum = mant_a + mant_b; // Incorrect if exponents differ

/* Right approach: Align mantissas by shifting smaller exponent mantissa */
// if (exp_a > exp_b) begin
//     mant_b = mant_b >> (exp_a - exp_b);
//     exp_sum = exp_a;
// end else begin
//     mant_a = mant_a >> (exp_b - exp_a);
//     exp_sum = exp_b;
// end
// mant_sum = mant_a + mant_b;
📊

Quick Reference

Tips for writing a floating point adder in Verilog:

  • Extract sign, exponent, and mantissa from inputs.
  • Align mantissas by shifting the smaller exponent mantissa.
  • Add mantissas and normalize the result.
  • Adjust exponent after normalization.
  • Handle sign bits carefully, especially for subtraction cases.
  • Consider special cases like zero, infinity, and NaN for full IEEE 754 compliance.

Key Takeaways

Align mantissas by shifting the smaller exponent mantissa before addition.
Normalize the mantissa and adjust the exponent after addition to maintain correct format.
Handle sign bits carefully to support addition and subtraction correctly.
Include rounding and special case handling for full IEEE 754 compliance.
Test with known floating point values to verify correctness.