Vivado IP core complex floating-point division Floating-point

Vivado IP core complex floating-point division Floating-point


foreword

        With the continuous development of the manufacturing process, the field programmable logic gate array (FPGA) is becoming more and more integrated, and its application is becoming more and more extensive. Among them, some mathematical processing IP must be used when processing digital signals. nuclear. Recently, I am studying the FPGA hardware implementation of airspace adaptive anti-jamming technology research, which inevitably uses some IP cores. Today I will introduce how to use the Floating-point IP core in vivado to realize complex floating-point division . to some extent helpful.


Tip: The following is the text of this article, all of which are original by the author himself. It is not easy to write an article. I hope you will attach a link to this article when reposting.

1. Example of complex floating-point division

        In order to facilitate the analysis of the results in the following simulations, here we list an example of the division of complex floating-point numbers. When simulating, directly use the following examples to perform simulations to verify whether the simulation results are correct.

        example : Let the floating point number a=32'h4057AE14+j32'h400F5C29, that is, a=3.37+j2.24, the floating point number b=32'h3FE51EB8+j32'hC039999A, that is, b=1.79-j2.9, then a/b= 32'hBD236E2F+32'h3F97E5C9, namely a/b=-0.0399+j1.1867, note that the result only retains four decimal places.

2. Floating-point IP core configuration steps

        How to configure the addition, subtraction, multiplication and division of the Floating-point IP core has been explained in the previous article. Students who don’t know it can read my previous article, so I won’t go into details here.

3. Overall thinking

        According to the formula \frac{a+bi}{c+di}=\frac{ac+bd+(bc-ad)i}{c^{2}+d^{2}}, we first use six parallel multipliers to calculate the results of ac, bd, ad, bc, cc, dd, and then use a subtractor and two adders to calculate bc-ad and ac+bd, cc+dd in parallel , and finally use two dividers to calculate the sum \frac{ac+bd}{c^2+d^2}in\frac{bc-ad}{c^2+d^2} parallel . In my IP core configuration, the delay of the multiplier IP core is 8 clocks, the delay of the adder and subtractor IP core is 11 clocks, and the delay of the divider IP core is 28 clocks. In the code, one or two more clocks are given to the data valid signal Valid. In the entire top-level code, counting cnt is particularly important, and the changes of many intermediate variables depend on the value of cnt. I also commented a lot in the code, and the design idea this time is not difficult, I believe everyone can understand it.

4. Simulation

1. Top-level code

Create a top-level module named float_complex_div .

code show as below:

`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. Simulation code

Create a simulation module named float_complex_div_tb to simulate the top-level module.

code show as below:

`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

5. Simulation result analysis

        The simulation results are shown in Figure 1. Compared with the examples of complex floating-point division mentioned above, it can be seen that the module has successfully realized the division of complex floating-point numbers. The result is 32'hBD23891A+j32'h3F97E634, which is -0.039925672+j1.1867127. If four decimal places are kept, it is -0.0399+j1.1867, which is consistent with the example introduced at the beginning of this article.

Figure 1 Simulation results

 


Summarize

This time we will introduce the division of complex floating-point numbers.

Guess you like

Origin blog.csdn.net/m0_66360845/article/details/125995674