xilinx FPGA 除法器ip核(divider)的学习和仿真(Vivado)

在设计中,经常出现除法运算,实现方法 :

1、移位操作

2、取模取余

3、调用除法器IP核

4、查找表

简单学习除法器IP。

网上很多IP翻译文档,不详细介绍,记录几个重要的点:

1、三种算法模式(不同模式所消耗的资源类型不同)

2、分清除数和被除数;余数模式的选择

3、延迟输出的周期可配置


除法器IP的关键信号:

可以看到仍然是axis接口,所以在给数据时候,仍遵循tready和tvaild握手则数据有效的原则

给定输入的除数以及被除数有效信号和数据,由于握手,所以只有在输出的对应tready信号准备好,才能给定输入的相关信号

代码如下:

bash 复制代码
`timescale 1ns / 1ps

module DIVIDE_IP(
    input                CLK                         ,
    input                RST                         ,
    output      [15:0]   REMINDER                    ,
    output      [17:0]   QUOEITINR     
    );
    
    reg           r_axis_divisor_tvalid  = 'b0      ;  
    reg  [15:0]   r_axis_divisor_tdata   = 'b0      ;  
    
    reg           r_axis_dividend_tvalid = 'b0     ; 
    reg  [23:0]   r_axis_dividend_tdata  = 'b0     ;
    
    wire [15:0]   s_axis_divisor_tdata             ;
    wire [23:0]   s_axis_dividend_tdata            ;    
    wire [39:0]   m_axis_dout_tdata                ;
    
    assign        s_axis_divisor_tvalid =  r_axis_divisor_tvalid ;
    assign        s_axis_divisor_tdata  =  r_axis_divisor_tdata  ;
    assign        s_axis_dividend_tvalid=  r_axis_dividend_tvalid;
    assign        s_axis_dividend_tdata =  r_axis_dividend_tdata ;
    
    assign        REMINDER              =  m_axis_dout_tdata[15:0]; //余数
    assign        QUOEITINR             =  m_axis_dout_tdata[39:16]; //商
    
   div_gen_0 u_div_gen_0 (
       .aclk                  (CLK                   ),    // input wire aclk
       .s_axis_divisor_tvalid (s_axis_divisor_tvalid ),    // input wire s_axis_divisor_tvalid
       .s_axis_divisor_tready (s_axis_divisor_tready ),    // output wire s_axis_divisor_tready
       .s_axis_divisor_tdata  (s_axis_divisor_tdata  ),    // input wire [15 : 0] s_axis_divisor_tdata
       .s_axis_dividend_tvalid(s_axis_dividend_tvalid),    // input wire s_axis_dividend_tvalid
       .s_axis_dividend_tready(s_axis_dividend_tready),    // output wire s_axis_dividend_tready
       .s_axis_dividend_tdata (s_axis_dividend_tdata ),    // input wire [23 : 0] s_axis_dividend_tdata
       .m_axis_dout_tvalid    (m_axis_dout_tvalid    ),    // output wire m_axis_dout_tvalid
       .m_axis_dout_tdata     (m_axis_dout_tdata     )     // output wire [39 : 0] m_axis_dout_tdata
);

     always @(posedge CLK)
     begin
         if(RST)
         begin
             r_axis_divisor_tvalid     <= 'b0;
             r_axis_divisor_tdata      <= 'd0; 
         end
         else if(s_axis_divisor_tready)
         begin
             r_axis_divisor_tvalid     <= 'b1;
             //r_axis_divisor_tdata      <= r_axis_divisor_tdata + 'd1; //除数
             r_axis_divisor_tdata      <= r_axis_divisor_tdata + 'd4; //除数
         end
         else
         begin
             r_axis_divisor_tvalid     <= 'b0;
             r_axis_divisor_tdata      <= 'd0; 
         end
     end

     always @(posedge CLK)
     begin
         if(RST)
         begin
             r_axis_dividend_tvalid     <= 'b0;
             r_axis_dividend_tdata      <= 'd0; //被除数
         end
         else if(s_axis_dividend_tready)
         begin
             r_axis_dividend_tvalid     <= 'b1;
             r_axis_dividend_tdata      <= r_axis_dividend_tdata + 'd5; //被除数
         end
         else 
         begin
             r_axis_dividend_tvalid     <= 'b0;
             r_axis_dividend_tdata      <= 'd0; //被除数
         end
     end
endmodule

TB:

bash 复制代码
`timescale 1ns / 1ns

module DIVIDE_IP_TB;

    reg         CLK        ;
    reg         RST        ;

    DIVIDE_IP u_DIVIDE_IP(
        .CLK   (CLK       ),
        .RST   (RST       )
    );

    initial                    CLK = 1'b1;
    always    #10              CLK = ~CLK;
    
    initial begin
        RST           = 'b1;
        #100;
        RST           = 'b0;
    end
endmodule

仿真情况:

无余数的情况,可以看到m_axis_dout_tvalid高时,对应的余数都是0

有余数的情况:

出现的问题:

IP输入信号出现高阻态。

如下图所示,给了正确的r_axis_divisor_tvalid、r_axis_divisor_tdata、r_axis_dividend_tvalid、r_axis_dividend_tdata信号,并将其赋值给除法器IP的输入s_axis_divisor_tvalid、s_axis_divisor_tdata、s_axis_dividend_tvalid、s_axis_dividend_tdata。

可以看到tvalid信号正常赋值,tdata却出现高阻态。

原因:赋值时,tvalid位宽1bit,可不定义直接赋值;但等于多bit位宽的tdata来说,赋值assign之前,需要先定义。

bash 复制代码
wire [15:0]   s_axis_divisor_tdata             
wire [23:0]   s_axis_dividend_tdata            

以上简单记录除法器IP的使用方法,后续可应用。比如A / B的操作,若有余数则在商的基础上加1.若没有余数就是商。

这样我们就可以先调用除法器IP,得到商和余数。

判断,当余数==0时,r_tmp = 商,否则r_tmp = 商 + 'b1

相关推荐
外收内放18 小时前
面向对象高级(实战案例)
开发语言·python·学习
九零HTTP19 小时前
10月21号-CSDN配菜-IP池的5个坑
服务器·数据库·tcp/ip
薛定e的猫咪19 小时前
(ICLR 2020)MAML 靠的不是快速学习,而是特征复用
人工智能·深度学习·学习·算法·机器学习
嵌入式软硬件攻城狮19 小时前
9.读写DDR测试
fpga开发
薛定e的猫咪19 小时前
(ICLR 2026)DF-META:面向 FJSP 的无导数元学习实例自适应调度
人工智能·深度学习·学习·算法·机器学习
ITxiaobing202320 小时前
海外广告投放的 IP 定位服务怎么选?一份基于实测数据的选型参考
网络协议·tcp/ip·php
别动我齐刘海1 天前
机器人 C++ / 系统联调补强2——异常处理、Protobuf
linux·c++·人工智能·学习·算法·机器学习·机器人
一直C1 天前
嵌入式 Linux 驱动开发学习笔记:内核定时器、platform 总线与 I²C 驱动
linux·驱动开发·嵌入式硬件·学习·imx6ull
承渊政道1 天前
Linux网络学习【传输层协议UDP】
linux·网络·网络协议·学习·ubuntu·udp
andrsted1 天前
练题簿免费刷题小程序:和学习搭子共用一份题库,一起刷题复习
学习·面试·微信小程序·小程序·学习方法·刷题