在使用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。
參考如下的代碼:
1 module redundant1(ina,inb,out1); 2 input ina,inb; 3 output out1,out2; 4 5 wire out1; 6 wire out2; 7 8 assign out1 = ina & inb; 9 assign out2 = ina & inb;; 10 11 endmodule
代碼如上編寫的話,綜合工具自動去掉一個AND gate,因為out1和out2使用同樣的AND gate就足夠了
若是代碼如下的話:
1 module redundant1d(ina,inb,out1,out2); 2 input ina,inb; 3 output out1,out2; 4 5 wire out1; 6 wire out2; 7 wire in1a /*synthesis syn_keep = 1*/; 8 wire in1b /*synthesis syn_keep = 1*/; 9 wire in2a /*synthesis syn_keep = 1*/; 10 wire in2b /*synthesis syn_keep = 1 */; 11 12 assign in1a = ina ; 13 assign in1b = inb ; 14 assign in2a = ina; 15 assign in2b = inb; 16 17 assign out1 = in1a & in1b; 18 assign out2 = in2a & in2b; 19 20 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。