XILINX FFT IP核使用IFFT,并实现流水线计算IFFT

最近在学习宽带数字接收机的一些东西,其中多相滤波是属于其中比较关键的一环,笔者在matlab上成功仿真了多相滤波这一环节后,便想着在FPGA上实现多相滤波,多相滤波的最后一个环节是IFFT运算,在vivado上实现IFFT还是比较简单的,使用FFT IP核的config通道配置为IFFT模式即可,但在具体运算上,还是有一些细节需要考虑,比如IFFT运算的实时性,吞吐量。
ADC采集的数据是流模式,不间断的,所以在进行IFFT运算时,便需要考虑使用FFT IP核的流水线结构,以实现数据的实时计算,如果使用非实时模式,且不采用流水线结构,因FFT计算的延迟过大,数据缓存存在极大压力,所以在本文中,笔者使用FFT的流水线架构,实时模式,实现IFFT计算。
FFT IP配置如下图所示,本文中采用32点FFT,也即经过配置后,32点IFFT。

在这里插入图片描述
在这里插入图片描述

在进行IFFT的使用时,笔者发现了一个问题,在实时模式下,FFT ip核的数据通道的s_axis_tdata_ready信号会出现拉低情况,并固定出现在数据开始传输之后的几个周期内,如下图所示,此时IFFT的配置也尚未完成
在这里插入图片描述
笔者一开始以为是没有勾选FFT IP核的复位配置,在添加了复位控制后其仍然出现这类情况。
那么如何解决这个问题,因为AXI_STREAM协议是在tready和tvalid信号同时为高时才缓存当前数据,如果不解决这个问题,必然会对IFFT运算结果产生影响,故可以在IFFT运算与数据输入之间,添加一级FIFO缓存,当tready信号为高时才进行数据的传输,这样就可以保证每一个数据成功缓存,而为了保证tvalid与当前时刻的tready信号同步为高,对于FIFO的读数据模式选择First Word Fall Through模式,即将最先写入的数据,直接放在输出端口上,此时的读延迟为0
在这里插入图片描述
同时,对于FIFO的读控制也使用组合逻辑,保证没有周期延迟,即当tready信号为高且fifo的empty信号不为1时进行FIFO的读使能,修改逻辑后的仿真如下。
在这里插入图片描述
可以看出,成功实现了数据的不丢失写入,接下来进行IFFT运算结果的查看
笔者是传输了1~32这32个数据进行第一次IFFT运算,同样在matlab中,进行这32点数据的IFFT运算,并且需要注意的是vivado的IFFT运算结果需要除以运算点数才是真实的运算结果,可以直接在代码中将运算结果进行移位即可,需要注意有符号数据的移位要考虑符号位的保持,在本文中,直接在MATLAB的运算结果上乘以32,进行数据查看。对于有符号数据,二进制补码的移位,笔者会在以后的文章中进行详细介绍。
在这里插入图片描述
在这里插入图片描述
还需要注意一点,在实际仿真中发现,如果FFT IP核添加了复位逻辑,在进行IFFT运算时,会出现运算结果的虚部与实际结果呈相反数的情况,目前只能将复位关闭,未能找到其他的解决办法。如果有同学知道如何解决这一问题,欢迎在评论区进行指正。
verilog代码如下

module ifft_test(
    input               i_clk       ,
    input               i_rst       ,
    input   [11:0]      i_data      ,
    input               i_valid     ,
    output              o_active    
    );

reg     [7 :0]          s_axis_config_tdata         ;
reg                     s_axis_config_tvalid        ;
wire                    s_axis_config_tready        ;
wire    [47:0]          m_axis_data_tdata           ;
wire                    m_axis_data_tvalid          ;
wire                    m_axis_data_tlast           ;
wire                    s_axis_data_tready          ;
wire                    event_frame_started         ;
wire                    event_tlast_unexpected      ;
wire                    event_tlast_missing         ;
wire                    event_data_in_channel_halt  ;
wire                    w_config_activate           ;
wire    signed[17:0]    w_ifft_re                   ;
wire    signed[17:0]    w_ifft_im                   ;
wire                    w_fifo_rd_en                ;
wire    [11:0]          w_fifo_dout                 ;
wire                    w_fifo_full                 ;
wire                    w_fifo_empty                ;
wire                    s_axis_data_tvalid          ;

FIFO_12X64 FIFO_12X64_U0 (
    .clk                            (i_clk                      ),
    .din                            (i_data                     ),
    .wr_en                          (i_valid                    ),
    .rd_en                          (w_fifo_rd_en               ),
    .dout                           (w_fifo_dout                ), 
    .full                           (w_fifo_full                ),
    .empty                          (w_fifo_empty               )
);

ifft_32 ifft_32_u0 (
    .aclk                           (i_clk                      ),
    // .aresetn                        (~i_rst                     ), 
    .s_axis_config_tdata            (s_axis_config_tdata        ),
    .s_axis_config_tvalid           (s_axis_config_tvalid       ),
    .s_axis_config_tready           (s_axis_config_tready       ),
    .s_axis_data_tdata              ({4'd0,12'd0,4'd0,w_fifo_dout}),
    .s_axis_data_tvalid             (s_axis_data_tvalid         ),
    .s_axis_data_tready             (s_axis_data_tready         ),
    .s_axis_data_tlast              (0),
    .m_axis_data_tdata              (m_axis_data_tdata          ),
    .m_axis_data_tvalid             (m_axis_data_tvalid         ),
    .m_axis_data_tlast              (m_axis_data_tlast          ),
    .event_frame_started            (event_frame_started        ),
    .event_tlast_unexpected         (event_tlast_unexpected     ),
    .event_tlast_missing            (event_tlast_missing        ),
    .event_data_in_channel_halt     (event_data_in_channel_halt )
);

assign  w_ifft_re = m_axis_data_tdata[17 :0]        ;
assign  w_ifft_im = m_axis_data_tdata[41:24]        ;
assign  w_config_activate = s_axis_config_tvalid & s_axis_config_tready;
assign  w_fifo_rd_en = s_axis_data_tready & !w_fifo_empty;
assign  o_active = w_config_activate;
assign  s_axis_data_tvalid = w_fifo_rd_en;

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        s_axis_config_tdata <= 'd0;
    else
        s_axis_config_tdata <= 'd0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        s_axis_config_tvalid <= 'b1;
    else if(s_axis_config_tvalid & s_axis_config_tready)
        s_axis_config_tvalid <= 'b0;
    else
        s_axis_config_tvalid <= s_axis_config_tvalid;
end

endmodule

整体来说,这个功能实现起来还是比较简单的,笔者也是个萌新,在学习过程中探索,如果有什么问题,欢迎大家在评论区批评指正。

如果觉得笔者的文章对您有些帮助,希望点个赞,激励下笔者的创作,不胜感激!

关于本文的完整matlab代码与vivado工程,可以私信博主免费领取!!!

### 回答1: Vivado是Xilinx公司的一款集成电路设计工具,用于快速实现数字电路设计。IFFT是Inverse Fast Fourier Transform的缩写,即快速傅里叶逆变换。 Vivado提供了IFFT作为其库中的一个模块,用于在FPGA实现快速傅里叶逆变换功能。IFFT通过接收频域中的复数数据,然后对其进行逆变换,将其变换为时域信号。 IFFT的设计主要包括如下几个部分:输入/输出接口、数据缓存、蝶形计算单元和控制逻辑。输入/输出接口用于和其他模块进行数据的输入和输出。数据缓存用于存储输入信号的频域数据,且提供给蝶形计算单元进行计算。蝶形计算单元是IFFT算法的心部分,通过执行一系列复数运算来实现逆变换。控制逻辑用于控制整个的工作流程和时序。 Vivado的IFFT可以通过使用IP(Intellectual Property) Catalog来进行快速的设计和集成。用户可以在IP Catalog中找到IFFT且将其添加到设计中。然后,可以根据实际需求配置IFFT的参数,如数据宽度、FFT点数等。最后,将实例化连接到其他设计模块中,完成FFT功能的实现。 Vivado提供了高度可定制的IFFT,可以根据具体的应用需求进行优化和修改。用户可以对进行参数调整、算法优化和时序约束等操作,以达到性能和功耗的平衡。 总而言之,Vivado提供了IFFT以帮助设计工程师在FPGA中快速实现傅里叶逆变换功能。通过使用Vivado提供的IP Catalog,设计人员可以方便地集成IFFT根据需求进行配置和优化,从而实现高性能和低功耗的FFT功能。 ### 回答2: Vivado IFFT 是一种在 Vivado 高级综合 (HLS) 工具中使用的模块,用于实现离散傅里叶逆变换 (IFFT)。IFFT 是离散傅里叶变换 (DFT) 的逆过程,将频域信号恢复为时域信号。 Vivado IFFT 的主要功能是接收一个输入频域信号,运算后输出对应的时域信号。它可用于信号处理和通信系统中的频率域信号重建。 Vivado IFFT 实现基于硬件描述语言 (HDL),可以使用 C/C++ 进行高级综合进行设计和调试。通过 HLS, 设计人员可以更快地实现和验证 IFFT 的功能,进行优化研究。 Vivado IFFT 的设计通常包括以下步骤: 1. 创建所需的输入和输出端口。 2. 根据要求设置 IFFT 长度、精度和其他参数。 3. 编写适当的 HLS 代码,描述 IFFT 算法的实现。 4. 运行综合和优化流程,将 HLS 代码转换为硬件描述语言(如 Verilog 或 VHDL)。 5. 将生成的 HDL 文件集成到 Vivado 工程中。 6. 进行综合、布局和布线,生成最终的位流文件。 7. 将位流文件加载到 FPGA 中进行验证和测试。 通过使用 Vivado IFFT ,设计人员可以更高效地实现复杂的信号处理算法,从而提高系统性能,加快设计时间。同时,结合 Vivado 的其他功能,如 IP 集成和调试,设计人员可以更好地优化和验证设计。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值