fpga_feixiang 发表于 2020-8-30 21:31:20

FPGA设计规范、代码优化方法和准则

一、 代码设计

1、设计中的FIFO、状态机接口需要有异常恢复状态和状态上报机制,格雷码电路防止被综合工具优化掉。

a)自行设计的格雷码FIFO(一般用于连续数据流跨时钟域)用Synplify综合时,为了防止被优化需要添加综合引导语句:“synthesis_syn_preserve = 1”;

b)各种综合工具均有状态机安全模式,综合时候建议打开。

2、电路中所有寄存器、状态机、计数器、FIFO在单板上电复位时及使用前必须处于一个已知状态。

    a)对电路中的寄存器、状态机、计数器、FIFO必须进行异步复位(不依赖于任何时钟的复位);

    b)电路中的状态机、计数器在应用的时候不能完全依赖于异步复位时的状态,对于重要的状态机或计数器,必须还有周期检测或同步并对它进行复位/置数机制,保证可靠工作。

3、跨时钟域以及异步信号必须同步化处理(使用的QuartusII中的Design Assistant或者专业的nlint、spyglass等工具完成代码检查),这条是用FPGA进行数字电路设计的最核心最基本的思想和方法!

a)尽可能在整个设计中只用一个主时钟,同时只用一个时钟沿,主时钟走全局时钟网络;

b)推荐所有输入输出信号均通过寄存器寄存,寄存器接口当作异步接口考虑;

c)当全部电路不能用同步电路思想设计时,即需要用多个时钟来实现,则可以将全部电路分成若干个局部同步电路(尽量以同一个时钟为一个模块),局部同步电路之间的接口当作异步接口考虑;

d)电路的实际最高工作频率不应大于理论最高工作频率,要留有一定设计余量,保证芯片可靠工作;

e)电路中所有寄存器、状态机在单板上电复位时应处在一个已知状态;

f)对于设计中的异步电路,要给出不能转换为同步设计的原因,并对该部分异步电路的工作可靠性(如时钟等信号是否有毛刺,建立保持时间是否满足要求等)做出分析判断,并提供分析报告;

g)关于全局时钟的约束,能上全局的全部上全局,不能上全局的建议通过区域时钟约束、逻辑锁定、增量编译等保证性能;

h)依靠QuartusII中的Design Assistant或者专业的nlint/spyglass工具检查跨时钟域代码处理部分。

4、电路中不能出现门控时钟和行波时钟。

a)门控时钟的使用主要是通过关断时钟来达到降低功耗的目的,但是使用不当容易使得时钟出现毛刺,给设计带来灾难性风险。如果降功耗必要的话,推荐使用厂家自带的时钟控制的IPCORE,例如 ALTCLKCTRL;

b)行波时钟是指寄存器输出的数据又作为下一个寄存器的时钟使用。行波时钟是一个非常危险的设计,由于寄存器有Tco,它会使时钟沿变缓,延时加大,多级级联的时候情况更加恶劣,出问题是必然的!行波时钟设计实际上是一种异步设计,大部分综合布线工具都不会对行波时钟设计进行setup/hold时序分析检查,设计无法保证正确性!

设计中完全没有必要使用行波时钟,可以用寄存器输出做同步使能用,与行波时钟设计意图完全一致!

5、需要综合的RTL源代码中不允许出现“* / %”这三个运算符。

a)目前大部分综合工具对以上三种运算支持的不好,而且非常浪费LE资源,而且还不能保证正确性和稳定性!可行的替代方案如下:

“*”通过例化IPCORE或者“移位运算+加法”来实现;

“/”通过“移位运算+加法”来近似逼近实现;例如:1/30 = 1/32 + 1/512 + 1/8192;

“%”通过自己手动计算得到;

以上运算在非综合的RTL的代码中使用不受此限制。

6、条件语句必须赋值完全,即:if语句后必须有配对else语句,case、casez、casex语句中必须有default语句。

a)如果if没有配对的else,case/casez/casex中没有对应的default语句的话,之后reg型数据会保持原来的值。这个在时序逻辑中可能没有太大的问题(如果设计者本意就是要保持的话),但在组合逻辑中会生成一个锁存器,锁存器逻辑往往不是设计者的意图而导致灾难性后果!

为了避免不经意的犯错,建议养成良好的编码习惯:if一定要有配对的else,case/casez/casex中一定要有对应的default语句,即使要保持原来的值也要显示声明(else;或者default;)

7、使用器件的专用管脚和专用资源实现电路功能,这些包括全局时钟、复位管脚,全局输出允许管脚等,内部全局时钟网络等。

a)专用管脚和专用资源一定要优先使用,使用得好会事半功倍。如果不用器件提供的专用管脚或资源,有时导致稳定性和可靠性不高甚至是设计失败。

8、逻辑未使用的但又硬件连线的管脚,逻辑必须显示声明并处理。所有有硬件连线的管脚必须在顶层代码中显示声明(包括暂时没有使用的),不允许放任不管。

a)对于有硬件连线的输入信号(包括三态的输入方向),建议输入到CPU接口作为只读寄存器(如果没CPU接口可以将该信号做成一些等效冗余逻辑加到其他逻辑中去),这样既可以消除warning,又可避免布线工具随便布线(把输出信号放到输入管脚)导致外部信号冲突;

b)对于有硬件连线的输出信号(包括三态的输出方向),对于暂时没有使用的一定与硬件人员确定其默认值,避免对外信号(如电阻上下拉)的干扰。

9、修改接口文档需要同对应项目组人员确认。

a)与硬件相关的方面涉及输入文件有qsf和sdc,内容包括但不限于电平标准、电流强度、管脚位置、输入输出方向、上下拉等等;

b)与软件相关的方面涉及方案协同实现文档和寄存器接口文档,包括寄存器操作地址、操作顺序等等。

二、 综合布线过程

1、综合布线的版本是否与配置库上的版本完全一致

a)养成良好的版本维护和管理习惯(如复制修改和设置只读属性等),善于使用代码比较工具修改版本(包括源代码、qsf和sdc等输入文件要全部仔细比对)。

2、所有约束(包括对外部接口的管脚约束、时序约束、内部时序约束)是否已经添加正确,布线报告满足约束要求,时序无error类告警。

a)硬件方面:电平标准、电流强度、翻转速率以及上下拉(差分时还有输入阻抗匹配,高速信号还有预加重、VOD、接收均衡、直流增益等);

b)输入输出锁IOB/IOE,时序约束正确(Tsu、Th、Tco、Fmax);

c)异步和组合逻辑锁IOB/IOE,加set_minimum_delay和set_maximum_delay约束;

d)时钟约束有基时钟、衍生时钟、虚拟时钟和多周期约束等。

3、所有编译、布线、时序分析等过程中出现的warning都已经确认。

三、 版本验证过程

    1、修改模块必须进行UT(单元测试)。

a)建议UT的覆盖按照功能覆盖优先,分解测试点,根据测试点来设计测试用例,保证测试点覆盖率为100%;

b)在功能覆盖率的前提下关注代码覆盖率,建议的代码覆盖率标准为:语句覆盖和分支覆盖为100%,条件覆盖和表达式覆盖率为90%。

    2、有条件的话单板验证必须进行完整的STB(上板系统测试)或全系统业务平台测试。

良好代码编写风格可以满足信、达、雅的要求。在满足功能和性能目标的前提下,增强代码的可读性、可移植性。
FPGA优化方法和准则概括如下:

一、 面积类

1、不进行不必要的数据清零。

    说明:一般在数据总线赋值额时候,习惯加上例如的:“else dout <= 16’d0”,实际上这种清零并不是必要的,因为一般写使能就已经控制了数据的有效性,数据即使保持原值也没有问题,加入上述语句后,综合其会用多余的资源实现这个没有必要的清零分支。

2、多路数据进行相同处理时,先选择后处理优于先处理后选择。

3、采用合适的编码方式(one hot bit速度更快,但是资源消耗得也更多)。

4、多拍串行计算打开为一拍并行计算

5、统计寄存器位宽根据需要来确定,不需要一位的32bit大位宽。

6、异步配置信号(CPU)可根据配置模块所在不同时钟域分别进行处理。

7、尽可能实现资源共享(计数器、比较器等),节省资源。

8、采用迭代算法节省资源。

10、使用reg代替FIFO接口。

11、状态机状态不要在比较器中使用。

12、3倍插值FIR滤波器优化。

13、用减法器借位位代替比较器。

14、利用ROM代替较大的组合逻辑。

15、利用多周期约束或通过RAM换LE的方法来节省CIC滤波器LE资源。

16、Multiplexer重编码节省LUT资源。

17、合理设置MUX默认条件有利于资源优化。例如:“default:dout <= 1’dx;”

18、合理设置QuartusII软件中auto packed register选项

20、建议使用“减法溢出”来设计Timer。

21、简化环回设计,节省资源。

22、减少时钟域,节省资源。

23、复数乘法公式展开,利用加法部分代替乘法。

24、禁止使用shift reg自动替换功能,避免小的的移位寄存器浪费M9K。

25、基于RAM的交换架构。

26、用RAM存放统计值来代替统计寄存器。

28、多通道分时处理时,功能相同的模块可以考虑复用。

29、复用没有全速运行的模块,多通道RAM使用复用模块代替。

RAM节省部分

1、 使用根据器件RAM块的位宽和深度合理选择。

2、 使用分布式RAM替换寄存器资源

3、 2倍插值滤波器优化。

其他部分

1、 根据器件内部block RAM特点,选择合理的拼接模式,可以减小RAM块地址译码和数据选择的LE。

2、 路由查表优化。

二、 时序类

1、打平逻辑可以提高时序。

2、配平寄存器以提高时序。

3、尽可能减少组合逻辑。

4、在输出到IOB时安排布线时延要求低的路径,要求高的放在内部逻辑。

5、降低高速时钟域布线资源。

6、加法时,将位宽较宽的放在多周期中,全速率中尽量减少加法位宽。

7、加法时,将高位宽拆分成两级进行运算。

8、使用RAM、DSP中流水reg,不增加额外延时。

9、使用multicycle。

10、减少扇出fanout。

11、功能等价法均匀分散组合逻辑。

12、设置QuartusII软件综合选项。

13、功能没有优先级的if-else将关键路径放在最前。

14、物理综合优化removal和recovery时序。

三、 功耗类

1、避免小fanout的信号也使用全局clock网络。

2、尽可能使用区域clock代替全局clock network。

3、关闭非持续工作的模块时钟(通过IPCORE、clock_ctrl模块)。

4、条件允许小选择低功耗管脚和设置电压电流约束。

5、控制RAM组合形式,减少每次操作的RAM块个数。

6、代码中才用关断使能、数据等降低功耗。

四、 案例类

1、减少调度模块的调度颗粒,提高系统吞吐率。

2、从方案角度优化降低编码实现复杂度。

3、保证外部总线错误时,逻辑内部可以检查到。

4、多带宽滤波器实现时,可考虑使用通用混模filter实现多个不同带宽filter,以节省资源。

五、其他

1、可靠性—板级信号传递握手机制为送耦合机制。

大鹏 发表于 2020-9-2 11:55:50

FPGA设计规范、代码优化方法和准则

大鹏 发表于 2021-3-5 16:16:50

FPGA设计规范、代码优化方法和准则

大鹏 发表于 2021-3-8 16:21:57

FPGA设计规范、代码优化方法和准则

zxopenhl 发表于 2022-9-2 11:47:40

FPGA设计规范、代码优化方法和准则
页: [1]
查看完整版本: FPGA设计规范、代码优化方法和准则