Vivado IP核之定点数转为浮点数Floating-point

前言

        随着制造工艺的不断发展,现场可编程逻辑门阵列(FPGA)的集成度越来越高,应用也越来越广,其中在对数字信号进行处理时必然要用到一些数学处理类的IP核。最近正在研究空域自适应抗干扰技术研究的FPGA硬件实现,其中不免要用到一些IP核,今天就从定点数转浮点数详细介绍一下vivado当中的Floating-point这个IP核吧,希望对各位的学习能起到一定的帮助作用。


提示:以下是本篇文章正文内容,均为作者本人原创,写文章实属不易,希望各位在转载时附上本文链接。

一、什么是定点数?

        定点数:小数位置固定不变的数叫做定点数,也就是小数点是定在某个位置不变的数。定点数分为定点整数与定点小数,其中定点整数又分为有符号定点整数与无符号定点整数,定点小数又分为有符号定点小数与无符号定点小数。本文着重介绍32位(1+1+30)有符号定点小数,位数的大小自己可以根据不同的使用场景设定,其他三类都比较简单,这里就不予以介绍。

        小数点的位置固定在最高有效数位之前、符号位之后,如图1所示。定点小数的小数点位置是隐含约定的,小数点并不需要真正地占据一个bit位。

图1 有符号定点小数格式

         在图1中,X_{s}为符号位,当X_{s}=0时,为正小数;当X_{s}=1时,小数为负小数。n为小数的位宽,小数的位宽会直接影响小数的精度,位宽n越大精度越高。

        在xilinx vivado中的IP核,有符号定点数均以补码表示,所以我们务必要明白原码、反码、补码三者之间的关系。正数的原码、反码、补码均相同;负数的原码即为其取绝对值后正数的原码,将负数原码逐位取反,即得到负数反码,将负数反码加一即得到负数补码。

         好了,话不多说,直接上例子。

        example1:    假设一个有符号32位(1位符号位+1位整数位+30位小数位)定点小数用二进制表示为32'b0011_0111_0110_1100_1111_0101_1101_0000,那么它表示的小数换成十进制是多少呢?首先,其符号位为0,可知其为正数,那么原码、反码、补码相同;其次,整数位为0,实际对应的整数位也为0;然后,其30位小数部分为30'b11_0111_0110_1100_1111_0101_1101_0000,化为十进制数即为929887696;最后,我们知道当30位小数全为1时表示的十进制数为1073741823,那么由929887696/1073741823≈0.8660254即可得出该定点小数化为实数也就近似为0.8660254。

        example2:    假设一个有符号32位(1位符号位+1位整数位+30位小数位)定点小数用二进制表示为32'b1100_1000_1001_0011_0000_1010_0011_0000,那么它表示的小数换成十进制是多少呢?首先,其符号位为1,可知其为负数,那么32'b1100_1000_1001_0011_0000_1010_0011_0000表示的为其补码,负数原码与补码不同,我们应该先求出其原码,其原码为32'b0011_0111_0110_1100_1111_0101_1101_0000;其次,整数位为0,实际对应的整数位也为0;由前面分析可知该码表示的正小数近似为0.8660254,至此即可得出该定点小数化为实数也就近似为-0.8660254。

二、什么是浮点数?

        浮点数是一种标准化的表达方式,常用标准为IEEE754 标准,用来近似表示实数,并且可以在表达范围和表示精度之间进行权衡,因此被称为浮点数。(关于IEEE754 标准不懂的自行百度,这里不在赘述)。

        example3:    假设一个有符号32位浮点数(单精度为32位,双精度为64位)用二进制32'b0011_1111_0101_1101_1011_0011_1101_0111,那么根据IEEE754 标准可知其符号位为0,表示正小数,其指数部分为8'b0111_1110,小数部分为23'b101_1101_1011_0011_1101_0111,根据IEEE754 标准可知其表示的小数为0.8660254。

        example4:    假设一个有符号32位浮点数(单精度为32位,双精度为64位)用二进制32'b1011_1111_0101_1101_1011_0011_1101_0111,那么根据IEEE754 标准可知其符号位为1,表示负小数,其指数部分为8'b0111_1110,小数部分为23'b101_1101_1011_0011_1101_0111,根据IEEE754 标准可知其表示的小数为-0.8660254。

三、Floating-point IP核配置步骤

        在vivado中搜索Floating-point,找到该IP核后即可按照以下操作完成相应的配置。

        1.首先配置Operation Selection界面,如图2所示。

图2 Operation Selection界面的配置

         2.其次配置Precision of Inputs界面,如图3所示。

图3 Precision of Inputs 界面的配置

         3.然后配置Precision of Result界面,如图4所示。

图4 Precision of Result 界面的配置

         4.再然后配置Optimizations界面,如图5所示。

图5 Optimizations 界面的配置

         5.最后配置Interface Options界面,如图6所示。

        

图5 Interface Options 界面的配置

         以上5个界面都配置完成后即可点击右下角OK按钮生成IP核。

四、仿真

1.顶层代码

建立一个顶层模块,命名为fix_to_float_top,用来例化刚才生成的IP核。

代码如下:

`timescale 1ns / 1ps
//
// Company: 重庆大学
// Engineer: CLG 
// Create Date: 2022/07/22 09:37:43
// Design Name: 
// Module Name: fix_to_float_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// Dependencies: 
// Revision:1.0
// Revision 0.01 - File Created
// Additional Comments:
//


module fix_to_float_top(
    input   clk,                                                      
    input           s_axis_a_tvalid,       //输入数据有效标志信号
    input   [31:0]  s_axis_a_tdata,        //输入的 定点数 数据
    output m_axis_result_tvalid,           //输出数据有效标志信号
    output  [31:0]  m_axis_result_tdata    //输出的 float 数据

    );
        floating_point_ip u1_floating_point_ip(
            .aclk(clk),
            .s_axis_a_tvalid(s_axis_a_tvalid),
            .s_axis_a_tdata(s_axis_a_tdata),
            .m_axis_result_tvalid(m_axis_result_tvalid),
            .m_axis_result_tdata(m_axis_result_tdata)
        );
  
endmodule

2.仿真代码

建立一个仿真模块,命名为fix_to_float_tb,用来仿真刚才顶层模块例化的IP核。

代码如下:

`timescale 1ns / 1ps
//
// Company: 重庆大学
// Engineer: CLG
// Create Date: 2022/07/22 10:02:05
// Design Name: 
// Module Name: fix_to_float_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// Dependencies: 
// Revision:1.0
// Revision 0.01 - File Created
// Additional Comments:
//


module fix_to_float_tb( );
    reg clk;
    reg a_valid_a = 1'b0;
    reg [31:0] a_a = 32'b0;
    wire [31:0] result_a;

    fix_to_float_top u1_fix_to_float_top(
        .clk(clk),
        .s_axis_a_tdata(a_a),
        .s_axis_a_tvalid(a_valid_a),
        .m_axis_result_tdata(result_a),
        .m_axis_result_tvalid(m_axis_result_tvalid)
    );
    always #5 clk=~clk;
    
    initial begin
       clk  =   1'b0;
        #100;
        a_valid_a <=   1'b1;
        a_a <= 32'h376CF5D0;

        #500;
        a_valid_a <=   1'b1;
        a_a <= 32'hc8930a30;
    end
    
    always @(posedge clk) begin
        if (m_axis_result_tvalid == 1'b1)  begin
            a_valid_a <=   1'b0;
        end      
    end

endmodule

五、仿真分析

        仿真结果如图7所示,对比前面所列举定点数、浮点数的例子,可知该模块成功实现了将定点数转化为浮点数。

图7 仿真结果

六、两种将十进制小数转化为任意位数的二进制有符号定点数的方法

https://download.csdn.net/download/m0_66360845/89567962icon-default.png?t=N7T8https://download.csdn.net/download/m0_66360845/89567962


总结

        本次介绍了定点数、浮点数以及怎么使用vivado中的Floating-point IP核将定点数转化32位浮点数。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐