Vivado IP核之复数浮点数除法 Floating-point

Vivado IP核之复数浮点数除法 Floating-point


前言

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


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

一、复数浮点数除法示例

        为了后面仿真便于分析结果,在此我们就列举复数浮点数除法的例子,仿真时直接用下面的例子进行仿真,来验证仿真结果是否正确。

        example:设浮点数a=32'h4057AE14+j32'h400F5C29,即a=3.37+j2.24,浮点数b=32'h3FE51EB8+j32'hC039999A,即b=1.79-j2.9,则a/b=32'hBD236E2F+32'h3F97E5C9,即a/b=-0.0399+j1.1867,注意该结果只保留了四位小数。

二、Floating-point IP核配置步骤

        关于Floating-point IP核的加减乘除如何配置在前面的文章都已经讲解过,不会的同学看我前面的文章,此处不再赘述。

三、整体思路

        根据公式\frac{a+bi}{c+di}=\frac{ac+bd+(bc-ad)i}{c^{2}+d^{2}}我们先用六个并行乘法器计算ac,bd,ad,bc,cc,dd的结果,然后再用一个减法器和两个加法器并行计算bc-ad和ac+bd、cc+dd,最后再用两个除法器并行计算\frac{ac+bd}{c^2+d^2}\frac{bc-ad}{c^2+d^2}即可。在我的IP核配置中,乘法器IP核延时为8个时钟,加法器与减法器IP核延时为11个时钟,除法器IP核延时为28个时钟,为了确保万无一失,在我的代码中,对于数据有效信号Valid多给了一两个时钟。整个顶层代码中,计数cnt尤为重要,很多中间变量的变化都取决于cnt的数值。代码中我注释的地方也比较多,本次设计思路也不难,相信大家能看懂的。

四、仿真

1.顶层代码

建立一个顶层模块,命名为float_complex_div

代码如下:

`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// Create Date: 2022/07/26 12:30:21
// Design Name: 
// Module Name: float_complex_div
// Project Name: 
// Target Devices: 
// Tool Versions: 2017.4
// Description: 
// Dependencies: 
// Revision:1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//计算公式: (a+bi)/(c+di)=( ac+bd+(bc-ad)i )/(c^2+b^2)

module float_complex_div(
    input clk,                // 输入时钟信号        
    input rst_n,              //输入复位信号
    input start,              //输入开始信号
    input [31:0] re_a,        //输入被除数a的实部
    input [31:0] im_a,        //输入被除数a的虚部
    input [31:0] re_b,        //输入除数b的实部
    input [31:0] im_b,        //输入除数b的虚部
    output reg over,          //输出计算完成信号
    output reg [31:0] re_res, //输出计算结果的实部
    output reg [31:0] im_res  //输出计算结果的虚部
    );
    //reg define
    reg [5:0] cnt;            //过程计数标志
    reg valid1;               //乘有效信号 
    reg valid2;               //加减有效信号 
    reg valid3;               //除有效信号
    
    //wire define
    wire [31:0] result1;      //结果1
    wire [31:0] result2;      //结果2
    wire [31:0] result3;      //结果3
    wire [31:0] result4;      //结果4
    wire [31:0] result5;      //结果5
    wire [31:0] result6;      //结果6
    wire [31:0] result7;      //结果7
    wire [31:0] result8;      //结果8
    wire [31:0] result9;      //结果9
    wire [31:0] result10;     //结果10
    wire [31:0] result11;     //结果11

    always @(posedge clk or negedge rst_n)
        if(!rst_n)
            cnt<=0;
        else if(start==1)
            begin
                if(cnt<6'd56)    
                    cnt<=cnt+1;
                else
                    cnt<=0;
            end
        else if(start==0)
            cnt<=0;

    always @(posedge clk or negedge rst_n) 
        if(!rst_n)  
            valid1<=0;
        else if(6'd0<cnt<=6'd9)
            valid1<=1;
        else
            valid1<=0;
    
    always @(posedge clk or negedge rst_n)
        if(!rst_n)  
               valid2<=0;
           else if(6'd12<cnt<=6'd24)
               valid2<=1;
           else
               valid2<=0; 
               
    always @(posedge clk or negedge rst_n)
            if(!rst_n)  
                 valid3<=0;
            else if(6'd24<cnt<=6'd53)
                 valid3<=1;
            else
                 valid3<=0;
                 
    always @(posedge clk or negedge rst_n)
         if(!rst_n)  
            begin over<=0;re_res<=0;im_res<=0; end
         else if(cnt==6'd55)
            begin  over<=1;re_res<=result10;im_res<=result11;  end
         else
            begin over<=0;re_res<=0;im_res<=0; end
        
    float_mul_ip u1_float_mul_ip(                       //乘法器1    计算ac
                   .aclk(clk),
                   .s_axis_a_tvalid(valid1),
                   .s_axis_a_tdata(re_a),
                   .s_axis_b_tvalid(valid1),
                   .s_axis_b_tdata(re_b),
                   .m_axis_result_tvalid(),
                   .m_axis_result_tdata(result1)
               );
    float_mul_ip u2_float_mul_ip(                       //乘法器2    计算bd
                   .aclk(clk),
                   .s_axis_a_tvalid(valid1),
                   .s_axis_a_tdata(im_a),
                   .s_axis_b_tvalid(valid1),
                   .s_axis_b_tdata(im_b),
                   .m_axis_result_tvalid(),
                   .m_axis_result_tdata(result2)
               );
    float_mul_ip u3_float_mul_ip(                       //乘法器3    计算ad
                   .aclk(clk),
                   .s_axis_a_tvalid(valid1),
                   .s_axis_a_tdata(re_a),
                   .s_axis_b_tvalid(valid1),
                   .s_axis_b_tdata(im_b),
                   .m_axis_result_tvalid(),
                   .m_axis_result_tdata(result3)
               );  
    float_mul_ip u4_float_mul_ip(                       //乘法器4    计算bc
                  .aclk(clk),
                  .s_axis_a_tvalid(valid1),
                  .s_axis_a_tdata(im_a),
                  .s_axis_b_tvalid(valid1),
                  .s_axis_b_tdata(re_b),
                  .m_axis_result_tvalid(),
                  .m_axis_result_tdata(result4)
              );   
              
    float_mul_ip u5_float_mul_ip(                       //乘法器5    计算c*c
                 .aclk(clk),
                 .s_axis_a_tvalid(valid1),
                 .s_axis_a_tdata(re_b),
                 .s_axis_b_tvalid(valid1),
                 .s_axis_b_tdata(re_b),
                 .m_axis_result_tvalid(),
                 .m_axis_result_tdata(result5)
            );    
    float_mul_ip u6_float_mul_ip(                       //乘法器6    计算d*d
                .aclk(clk),
                .s_axis_a_tvalid(valid1),
                .s_axis_a_tdata(im_b),
                 .s_axis_b_tvalid(valid1),
                 .s_axis_b_tdata(im_b),
                 .m_axis_result_tvalid(),
                 .m_axis_result_tdata(result6)
            );                          
              
    float_sub_ip u1_float_sub_ip(                    //减法器   计算bc-ad
                .aclk(clk),
                .s_axis_a_tvalid(valid2),
                .s_axis_a_tdata(result4),
                .s_axis_b_tvalid(valid2),
                .s_axis_b_tdata(result3),
                .m_axis_result_tvalid(),
                .m_axis_result_tdata(result7)
              );     
    float_add_ip u1_float_add_ip(                  //加法器1  计算ac+bd
                .aclk(clk),
                .s_axis_a_tvalid(valid2),
                .s_axis_a_tdata(result1),
                .s_axis_b_tvalid(valid2),
                .s_axis_b_tdata(result2),
                .m_axis_result_tvalid(),
                .m_axis_result_tdata(result8)
              );
    float_add_ip u2_float_add_ip(                  //加法器2   计算cc+dd
               .aclk(clk),
               .s_axis_a_tvalid(valid2),
               .s_axis_a_tdata(result5),
               .s_axis_b_tvalid(valid2),
               .s_axis_b_tdata(result6),
               .m_axis_result_tvalid(),
               .m_axis_result_tdata(result9)
          );                
    float_div_ip u1_float_div_ip(                  //除法器1   计算(ac+bd)/(cc+dd)
              .aclk(clk),
              .s_axis_a_tvalid(valid3),
              .s_axis_a_tdata(result8),
              .s_axis_b_tvalid(valid3),
              .s_axis_b_tdata(result9),
              .m_axis_result_tvalid(),
              .m_axis_result_tdata(result10)
                );  
    float_div_ip u2_float_div_ip(                  //除法器2   计算(bc-ad)/(cc+dd)
              .aclk(clk),
              .s_axis_a_tvalid(valid3),
              .s_axis_a_tdata(result7),
              .s_axis_b_tvalid(valid3),
              .s_axis_b_tdata(result9),
               .m_axis_result_tvalid(),
               .m_axis_result_tdata(result11)
          );     
    
endmodule

2.仿真代码

建立一个仿真模块,命名为float_complex_div_tb,用来仿真顶层模块。

代码如下:

`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// Create Date: 2022/07/26 13:32:30
// Design Name: 
// Module Name: float_complex_div_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 2017.4
// Description: 
// Dependencies: 
// Revision:1.0
// Revision 0.01 - File Created
// Additional Comments:
//

module float_complex_div_tb();
    reg clk;             // 输入时钟信号        
    reg rst_n;           //输入复位信号
    reg start;           //输入开始信号
    reg [31:0] re_a;     //输入因数a的实部
    reg [31:0] im_a;     //输入因数a的虚部
    reg [31:0] re_b;     //输入因数b的实部
    reg [31:0] im_b;     //输入因数b的虚部
    wire over;           //输出计算完成信号
    wire [31:0] re_res;  //输出计算结果的实部
    wire [31:0] im_res;  //输出计算结果的虚部

float_complex_div u1_float_complex_div(  //例化顶层模块
    .clk(clk),
    .rst_n(rst_n),
    .start(start),
    .re_a(re_a),
    .im_a(im_a),
    .re_b(re_b),
    .im_b(im_b),
    .over(over),
    .re_res(re_res),
    .im_res(im_res)
);
always #5 clk=~clk;
initial begin
    clk=1'b0;rst_n=1'b1;start=1'b0;
#5;     rst_n=1'b0;
#10;     rst_n=1'b1;
            start=1'b1;
            re_a=32'h4057ae14;
            im_a=32'h400f5c29;   
            re_b=32'h3fe51eb8;
            im_b=32'hc039999a; 
#560    start=1'b0;
      
end

endmodule

五、仿真结果分析

        仿真结果如图1所示,对比前面所列举复数浮点数除法的例子,可知该模块成功实现了复数浮点数的除法。该结果为32'hBD23891A+j32'h3F97E634,即-0.039925672+j1.1867127,如果保留四位小数就为-0.0399+j1.1867,这与本文开始介绍的例子是符合的。

图1 仿真结果

总结

本次介绍了复数浮点数的除法。

猜你喜欢

转载自blog.csdn.net/m0_66360845/article/details/125995674