1、背景
前一阵子,一位工程师基于某国产 FPGA,在其 EDA 工具上调用了 DSP 模块 IP,实现了一个由多个 DSP 模块级联组成的带符号定点运算功能,并进行测试验证。
该工程师在写完代码后,在 Questasim 上通过了 RTL 仿真,查看了时序分析,并最后上板测试无误(注意,此时的所有操作都是正常情况下进行的),至此就将工程提交至其它同事。但在后续工作中,收到了来自同事的消息:烧录了该工程的开发板未通过在低温、低压下的测试。
随后,作者作为协助者,将这件事情完整地描述出来了。
2、具体细节
我们先来看一下具体细节!
2.1、顶层控制
1、为了确保代码可适配性,使用了 IP 核产生内部时钟和复位信号。内部时钟信号来源于 OSC 输出。
2、同步释放、异步复位。
3、使用 Clk、rst_N_d2 对有符号定点数级联运算模块进行控制。
2.2、运算实现
这部分的内容对应于上文截图中的 dsp_mult 模块,用于实现运算。
- 其中:
- D_L[17:0]=D_U[17:0],即 D_L 和 D_U 的数据输入是一样的,这个是在 IP 输入接口完成的。
- 在同一个 DSP 模块中,输入 C_L、A_L 可以连接到级联输出 C_L_CAS_OUT、A_L_CAS_OUT,而 C_L_CAS_OUT、A_L_CAS_OUT 可以连接到输入 C_U、A_U。同理,输入 C_U、A_U 也可以连接到级联输出 C_U_CAS_OUT、A_U_CAS_OUT。
- 在相邻的两个 DSP 模块中,把第一个 DSP 的输级联输出 C_U_CAS_OUT、A_U_CAS_OUT,直接连接到第二个 DSP 的输入 C_L、A_L 上,即可达到级联的目的。
- 为了使输入数据对其,输入 C_L、A_L、C_U、A_U 到级联输出 C_L_CAS_OUT、A_L_CAS_OUT、C_U_CAS_OUT、A_U_CAS_OUT 过程,以及级联输出 C_U_CAS_OUT、A_U_CAS_OUT 到 C_L、A_L 的过程,均没有开启寄存器。否则,这是一个 FIR 滤波器,必须要给 D、U 打节拍进行数据对齐才能确保各个 DSP 的输出与预期相符,而且随着级联数越多,所需寄存器就越多。
- 基于上述,完成了多个 DSP 级联的带符号的定点数计算:R[55:0] = 2 * ( C[17:0] + D[17:0] ) x A[17:0] + U[55:0]。且每个 DSP 的输入、输出都是一样的。
3、复现、解决与反思
3.1、复现与分析
1、遇到 Bug 第一步,按照反馈过来的结果,工程师使用对方寄过来的开发板,下载该工程,进行低温低压下的现象复现。果然,问题复现了。 2、随后将代码中的时钟源由内部 OSC 输出改为外部时钟引脚输入,低温、低压下,上板测试通过。由于内部 OSC 时钟频率远高于外部时钟引脚输入的时钟频率,因此,有些怀疑可能是由于时钟频率过高造成的。 3、基于 2 的怀疑,使用 PLL 将外部时钟输入分别分频至多个不同的时钟频率,进而驱动 DSP 的运算,对于代码中的 dsp_mult 模块,多次上板在低温低压下进行测试。最终发现,只有驱动 dsp_mult 模块的时钟频率不超过 2 倍时钟输入引脚的频率时,低温低压下的上板测试才会通过。 4、基于上述测试与分析,目前已基本确认问题是内部 OSC 输出时钟频率过高造成的。
3.2、修复与改进
基于<3.1、复现与分析>认为,当下如果继续使用内部 OSC 输出作为时钟输入信号来驱动 dsp_mult 模块,则需要降频。
3.2.1、关于降频方案的实施
在一位资深大佬建议下,直接使用 counter 计数,来实现降频。
工程师如有所思,写下了如下代码:
reg [1:0] clk_count;
reg Clk;
always @(posedge Clk_o or negedge rst_N)
if (!rst_N) begin
clk_count <= 2'b00;
clk <= 1'b0;
end else begin
clk_count <= clk_count + 1'b1;
if(clk_count == 2'b11) Clk <= ~Clk;
else clk <= Clk;
end


