FPGA 的数字信号处理:重写 FIR 逻辑以满足时序要求

这篇具有很好参考价值的文章主要介绍了FPGA 的数字信号处理:重写 FIR 逻辑以满足时序要求。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

fpga 信号处理,fpga开发,信号处理

fpga 信号处理,fpga开发,信号处理

在上一篇文章中(FPGA 的数字信号处理:Verilog 实现简单的 FIR 滤波器)演示了在 Verilog 中编写自定义 FIR 模块的初始demo。该项目在行为仿真中正常,但在布局和布线时未能满足时序要求。

所以今天的文章让我们来看看当设计不能满足时序要求时如何分析并解决它。

fpga 信号处理,fpga开发,信号处理

当在目标 FPGA 芯片中布局和布线时,首先在 Vivado 中确定时序要求.

将 FIR 作为RTL 模块导入到block design中,其中通过AXI DMA 从存储器传输相位增量偏移值的DDS可以输入可变频率正弦曲线,这样就可以演示FIR的行为。

fpga 信号处理,fpga开发,信号处理

在 Vivado 中综合布局布线并打开设计后,会弹出严重警告,告知设计不符合时序要求。

为了能够准确查看设计时序失败的原因,在已完成综合设计的底部窗口包含一个选项卡,用于 Vivado 在综合期间对设计执行的时序分析。当存在时序失败的信号路径时,用户可以过滤此时序分析以仅使用下图中显示的红色圆圈感叹号查看这些违规路径:

fpga 信号处理,fpga开发,信号处理

在这个特定的设计中,有几个信号路径未能达到其分配的时序,这意味着信号的物理距离太远而无法穿过芯片和/或在信号出去之前需要通过太多的逻辑级别。保持时间太长的信号意味着当将其计时到下一级寄存器中时,不能依赖它的值是否有效,从而使其余下游逻辑的行为不可靠/不可预测。

s_axis_fir_tdata在这种情况下,进入 FIR 模块的 AXI Stream 输入接口的数据信号需要很长时间才能到达m_axis_fir_tdata目标寄存器处的输出。要查看比屏幕底部的时序分析窗口中的内容更多的详细信息,右键单击底部时序分析窗口中的违规信号路径,然后选择“查看路径报告(View Path Report)”选项。然后,将能够看到 Vivado 如何计算出该信号的允许建立时间,并与它实际给出的 HDL 设计编写方式进行比较。这会给一些提示,说明是什么导致建立时间延长。然而,我发现要真正可视化保持时序违规比在示意图中查看信号会更直观。

fpga 信号处理,fpga开发,信号处理

要在原理图中打开特定信号路径,再次右键单击底部时序分析窗口中的违规信号路径,然后选择“Schematic”选项。将打开一个新选项卡,显示信号路径在设计的物理布局中经过的逻辑。

在为axis_fir_tdata的数据总线中的一个位打开信号路径时,它揭示了设计在芯片中的布线,从图中可以看出信号必须通过 11 级逻辑串行后才能到达其目的地。

fpga 信号处理,fpga开发,信号处理

既然对已实施设计的分析已经揭示了哪些信号路径是哪个时序违规的问题,现在的问题是我们如何解决它?在这种情况下,很明显需要重新设计当前逻辑,以更并行的方式处理更小的数据块,从而缩短数据到其目标寄存器的总路径。

个人更喜欢在尝试编写任何实际的 Verilog 代码之前绘制出逻辑。当有这种设计执行的操作的可视化表示时,调试设计会容易得多,特别是对于跟踪此类时序违规等问题。

检查当前 FIR 模块的逻辑设计,其中数据总线违反了建立时序,很明显循环缓冲区串行填充然后将所有 15 个数据发送到累加块时,立即求和会产生大量的处理延迟。

fpga 信号处理,fpga开发,信号处理

核心的想法是尝试填充循环缓冲区,将每个缓冲区乘以适当的系数,最后一次性对 15 个算子的每一个求和,但是这次我们考虑重新设计逻辑,让循环缓冲区中仅花费乘法和累加(求和)两个寄存器一个级联的时间。

fpga 信号处理,fpga开发,信号处理

新 FIR 模块的 Verilog 代码:

`timescale 1ns / 1ps

module FIR(
    input clk,
    input reset,
    input signed [15:0] s_axis_fir_tdata, 
    input [3:0] s_axis_fir_tkeep,
    input s_axis_fir_tlast,
    input s_axis_fir_tvalid,
    input m_axis_fir_tready,
    output reg m_axis_fir_tvalid,
    output reg s_axis_fir_tready,
    output reg m_axis_fir_tlast,
    output reg [3:0] m_axis_fir_tkeep,
    output reg signed [31:0] m_axis_fir_tdata
    );

    /* This loop controls tkeep signal on AXI Stream interface */
    always @ (posedge clk)
        begin
            m_axis_fir_tkeep <= 4'hf;
        end
        
    /* This loop controls tlast signal on AXI Stream interface */
    always @ (posedge clk)
        begin
            if (s_axis_fir_tlast == 1'b1)
                begin
                    m_axis_fir_tlast <= 1'b1;
                end
            else
                begin
                    m_axis_fir_tlast <= 1'b0;
                end
        end
    
    // 15-tap FIR 
    reg enable_fir;
    reg signed [15:0] buff0, buff1, buff2, buff3, buff4, buff5, buff6, buff7, buff8, buff9, buff10, buff11, buff12, buff13, buff14;
    wire signed [15:0] tap0, tap1, tap2, tap3, tap4, tap5, tap6, tap7, tap8, tap9, tap10, tap11, tap12, tap13, tap14; 
    reg signed [31:0] acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10, acc11, acc12, acc13, acc14; 

    
    /* Taps for LPF running @ 1MSps */
    assign tap0 = 16'hFC9C;  // twos(-0.0265 * 32768) = 0xFC9C
    assign tap1 = 16'h0000;  // 0
    assign tap2 = 16'h05A5;  // 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5
    assign tap3 = 16'h0000;  // 0
    assign tap4 = 16'hF40C;  // twos(-0.0934 * 32768) = 0xF40C
    assign tap5 = 16'h0000;  // 0
    assign tap6 = 16'h282D;  // 0.3139 * 32768 = 10285.8752 = 10285 = 0x282D
    assign tap7 = 16'h4000;  // 0.5000 * 32768 = 16384 = 0x4000
    assign tap8 = 16'h282D;  // 0.3139 * 32768 = 10285.8752 = 10285 = 0x282D
    assign tap9 = 16'h0000;  // 0
    assign tap10 = 16'hF40C; // twos(-0.0934 * 32768) = 0xF40C
    assign tap11 = 16'h0000; // 0
    assign tap12 = 16'h05A5; // 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5
    assign tap13 = 16'h0000; // 0
    assign tap14 = 16'hFC9C; // twos(-0.0265 * 32768) = 0xFC9C
    
    /* This loop controls tready & tvalid signals on AXI Stream interface */
    always @ (posedge clk)
        begin
            if(reset == 1'b0 || m_axis_fir_tready == 1'b0 || s_axis_fir_tvalid == 1'b0)
                begin
                    enable_fir <= 1'b0;
                    s_axis_fir_tready <= 1'b0;
                    m_axis_fir_tvalid <= 1'b0;
                end
            else
                begin
                    enable_fir <= 1'b1;
                    s_axis_fir_tready <= 1'b1;
                    m_axis_fir_tvalid <= 1'b1;
                end
        end
    
    reg [3:0] cnt;
    reg signed [31:0] acc01, acc012, acc23, acc34, acc45, acc56, acc67, acc78, acc89, acc910, acc1011, acc1112, acc1213;
    
    /* Circular buffer w/ Multiply & Accumulate stages of FIR */
    always @ (posedge clk or posedge reset)
        begin
            if (reset == 1'b0)
                begin
                    m_axis_fir_tdata <= 32'd0;
                end
            else if (enable_fir == 1'b1)
                begin
                    buff0 <= s_axis_fir_tdata;
                    acc0 <= tap0 * buff0;
                    
                    buff1 <= buff0; 
                    acc1 <= tap1 * buff1;  
                    acc01 <= acc0 + acc1;
                         
                    buff2 <= buff1; 
                    acc2 <= tap2 * buff2;
                    acc012 <= acc01 + acc2;
                            
                    buff3 <= buff2; 
                    acc3 <= tap3 * buff3;
                    acc23 <= acc012 + acc3;
                         
                    buff4 <= buff3; 
                    acc4 <= tap4 * buff4;
                    acc34 <= acc23 + acc4;
                         
                    buff5 <= buff4;
                    acc5 <= tap5 * buff5; 
                    acc45 <= acc34 + acc5;
                          
                    buff6 <= buff5; 
                    acc6 <= tap6 * buff6;
                    acc56 <= acc45 + acc6;
                       
                    buff7 <= buff6; 
                    acc7 <= tap7 * buff7;
                    acc67 <= acc56 + acc7;
                          
                    buff8 <= buff7;
                    acc8 <= tap8 * buff8;
                    acc78 <= acc67 + acc8;
                           
                    buff9 <= buff8; 
                    acc9 <= tap9 * buff9;
                    acc89 <= acc78 + acc9;
                          
                    buff10 <= buff9; 
                    acc10 <= tap10 * buff10;
                    acc910 <= acc89 + acc10;
                           
                    buff11 <= buff10; 
                    acc11 <= tap11 * buff11;
                    acc1011 <= acc910 + acc11;
                          
                    buff12 <= buff11; 
                    acc12 <= tap12 * buff12;
                    acc1112 <= acc1011 + acc12;
                          
                    buff13 <= buff12; 
                    acc13 <= tap13 * buff13;
                    acc1213 <= acc1112 + acc13;
                          
                    buff14 <= buff13; 
                    acc14 <= tap14 * buff14;
                    m_axis_fir_tdata <= acc1213 + acc14;
                    
                end
        end
    
endmodule

使用新 FIR 模块的 Verilog 代码重新运行综合布局布线后就可以产生满足所有时序要求的设计。打开之前违反建立时序的相同数据信号路径的原理图,可以直观地证明信号路径是如何整体缩短的。

新原理图显示axis_fir_tdata总线中每个位的信号路径都被并行处理,有效地缩短了它们到达目标寄存器的时间,这就是减少信号建立时间的原因。

fpga 信号处理,fpga开发,信号处理

当新设计满足时序要求时,接下来就是验证重写后的逻辑是否仍然与旧逻辑一样。重新运行行为仿真将很快回答这个问题。

由于希望用新代码替换之前的逻辑,发现设置断点并在更新波形图时单步执行 Verilog 的每一行的功能可以实现我们的目的。

启动行为仿真后,会注意到 HDL 的每条有效行的行号右侧都有一个红色圆圈。单击这些红色圆圈之一将启用该行上的断点。

fpga 信号处理,fpga开发,信号处理

当仿真运行并遇到该断点时,可以使用顶部工具栏中的“步进”按钮(如下所示)或 F8 来逐步执行剩余的代码行。

fpga 信号处理,fpga开发,信号处理

最后,我们看到 FIR 滤波器的新逻辑设计确实按预期运行!

fpga 信号处理,fpga开发,信号处理

总结

上面的两个例子能证明在目标 FPGA 芯片上,最终输出相同结果的两种不同的 HDL 编写方式对时序影响不同的重要性。这就是为什么在编写代码脑中“有电路”是很重要的原因。

一本Verilog HDL代码对应电路的书,助你快速编写可综合模型
文章来源地址https://www.toymoban.com/news/detail-708060.html

到了这里,关于FPGA 的数字信号处理:重写 FIR 逻辑以满足时序要求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数字信号处理翻转课堂笔记17——窗函数法设计FIR滤波器及matlab实现

    对应教材:《数字信号处理(第五版)》西安电子科技大学出版社,丁玉美、高西全著 (1)窗函数法设计FIR线性相位滤波器的原理; (2)加窗效应:加窗对滤波器特性的影响(难点); (3)典型窗函数及其主要特性和参数(重点); (4)窗函数法设计FIR滤波器的步骤(

    2024年01月16日
    浏览(53)
  • 数字信号处理----数字上变频和下变频都FPGA实现

    数字上变频器(DUC)和数字下变频器(DDC)广泛应用于通信系统,用于信号采样速率的转换。当信号从基带转换至中频( IF )带,需要使用数字上变频器。而数字下变频器是用于将信号从中频( IF )带转换为基带。DUC和DDC通常包括使用混频器进行频率转换,此外还有采样率

    2024年01月16日
    浏览(57)
  • FPGA与LVDS:数字信号处理的完美组合

    FPGA与LVDS:数字信号处理的完美组合 FPGA(Field-Programmable Gate Array)是一种可编程逻辑器件,具有高度灵活性和可重构性,可实现各种数字逻辑和处理功能。而LVDS(Low-Voltage Differential Signaling)则是一种用于高速数据传输的技术,特点是传输距离长、抗干扰能力强、带宽大。

    2024年01月23日
    浏览(52)
  • 数字信号处理-11-FPGA FFT IP应用实例

    本文根据FFT相关原理进行设计构建工程,仿造前文的工程构建的混频功能的工程,设计工程显示该混频信号的功率谱,然后进行仿真分析。 本文不再针对FFT的原理进行过多赘述,提供一份简单的matlab仿真代码。根据仿真简述下FFT的相关使用注意事项。 代码设计,模拟生成了

    2024年02月02日
    浏览(44)
  • 《FPGA数字信号处理》基于FPGA的32点并行FFT/IFFT设计

    本人FPGA小白,只关注FPGA具体功能实现。如以下描述有误,望评论区指正!以下内容,纯手打,严禁未经过同意擅自转载,谢谢! 相比于基2算法,基4算法对本设计(32点FFT)运算的复杂度并没有显著的降低。 基2按时间抽取的FFT蝶形运算如下图所示: 可以发现输入端与输出端

    2024年04月23日
    浏览(49)
  • 【Matlab】音频信号分析及FIR滤波处理——凯泽(Kaiser)窗

    1.1 课题内容: 利用麦克风采集语音信号(人的声音、或乐器声乐),人为加上环境噪声(窄带) 分析上述声音信号的频谱,比较两种情况下的差异 根据信号的频谱分布,选取合适的滤波器指标(频率指标、衰减指标),设计对应的 FIR 滤波器 实现数字滤波,将滤波前、后的声

    2024年02月21日
    浏览(43)
  • 【FPGA数据采集测试系统】——基于FPGA的通用数据采集测试系统是当今数字电路领域最热门的研究课题之一。它不仅可以用于数字信号处理,而且也被广泛应用于音频、视...

    【FPGA数据采集测试系统】——基于FPGA的通用数据采集测试系统是当今数字电路领域最热门的研究课题之一。它不仅可以用于数字信号处理,而且也被广泛应用于音频、视频以及其他多媒体领域。 此外,基于FPGA的数据采集测试系统还可以用于传感器接口、机器视觉、自动控制

    2024年02月09日
    浏览(47)
  • 数字信号处理、语音信号处理、现代信号处理

    推荐他的博客: 手撕《数字信号处理》——通俗易懂的数字信号处理章节详解集合 手撕《语音信号处理》——通俗易懂的语音信号处理章节详解集合 手撕《现代信号处理》——通俗易懂的现代信号处理章节详解集合

    2024年02月08日
    浏览(69)
  • 数字信号处理8:利用Python进行数字信号处理基础

    我前两天买了本MATLAB信号处理,但是很无语,感觉自己对MATLAB的语法很陌生,看了半天也觉得自己写不出来,所以就对着MATLAB自己去写用Python进行的数字信号处理基础,我写了两天左右,基本上把matlab书上的代码全部用Python实现了,所以,今天贴的代码和图有些多, 要用到的

    2024年02月13日
    浏览(41)
  • FPGA 音频信号处理

    第八届集创赛杯赛题目——紫光同创杯 - 全国大学生集成电路创新创业大赛 题目任务要求:采集信号、降噪、识别、视频展示。 硬件:麦克风、扬声器、FPGA(盘古50)、HDMI显示器 软件:紫光同创PDS(用于部署)、anaconda、jupyter(用于部署训练网络) 1.麦克风采集好数据经过

    2024年03月14日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包