在使用Synplify综合时,此工具会自动优化我的设计。
当然此功能有好有坏,最近有个项目需要使用Chipscope观察内部信号,打开inserter就懵了,信号列表中我的设计有的是名字被改了,有的是干脆给优化没了。
网上当然也有人提出这个问题, 例如 http://www.xilinx.com/support/answers/5249.html 就提供了一个 /* synthesis syn_keep = 1 */ 的语法来保留自己的设计。
随后又以 /* synthesis syn_keep = 1 */ 为关键词搜索了一下,又发现了其他的新内容,随即记录一下。
在 Synopsys FPGA Synthesis Attribute Reference Manual 中提到了三个语法: syn_keep , syn_preserve, syn_noprune 并对三种语法做出了比较。
syn_keep | 只适用于net和 combinational logic,此语法可以在综合过程中保留wire,且不对此wire做任何的优化。此语法也可用于register,当用于register时,register可以被保留且不会变成macro |
syn_preserve | 保证register不会被优化 |
syn_noprune | 保证一个没输出的blackbox(此blackbox 的输出没有驱动任何logic)不被优化 |
然而看了此表还是很模糊,再看了一下Synplify Pro for Microsemi Edition User Guide文档中 Preserving Objects from Being Optimized Away 部分则会有更深入的解释。
To Preserve | Attach | Result |
Nets | 使用syn_keep语法。适用于verilog中的wire或reg,或者VHDL中的signal | 在仿真,综合或者P&R中保留net |
Net for probing | 使用syn_probe语法。用于verilog中的wire或者reg,或者VHDL中的signal | 保留内部的net来用于观察 |
Shared registers | 使用syn_keep语法。适用于shared register的输入wire或者signal | 保留重复的驱动cell |
sequential component |
使用syn_preserve语法。适用于verilog中的reg或者module,或者VHDL中的signal或architecture | 保留固定值驱动的register |
FSM | 使用syn_preserve语法。适用于verilog中的reg或module,或者VHDL中的signal | 保留state register有值的输出端口或者内部信号 |
instantiated components |
使用syn_noprune语法。适用于verilog中的module或者component,或者VHDL的architecture或者instance | 即使instance有未使用的端口也可以保留下来 |
由此可以总结一下:
syn_keep最常用,可以用于wire,reg和shared register两种情况;
syn_probe处于观察的目的可以使用于wire或者reg (ChipScope观察信号的话使用此语法应该足够了);
syn_preseve使用于固定值驱动(constant-driven)的register或者状态机register中;
而syn_noprune使用于例化的模块(instance),即使例化模块有未使用的端口,也可以让模块保留下来。
关于Shared register:
共享的register又可以称为重复的logic。
参考如下的代码:
module redundant1(ina,inb,out1);
input ina,inb;
output out1,out2; wire out1;
wire out2; assign out1 = ina & inb;
assign out2 = ina & inb;; endmodule
代码如上编写的话,综合工具自动去掉一个AND gate,因为out1和out2使用同样的AND gate就足够了
若是代码如下的话:
module redundant1d(ina,inb,out1,out2);
input ina,inb;
output out1,out2; wire out1;
wire out2;
wire in1a /*synthesis syn_keep = 1*/;
wire in1b /*synthesis syn_keep = 1*/;
wire in2a /*synthesis syn_keep = 1*/;
wire in2b /*synthesis syn_keep = 1 */; assign in1a = ina ;
assign in1b = inb ;
assign in2a = ina;
assign in2b = inb; assign out1 = in1a & in1b;
assign out2 = in2a & in2b; endmodule
由于加了syn_keep语法导致综合结果是两个AND gate都会保留下来。
**需要注意的一点是syn_keep语法需要用在例化程序的输入端(input of instance)才会有效果,例如上面代码syn_keep加在out1,out2之后是没有任何效果的。
关于固定驱动值(Constant-driven)
指某一个flip-flop的输入总是为常数,例如有一个flip-flop总是被logic 1 驱动,则在综合的时候工具会自动移除此flip-flop且把信号绑到VCC上。使用syn_preseve的话可以保留此flip-flop。