Quartus II以及後來的Quartus Prime(截止本文寫作時其最新版本是v16.1)是Altera公司爲自家FPGA編寫的集成開發環境,包括編譯、綜合工具。工具不錯,但對SystemVerilog的支持實在槽點多多,下面僅列出本人遇到的5個無力吐槽的編譯器大BUG:
1.不支持在interface中聲明interface的實例
示例代碼:
interface test_if #(
parameter BITW = 16
);
logic [BITW-1:0] sigs;
endinterface
interface nest_if #(
parameter BITW = 16
);
test_if #(.BITW(BITW)) tifi();
endinterface
module multiinstif #(
parameter BITW = 8
) ;
nest_if #(.BITW(BITW)) nifi();
endmodule
現象:quartus_map.exe直接崩潰,屢試不爽!
受影響的版本:Quartus Prime v16.0、v16.1,舊版Quartus還未測試,也懶得測試了-_-!
官方給出的解決方案:工程目錄下新建一個quartus.ini文件,在其中加入一行:sgn_use_new_verific = on
解決方案可行性:可以編譯通過,但貌似該模式仍然是未完善的狀態,某些語言特性無法得到支持,例如——多維數組信號
評價:看你運氣了,大工程的話效果會怎麼樣實在不敢想象。
2.對interface中的條件generate代碼支持不好
示例代碼:
interface test_gen_if #(
parameter int BITW = 16
);
generate
if (BITW > 0) begin: SIGS
logic[BITW-1:0] sigs;
end: SIGS
endgenerate
endinterface
module multiinstif(
input clk,
input rst
);
test_gen_if #(.BITW(0)) tgifi_01();
test_gen_if #(.BITW(0)) tgifi_02();
test_gen_if #(.BITW(0)) tgifi_03();
test_gen_if #(.BITW(0)) tgifi_04();
test_gen_if #(.BITW(0)) tgifi_05();
endmodule
現象:當multiinstif中聲明的test_gen_if實例的例化參數BITW賦值0,且聲明超過4個實例時,quartus_map.exe直接崩潰,屢試不爽!
受影響的版本:QuartusPrime v16.0,v16.1版貌似已經解決了,舊版的QuartusII沒測試過,同樣,懶得測了-_-!
官方解決方案:還是用quartus.ini文件加入一行:sgn_use_new_verific = on
的辦法
評價:同上
3.某些情況下不能正確識別和區分常量和變量
示例代碼:
interface test_if #(
parameter BITW = 16
);
logic [BITW-1:0] sigs;
endinterface
package test_pkg;
function automatic int test_calc(int bitw);
return bitw + 1;
endfunction
endpackage
module test_mod #(
parameter BITW = 8
) ( input bit clk, input wire rst);
test_if #(.BITW(BITW)) tifi();
localparam int bitw_ofcalc = test_pkg::test_calc($size(tifi.sigs,1)); // on this line Quartus reports error message: can't pass value from actual to argument bitw
initial $warning("DEBUG: bitw_ofcalc = %0d", bitw_ofcalc);
endmodule
現象:Quartus編譯報告 “ can’t pass value from actual to argument bitw”,就像代碼中註釋的說明一樣
受影響的版本:Quartus Prime v16.0、v16.1,同樣的,舊版懶得測試了-_-!
官方解決方案:將代碼中的 test_if #(.BITW(BITW)) tifi();
改爲 test_if #(.BITW(8)) tifi();
評價:無力吐槽——傳遞 BITW
的目的就是爲了提高代碼的可重用性,這樣來整,對每一個不同值的BITW我都得寫一個與test_mod代碼相同但名稱不同的模塊,這是要累死我的節奏嗎?
4.對分層標識符支持不好
示例代碼:
interface test_if #(
parameter int test_bitw = 1
);
generate
if (test_bitw > 0) begin: SIGS
logic[test_bitw-1:0] sig;
end
endgenerate
endinterface
module test_mod(
test_if tifi,
output wire sig_o
);
generate
if (tifi.test_bitw > 0) begin: OSIG // quartus complains : constant expression cannot contain a hierarchical identifier
assign sig_o = |tifi.SIGS.sig;
end
endgenerate
endmodule
現象:quartus在有註釋的那一行報告”constant expression cannot contain a hierarchical identifier“
受影響的版本:Quartus II v13.1、Quartus Prime v16.0、v16.1,其他版本懶得測了,咱又不在Altera領工資-_-!
官方解決方案:等下一版Quartus Prime修復……
評價:又一次無力吐槽——SystemVerilog標準(IEEE std. 1800)中並未規定不能引用分層標識符,就算你聲明自己實現的只是該標準的一個子集,那爲什麼按下面的代碼寫test_mod時又能編譯了?
module test_mod(
test_if tifi,
output wire sig_o
);
localparam bit osig_en = tifi.test_bitw > 0 ? 1'b1 : 1'b0;
generate
if (osig_en) begin: OSIG // quartus passed the compilation with no error message
assign sig_o = |tifi.SIGS.sig;
end
endgenerate
endmodule
好吧,我等……再說幾句:上面的解決方案只適用於Quartus Prime v16.0、v16.1,在Quartus II v13.1上仍然繞不過去,而一些舊的芯片例如Cyclone III,則因爲新版的Quartus Prime不支持,加上Altera官方並不願意爲舊版的QuartusII開發補丁,因此這樣的問題便變得無解了,悲劇吧?
5.SystemVerilog代碼的編譯錯誤定位不準確
我就不放示例代碼了,因爲要重現這個問題太麻煩,不是簡單的幾行代碼就能搞出來的。現象就是:Quartus編譯器給出的錯誤信息不能完全反映代碼的錯誤位置,有時甚至奇葩到對一行很明顯沒問題的語句報錯,爲了正確定位編譯錯誤我不得不採用費時費力的排除法,嚴重降低了開發效率。
根據這些現象個人懷疑目前版本的Quartus編譯器程序中存在着內存管理漏洞,導致在解析某些錯誤代碼時觸發內存訪問越界或內存泄漏的問題,並最終造成這樣莫名其妙的報錯,由此看來,Quartus編譯器的軟件質量實在堪憂啊。
個人的解決辦法:就像上面說的一樣,採用排除法來定位編譯錯誤,具體點就是——先不停的註釋代碼,直到編譯器不再報錯,然後在這樣的代碼版本基礎上一塊一塊的增加不同位置的代碼,看哪一塊代碼增加後會導致編譯器報錯。這真的是體力活兒啊!