Division en virgule flottante complexe de noyau Vivado IP Virgule flottante

Division en virgule flottante complexe de noyau Vivado IP Virgule flottante


avant-propos

        Avec le développement continu du processus de fabrication, le réseau de portes logiques programmables sur le terrain (FPGA) devient de plus en plus intégré et son application devient de plus en plus étendue.Parmi eux, certains IP de traitement mathématique doivent être utilisés lors du traitement des signaux numériques. nucléaire. Récemment, j'étudie l'implémentation matérielle FPGA de la recherche sur la technologie anti-brouillage adaptative de l'espace aérien, qui utilise inévitablement certains cœurs IP.Aujourd'hui, je vais vous présenter comment utiliser le cœur IP à virgule flottante dans vivado pour réaliser une division complexe en virgule flottante.à certains mesure utile.


Astuce : Ce qui suit est le texte de cet article, qui sont tous originaux par l'auteur lui-même. Il n'est pas facile d'écrire un article. J'espère que vous joindrez un lien vers cet article lors de la publication.

1. Exemple de division complexe en virgule flottante

        Afin de faciliter l'analyse des résultats dans la simulation suivante, nous énumérons ici l'exemple de division de nombres à virgule flottante complexe. Pendant la simulation, utilisez directement l'exemple suivant pour la simulation afin de vérifier si le résultat de la simulation est correct.

        exemple : Soit le nombre flottant a=32'h4057AE14+j32'h400F5C29, soit a=3.37+j2.24, le nombre flottant b=32'h3FE51EB8+j32'hC039999A, soit b=1.79-j2 .9, puis a/b= 32'hBD236E2F+32'h3F97E5C9, soit a/b=-0.0399+j1.1867, notez que le résultat ne conserve que quatre décimales.

2. Étapes de configuration du noyau IP à virgule flottante

        Comment configurer l'addition, la soustraction, la multiplication et la division du noyau IP à virgule flottante a été expliqué dans l'article précédent. Les étudiants qui ne le savent pas peuvent lire mon article précédent, donc je ne le répéterai pas ici.

3. Réflexion globale

        Selon la formule \frac{a+bi}{c+di}=\frac{ac+bd+(bc-ad)i}{c^{2}+d^{2}}, nous utilisons d'abord six multiplicateurs parallèles pour calculer les résultats de ac, bd, ad, bc, cc, dd, puis utilisons un soustracteur et deux additionneurs pour calculer bc-ad et ac+bd, cc+dd dans parallèle , et enfin utiliser deux diviseurs pour calculer la somme \frac{ac+bd}{c^2+d^2}en\frac{bc-ad}{c^2+d^2} parallèle . Dans ma configuration de cœur IP, le retard du cœur IP multiplicateur est de 8 horloges, le retard du cœur IP additionneur et soustracteur est de 11 horloges et le retard du cœur IP diviseur est de 28 horloges.Dans le code, un ou deux de plus des horloges sont données au signal de données valides Valid. Dans l'ensemble du code de niveau supérieur, le comptage de cnt est particulièrement important, et les changements de nombreuses variables intermédiaires dépendent de la valeur de cnt. J'ai aussi beaucoup commenté dans le code, et l'idée de conception cette fois n'est pas difficile, je pense que tout le monde peut la comprendre.

4. Simuler

1. Code de niveau supérieur

Créez un module de niveau supérieur nommé float_complex_div .

code afficher comme ci-dessous:

`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. Code de simulation

Créez un module de simulation nommé float_complex_div_tb pour simuler le module de niveau supérieur.

code afficher comme ci-dessous:

`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. Analyse des résultats de la simulation

        Les résultats de la simulation sont présentés sur la figure 1. Par rapport aux exemples de division complexe en virgule flottante mentionnés ci-dessus, on peut voir que le module a réalisé avec succès la division de nombres complexes en virgule flottante. Le résultat est 32'hBD23891A+j32'h3F97E634, soit -0,039925672+j1,1867127. Si quatre décimales sont conservées, il est -0,0399+j1,1867, ce qui est cohérent avec l'exemple présenté au début de cet article.

Figure 1 Résultats de simulation

 


Résumer

Cette fois, nous allons introduire la division des nombres complexes à virgule flottante.

Je suppose que tu aimes

Origine blog.csdn.net/m0_66360845/article/details/125995674
conseillé
Classement