FPGA设计中DFX的应用

本文转载自: FPGA的现今未微信公众号

注:本文由作者授权转发,如需转载请联系作者本人

首先讲一个故事,12年的时候,部门来了很多新员工,当时刚好遇到一个非常复杂的项目,每个人都负责一个一级模块,代码量也在10K以上。新员工已经入职了半年到1年的样子,加上进度也比较紧张,这样的工作量对他们来说还是有点点吃力的,整个项目阶段工作都比较紧张,尤其到了后期调试阶段,上板测试时出现各种各种问题,由于经验不足,定位起来也是比较吃力。

部门对上板定位问题,已经有一套可行的方法,就是对每个模块要做好状态、告警检测和统计的上报。为什么要做这个事情,当时新员工并不是很理解,强推的话有点阻力,SE和项目经理后来想了一个办法,那就是怀疑到是谁的问题了,谁来主导定位这个问题。新员工由于缺乏经验就有点吃不消了,怎么办?SE这个时候出来告诉大家定位思路,比如要增加哪些状态、告警的检测和统计,先排除是不是自己模块的问题,不是的话如何证明?是的话大概是什么问题。通过这种方式定位一个问题后,新员工对哪些状态、告警检测和统计的认识有了更深刻的理解,再也不用强调这些问题定位的手段了。

FPGA设计中的DFX到底是什么呢?
DFX是Design For X的意思,这里的X可以代表测试,维护、制造等等,比如可测试性设计、可维护性设计、可制造性设计等。在FPGA的设计中的DFX主要是包括可测试性设计和可维护性设计这2大点。最终的目的是快速定位板上问题和后期维护阶段日常巡检诊断。

为什么会有DFX的存在呢?
这是伴随着FPGA的设计规模不断地增长而出现的。FPGA早期的设计比较简单,在仿真和signalTap、chipscope等的工具辅助下,问题直接通过抓信号就能被搞定(当然现在很多人也是这么用的)。随着逻辑规模和设计复杂度的增大,资源消耗的变多,可能会出现没有抓信号的资源,或者说问题现象太复杂,都不知道抓什么信号。这个时候DFX信息就相当有效了。

其次出现问题后,收集DFX信息,就能快速定位到问题可能出现模块,相比多次抓信号,在大规模逻辑设计里,有效率上的天然优势。

那DFX主要是做什么呢?
DFX的内容没有一个统一的标准,在讨论这个问题前先思考一个问题,我们自己设计的一个模块,如何证明他是正常工作的,比如如下图所示的整包fifo,要说明他是正常的,可以从这几个方面说明:

1、状态:fifo的空满状态正常,即空位1,满或者将满位0;在控制写、读过程中的一些关键信号处于初始状态;
2、异常检测:检测到写入报文的时序正常、整包输出的时序正常、fifo没有上下溢出告警;
3、统计:输入报文个数统计等于输出报文个数统计

如果上面的信息都是满足的,那么我们非常有理由相信这个模块的工作是正常的(当然这里不能绝对说是正常的,从定位问题的角度来讲,怀疑这个模块的概率是大大降低了)。DFX主要做什么,作者总结下就是从3个方面着手设计:

第一就是状态信息,即一些关键信号的状态都要可读,比如fifo的空满状态、状态机的状态、内部关键信号的状态、接口信号的反压状态等等;

第二就是告警信息,或者叫做异常检测,一个是对接口输入信息做异常检测,比如输入的数据格式是否正确?输入的数据个数是否正确等。另一个就是检测内部的处理是否正确,是否会出现一些不该出现的情景?

第三就是统计,输入输出的各种统计,还有内部处理过程中的统计等。

DFX应该什么时候做或者应该怎么做呢?
我们做DFX时,很多时候是写完代码后以打补丁的方式来开发,这种事后补救的方式,在资源消耗和信息收集全面性上不太友好,更加推荐的方式是在方案设计阶段就开始考虑,要考虑通过哪些信息来证明你设计的模块功能是正确的。因为通过以往的经验来看,后期打补丁虽然也可以,但是要么打不全,要么重复检测浪费大量的资源。所以通过方案设计+打补丁的方式,更能在信息收集和资源消耗上能找到一个合适的平衡位置。

示例
状态的DFX如下所示,将本模块内的关键状态信号全部拉到一个寄存器里,当然,如果一个寄存器不够,就来2个。

always@(posedge clk_sys or posedge rst)
begin
if(rst == 1'b1) begin
mge2hpi_state <= 32'b0;
end
else begin
mge2hpi_state <= { 18'b0 ,
sot2spw_pkt_cnt_afull , //13
stk2spw_key_afull , //12
fca2spw_key_afull , //11
order_fifo_ren_wait , //10
~order_fifo_empty , //9
order_fifo_afull , //8
~wod_fifo_empty[3] , //7
~wod_fifo_empty[2] , //6
~wod_fifo_empty[1] , //5
~wod_fifo_empty[0] , //4
wod_fifo_afull[3] , //3
wod_fifo_afull[2] , //2
wod_fifo_afull[1] , //1
wod_fifo_afull[0] }; //0
end
end

告警DFX如下所示:这里有2段代码,第一段主要是对fifo的上下溢出做告警,第二段代码是对内部报文长度计算是否错误做告警。

always@(posedge clk_sys or posedge rst)
begin
if(rst == 1'b1) begin
mge2hpi_err[9:0] <= 10'b0;
end
else begin
mge2hpi_err[9:0] <= { order_fifo_err[1:0] ,
wod_fifo_err[3][1:0] ,
wod_fifo_err[2][1:0] ,
wod_fifo_err[1][1:0] ,
wod_fifo_err[0][1:0] };
end
end

always@(posedge clk_sys or posedge rst)
begin
if(rst == 1'b1) begin
pkt_len_err <= 1'b0;
end
else if((axis_data_sop == 1'b1) && (qmg2spw_axis_tvalid == 1'b1) && (qmg2spw_axis_tready == 1'b1) &&
(qdma_qid == 11'd0) && (qmg2spw_axis_tdata[56 +: 16] != qmg2spw_axis_tuser[15:0])) begin
pkt_len_err <= 1'b1;
end
else if((pkt_len_err == 1'b1) && ((axis_data_eop == 1'b1) || (axis_data_eop_1dly == 1'b1))) begin
pkt_len_err <= 1'b0;
end
else;
end

总结一下,DFX信息主要包括3个内容,状态、告警和统计,目标就是用最少的资源,做合理的检测达到快速定位问题或者给逻辑“体检”目的。关于DFX的内容,你有什么更好的内容,欢迎一起交流分享。

最新文章

最新文章