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

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

目录

前言

一、复数浮点数乘法示例

二、Floating-point IP核配置步骤

三、整体思路

四、仿真

1.顶层代码

2.仿真代码

五、仿真结果分析

总结


前言

         随着制造工艺的不断发展,现场可编程逻辑门阵列(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'h414873EB+32'hC0B86DC6,即a*b=12.5283-j5.7634,该结果是用matlab算的。

二、Floating-point IP核配置步骤

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

三、整体思路

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

四、仿真

1.顶层代码

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

代码如下:

`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// Create Date: 2022/07/24 15:15:43
// Design Name: 
// Module Name: float_complex_mul
// 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+(ad+bc)i

module float_complex_mul(
    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 [4:0] cnt;               //过程计数标志
    reg valid1;                  //乘有效信号 
    reg valid2;                  //加减有效信号 
    
    //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
    always @(posedge clk or negedge rst_n)
        if(!rst_n)
            cnt<=0;
        else if(start==1)
            begin
                if(cnt<5'd27)    
                    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(5'd0<cnt<=5'd9)
            valid1<=1;
        else
            valid1<=0;
    
    always @(posedge clk or negedge rst_n)
        if(!rst_n)  
               valid2<=0;
           else if(5'd12<cnt<=5'd24)
               valid2<=1;
           else
               valid2<=0; 
    always @(posedge clk or negedge rst_n)
         if(!rst_n)  
            begin over<=0;re_res<=0;im_res<=0; end
         else if(cnt==5'd26)
            begin  over<=1;re_res<=result5;im_res<=result6;  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_sub_ip u1_float_sub_ip(                    //减法器   计算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(result5)
              );     
    float_add_ip u1_float_add_ip(                  //加法器   计算ad+bc
                .aclk(clk),
                .s_axis_a_tvalid(valid2),
                .s_axis_a_tdata(result3),
                .s_axis_b_tvalid(valid2),
                .s_axis_b_tdata(result4),
                .m_axis_result_tvalid(),
                .m_axis_result_tdata(result6)
              );
              
endmodule

2.仿真代码

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

代码如下:

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

module float_complex_mul_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_mul u1_float_complex_mul(  //例化顶层模块
    .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; 
#270   start=1'b0;
      
end

endmodule

五、仿真结果分析

仿真结果如图1所示,对比前面所列举复数浮点数乘法的例子,可知该模块成功实现了复数浮点数的乘法。结果最后一位十六进制数与前面用matlab算的差1,这在能接受的范围之内,可见,用FPGA计算误差也可达到非常小。

图1 仿真结果


总结

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

猜你喜欢

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