介紹verilog-mode的一個ppt:http://www.veripool.org/papers/verilog-mode_veritedium_20090925.pdf。它的官方網站:http://www.veripool.org/wiki/verilog-mode(應該是吧,沒仔細考證)
電腦跑仿真,還得挺長時間的,順便把用emacs寫verilog的方便之處大概總結一下吧,我只能說:太方便了!
以前用verilog-mode也就用個/*AUTOARG*/、/*AUTOWIRE*/、/*AUTOSENSE*/、/*AUTOINST*/之類的,寫個小工程基本也足夠了。后來開始用/* AUTO_TEMPLATE*/、/*AUTOINSERTLISP*/,發現這個大大提高工作效率:有一個1000行左右的verilog模塊(主要是例化了很多其他模塊),用verilog-mode只寫了100行,然后等着自動生成就行了。雖說也可以copy-paste,然后再改改,不用真寫1000行,但這個工作量也不小,也有容易出錯。
verilog-mode大概有這么幾個作用吧(代碼摘自http://www.veripool.org/projects/verilog-mode/wiki/Verilog-mode_veritedium):
注意:左邊是需要寫的,右邊是C-c a自動生成的。
1 自動生成組合邏輯敏感列表 /*AUTOSENSE*/
always @ (/*AUTOSENSE*/) begin outin = ina | inb; out = outin; end always @ (/*AUTOSENSE*/ina or inb) begin outin = ina | inb; out = outin; end
2 自動生成端口 /*AUTOARG*/
module ex_arg (/*AUTOARG*/); input i; output o; endmodule module ex_arg (/*AUTOARG*/ // Outputs o, // Inputs i);
input i; output o; endmodule
3 自動例化 /*AUTOINST*/
module fanout (o,i) input i; output [31:0] o; wire [31:0] o = {32{i}}; endmodule
module ex_inst (o,i) input i; output [31:0] o; fanout fanout (/*AUTOINST*/); endmodule
module fanout (o,i) input i; output [31:0] o; wire [31:0] o = {32{i}}; endmodule
module ex_inst (o,i) output o; input i; fanout fanout (/*AUTOINST*/ // Outputs .o (o[31:0]), // Inputs .i (i)); endmodule
4 模板 /*AUTO_TEMPLATE*/,注意下面的@,和例化的序號(如下面的ms2中的2)是一致的
/* psm_mas AUTO_TEMPLATE ( .PTL_MAPVALIDX (PTL_MAPVALID[@]), .PTL_BUS (PTL_BUSNEW[]), ); */
psm_mas ms2 (/*AUTOINST*/);
/* psm_mas AUTO_TEMPLATE ( .PTL_MAPVALIDX (PTL_MAPVALID[@]), .PTL_BUS (PTL_BUSNEW[]), ); */
psm_mas ms2 (/*AUTOINST*/ // Outputs .INSTDATAOUT (INSTDATAOUT), .PTL_MAPVALIDX (PTL_MAPVALID[2]), // Templated .PTL_BUS (PTL_BUSNEW[3:0]), // Templated
5 lisp模板 /*AUTO_TEMPLATE*/,注意下面的@,后面可以跟一些lisp代碼,比如上面的例子,ms2的PTL_MAPVALIDX 不是接(PTL_MAPVALID[2]),而是(PTL_MAPVALID[2+1]),那前面寫成這樣就行了((+ 1 @)是elisp的1+@):
/* psm_mas AUTO_TEMPLATE ( .PTL_MAPVALIDX (PTL_MAPVALID[@“(+ 1 @)"]), .PTL_BUS (PTL_BUSNEW[]), ); */
這個功能相當強大,比如例化很多相同的模塊的時候,連接關系通常會有規律,那么按照這個規律寫elisp就可以了。
6 插入lisp語句 /*AUTOINSERTLISP*/,比如 /*AUTOINSERTLISP(my-insert 0 22 "my_init(\"c:\\\\my_src\\\\my_src%d\");\n")*/ /*AUTOINSERTLISP(my-insert 0 22 "my_init(\"c:\\\\my_src\\\\my_src%d\");\n")*/ // Beginning of automatic insert lisp my_init("c:\\my_src\\my_src0"); my_init("c:\\my_src\\my_src1"); my_init("c:\\my_src\\my_src2"); my_init("c:\\my_src\\my_src3"); my_init("c:\\my_src\\my_src4"); my_init("c:\\my_src\\my_src5"); my_init("c:\\my_src\\my_src6"); my_init("c:\\my_src\\my_src7"); my_init("c:\\my_src\\my_src8"); my_init("c:\\my_src\\my_src9"); my_init("c:\\my_src\\my_src10"); my_init("c:\\my_src\\my_src11"); my_init("c:\\my_src\\my_src12"); my_init("c:\\my_src\\my_src13"); my_init("c:\\my_src\\my_src14"); my_init("c:\\my_src\\my_src15"); my_init("c:\\my_src\\my_src16"); my_init("c:\\my_src\\my_src17"); my_init("c:\\my_src\\my_src18"); my_init("c:\\my_src\\my_src19"); my_init("c:\\my_src\\my_src20"); my_init("c:\\my_src\\my_src21"); // End of automatics
如果要例化很多模塊,或者寫很多my_reg_0、my_reg_1……什么的,方便很多很多。上面的例子是做仿真時候指定test vector源文件的,就是現在正在跑的,也很方便。其中my-insert是自己寫的一個簡陋的elisp函數:
(defun my-insert (num1 num2 prefix) (let ((@ num1)) (save-restriction (while (< @ num2) (insert (format prefix @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @)) (setq @ (1+ @)))))) elisp高手不要笑話我啊……不知道寫成AUTO_TEMPLATE的那個樣子需要怎么寫……
總結一下,用verilog-mode基本上只需要寫真正需要的,而那些由於verilog的語法什么的規則導致的重復勞動都可以省下了。還有一個好處,自動生成的這些C-c k就沒有了,也就是說那1000行的代碼就被縮減到100行,維護起來方便很多。還有一些快捷鍵,寫module、always、case之類的只用寫名字、條件之類的就行了,像begin、end、endmodule、endcase、case之類的也都是自動生成的。
其實還漏了一些,比如/*AUTOWIRE*/,他會把例化模塊的輸出中,沒有聲明wire的自動聲明;/*AUTORESET*/,自動把寄存器初始化寫好;/*AUTOREG*/,如果輸出中不應該是wire型,自己又沒寫reg,這個就自動生成了。
總之很推薦!不過vimer可能就不太爽了,Verilog-mode的網站上雖然有個解決方法,但是其實很不好用,原文是這樣:
For those that use vi, or have a script generating code, it is useful to be able to expand the automatics from the shell. Batch invocation is done with the shell command:
emacs --batch filename.v -f verilog-auto -f save-buffer ![]()
