【Verilog】32位单精度浮点数比较大小

本文介绍了如何在Verilog中使用位操作实现单精度浮点数的float_max模块,通过C语言实现对比并验证其正确性,适合初学者理解浮点数比较原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考链接

32位单精度浮点数的IEEE表示法

问题描述

  在使用Verilog编写模块时,有时会需要进行多个浮点数中取最大/最小值的操作,而Vivado中提供的floating-point IP核并未提供取极值的相关操作。这里实现了一个float_max模块用于获取两个输入浮点数中的最大值。

C实现

    单精度浮点数比较大小的过程见float_max函数,这里在主函数中将float_max和max函数的输出结果进行了比较,用于保证float_max的正确性。


#include <stdio.h>
#include <math.h>

float float_max(float a, float b) {
    unsigned int a_hex = *((unsigned int*)&a);
    unsigned int b_hex = *((unsigned int*)&b);
    unsigned int a_flag = a_hex & 0x80000000;
    unsigned int a_floor = a_hex & 0x7f800000;
    unsigned int a_tail = a_hex & 0x007fffff;
    unsigned int b_flag = b_hex & 0x80000000;
    unsigned int b_floor = b_hex & 0x7f800000;
    unsigned int b_tail = b_hex & 0x007fffff;
    
    if (a == b) {
        return a;//or b
    }
    else if (a != b && a_flag > b_flag) {
        return b;
    }
    else if (a != b && a_flag < b_flag) {
        return a;
    }
    else if (a != b && a_flag == b_flag && a_flag == 0 && a_floor > b_floor) {
        return a;
    }
    else if (a != b && a_flag == b_flag && a_flag == 0 && a_floor < b_floor) {
        return b;
    }
    else if (a != b && a_flag == b_flag && a_flag == 0 && a_floor == b_floor && a_tail > b_tail) {
        return a;
    }
    else if (a != b && a_flag == b_flag && a_flag == 0 && a_floor == b_floor && a_tail < b_tail) {
        return b;
    }
    else if (a != b && a_flag == b_flag && a_flag > 0 && a_floor > b_floor) {
        return b;
    }
    else if (a != b && a_flag == b_flag && a_flag > 0 && a_floor < b_floor) {
        return a;
    }
    else if (a != b && a_flag == b_flag && a_flag > 0 && a_floor == b_floor && a_tail > b_tail) {
        return b;
    }
    else if (a != b && a_flag == b_flag && a_flag > 0 && a_floor == b_floor && a_tail < b_tail) {
        return a;
    }
    return 0;
}

float max(float a, float b) {
    if (a > b)
        return a;
    else
        return b;
}

int main()
{
    float a = 0;
    float b = 0;
    for (a = -10; a < 10; a += 0.01) {
        for (b = -10; b < 10; b += 0.01) {
            if (fabs(float_max(a,b) - max(a,b)) > 1e-3) {
                printf("%f %f %f %f\n", a, b, float_max(a,b), max(a,b));
                return 0;
            }
        }
    }
    printf("done:)");
    return 0;
}

Verilog实现

  在Vivado中,float_max函数可改写为如下代码:

module float_max #(
    localparam precision = 32
) (
    input  [31 : 0] a,
    input  [31 : 0] b,
    output [31 : 0] c
);
    wire            a_flag  = a[31];
    wire   [7 : 0]  a_floor = a[30 : 23];
    wire   [22 : 0] a_tail  = a[22 : 0];
    wire            b_flag  = b[31];
    wire   [7 : 0]  b_floor = b[30 : 23];
    wire   [22 : 0] b_tail  = b[22 : 0];
    
    wire            a_e_b = ~(| (a[31 : 0] ^ b[31 : 0]));
    //wire            a_flag_g_b_flag = a_flag & (~b_flag);
    wire            a_flag_l_b_flag = (~a_flag) & b_flag;
    wire            a_flag_e_b_flag = ~(a_flag ^ b_flag);
    wire            a_floor_g_b_floor = a_floor > b_floor ? 1 : 0;
    wire            a_floor_l_b_floor = a_floor < b_floor ? 1 : 0;
    wire            a_floor_e_b_floor = ~(| (a_floor[7 : 0] ^ b_floor[7 : 0]));
    wire            a_tail_g_b_tail = a_tail > b_tail ? 1 : 0;
    wire            a_tail_l_b_tail = a_tail < b_tail ? 1 : 0;
    //wire            a_tail_e_b_tail = ~(| (a_tail[22 : 0] ^ b_tail[22 : 0]));
    
    wire            condition1 = a_e_b;
    //wire            condition2 = ~a_e_b & a_flag_g_b_flag;
    wire            condition3 = ~a_e_b & a_flag_l_b_flag;
    wire            condition4 = ~a_e_b & a_flag_e_b_flag & (~a_flag) & a_floor_g_b_floor;
    //wire            condition5 = ~a_e_b & a_flag_e_b_flag & (~a_flag) & a_floor_l_b_floor;
    wire            condition6 = ~a_e_b & a_flag_e_b_flag & (~a_flag) & a_floor_e_b_floor & a_tail_g_b_tail;
    //wire            condition7 = ~a_e_b & a_flag_e_b_flag & (~a_flag) & a_floor_e_b_floor & a_tail_l_b_tail;
    //wire            condition8 = ~a_e_b & a_flag_e_b_flag & (a_flag) & a_floor_g_b_floor;                           
    wire            condition9 = ~a_e_b & a_flag_e_b_flag & (a_flag) & a_floor_l_b_floor;                           
    //wire            condition10= ~a_e_b & a_flag_e_b_flag & (a_flag) & a_floor_e_b_floor & a_tail_g_b_tail;         
    wire            condition11= ~a_e_b & a_flag_e_b_flag & (a_flag) & a_floor_e_b_floor & a_tail_l_b_tail;         
    
    assign c = (condition1 | condition3 | condition4 | condition6 | condition9 | condition11) ? a : b;
endmodule

本人刚刚接触Verilog开发,编写的代码可能存在错误,欢迎大佬批评指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjh776a68

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值