赞
踩
gvim对于编写Verilog代码有个神奇的功能,可以快速制作verilog模板,但是网上没有相应的分享,所以自己制作了一个,分享出来(windows下)。
模板包括:文件头、常用自定义命令、Module中常用模板(包括模块基本模板、组合时序逻辑模板、计数器、状态机、边沿检测器、同步器、触发器、触发器例化、头文件等)、预编译模板(延时、仿真精度)、TB模板(TB基本模板、产生时钟复位、延时任务、生成波形图文件、产生随机数、取对数、打开文件、断言等)、注释(注释头、段注释、端口注释等)、任务模板(延时任务、任务模板)。
注: 这些模板都是我自己经常使用的模板
_vimrc文件
中该文件在安装目录中,如果不知道安装目录在哪,可以在末行模式下输入::echo $VIM
就可以显示安装位置。
各命令意思已经在注释中注明。
请注意:以下内容其实具有灵活性,可以根据你自己的需求添加相应的代码。我的命名规格一般是大写缩写+小写缩写
,什么意思呢,举个例子:就拿最常见的Verilog模块的框架来说,我的重命名为:MBmk
,MB
就是模板
的缩写,mk
是模块
的缩写,所以如果你想生成一个模块的模板,只需要输入MBmk
即可,其他的都类似。
"""""""""""""""""""""""""""""""新文件标题"""""""""""""""""""""""""""""""""""""""""""""""""" "按F4自动插入文件头 map <F4> :call SetTitle() <cr>:11 <cr><end>i "定义函数SetTitle,自动插入文件头 func SetTitle() call append(line(".")-1 , "`timescale 1ns/1ps") call append(line(".")+0 , "//******************************************************************") call append(line(".")+1 , "//") call append(line(".")+2 , "//*@File Name: ".expand("%")) if expand("%:e") == "v" let tmp1 = "verilog" elseif expand("%:e") == "sv" let tmp1 = "system verilog" elseif expand("%:e") == "c" let tmp1 = "C" elseif expand("%:e") == "cpp" let tmp1 = "C++" elseif expand("%:e") == "txt" let tmp1 = "plain text" else let tmp1 = "NONE" endif call append(line(".")+3 , "//*@File Type: ".expand(tmp1)) call append(line(".")+4 , "//*@Version : 0.0") call append(line(".")+5 , "//*@Author : Zehua Dong, SIGS") call append(line(".")+6 , "//*@E-mail : 1285507636@qq.com") call append(line(".")+7 , "//*@Date : ".strftime("%c")) call append(line(".")+8 , "//*@Function : ") call append(line(".")+9 , "//") call append(line(".")+10, "//*@V0.0 : Initial.") call append(line(".")+11, "//") call append(line(".")+12, "//******************************************************************") call append(line(".")+13, "") call append(line(".")+14, "//") call append(line(".")+15, "// Header file") call append(line(".")+16, "`include \"common.vh\"") call append(line(".")+17, "") call append(line(".")+18, "//") call append(line(".")+19, "// Module") call append(line(".")+20, "") "新建文件后,自动定位到文件末尾 autocmd BufNewFile * normal G endfunc """"""""""""""""""""""""""""""""自定义命令""""""""""""""""""""""""""""""""""" "显示时间,两种方式,可以取消注释都试试效果 ":ab xtime <c-r>=strftime("%Y-%m-%d")<cr> :ab xtime <c-r>=strftime("%Y-%m-%d %H:%M:%S")<cr> """"""""""""""""""""""""""""""""Module""""""""""""""""""""""""""""""""""" "模块定义 :ab MBmk module (<enter>clk <enter>rst_n <enter>);<enter><enter>input clk <enter>input rst_n <enter><enter><enter><enter><enter><enter><enter><enter><enter><enter><enter><enter><enter><enter><enter>endmodule "组合逻辑 :ab Zuhe always @(*) begin<Enter>if( )begin<Enter>end<Enter>else begin<Enter>end<Enter>end "时序逻辑 :ab Shixu always @( posedge clk or negedge rst_n ) begin<enter>if( ~rst_n ) begin<enter>end<enter>else begin<enter>end<enter>end "计数器 :ab MBjsq `define COUNT_BITS 8<enter><enter>reg [ `COUNT_BITS-1:0 ] count;<enter><enter>always @( posedge clk or negedge rst_n ) begin<enter>if( ~rst_n ) begin<enter>count <= #`DEL `COUNT_BITS'd0;<enter>end<enter>else if( count ) begin<enter>count <= #`DEL `COUNT_BITS'd0;<enter>end<enter>else begin<enter>count <= #`DEL count + `COUNT_BITS'd1;<enter>end<enter>end "状态机 :ab MBfsm reg [2:0] cs;<enter>reg [2:0] ns;<enter>parameter [2:0] IDLE = 3'b000,<enter>S1 = 3'b001,<enter>S2 = 3'b010,<enter>ERROR = 3'b100;<enter>always @( posedge clk or negedge rst_n ) begin<enter>if ( !rst_n ) begin<enter>cs <= IDLE;<enter>end<enter>else begin<enter>cs <= ns;<enter>end<enter>end<enter><enter>always @( * ) begin<enter>ns = IDLE;<enter>case ( cs )<enter>IDLE: begin<enter>if ( ) begin<enter>ns = S1;<enter>end<enter>else begin<enter>ns = IDLE;<enter>end<enter>end<enter>S1: begin<enter>if ( ) begin<enter>ns = S2;<enter>end <enter>else begin <enter>ns = S1;<enter>end<enter>end <enter>S2: begin <enter> if ( ) begin<enter>ns = ERROR; <enter>end <enter>else begin <enter>ns = S2;<enter>end<enter>end<enter>ERROR: begin <enter> if ( ) begin<enter>ns = IDLE; <enter>end<enter>else begin<enter>ns = ERROR;<enter>end<enter>end <enter>endcase <enter>end<enter><enter>always @( posedge clk or negedge rst_n ) begin <enter>if ( !rst_n ) begin <enter>end<enter>else begin <enter>case ( ns )<enter>endcase <enter>end <enter>end "边沿检测器 :ab MBby reg _en_q;<enter>wire _en_flag;<enter><enter>always @( posedge clk or negedge rst_n ) begin<enter>if( ~rst_n ) begin<enter>_en_q <= #`DEL 1'b0;<enter>end<enter>else begin<enter>_en_q <= #`DEL _en;<enter>end<enter>end<enter>assign _en_flag = ( ~_en_q ) && ( _en ); "同步器 :ab MBtongbuqi reg rst_s1;<enter>reg rst_s2;<enter><enter>always @ (posedge clk or negedge rst_n) begin<enter>if (!rst_n) begin<enter>rst_s1 <= 1'b0;<enter>rst_s2 <= 1'b0;<enter>end<enter>else begin<enter>rst_s1 <= 1'b1 ;<enter>rst_s2 <= rst_s1;<enter>end<enter>end "触发器模板 :ab MBdff module dff #( parameter SIZE = 64 )(<enter> clk ,<enter>rst_n ,<enter>D ,<enter>Q<enter>);<enter><enter>input clk ;<enter>input rst_n ;<enter>input [SIZE - 1 : 0] D ;<enter>output [SIZE - 1 : 0] Q ;<enter><enter>wire clk ;<enter>wire rst_n ;<enter>wire [SIZE - 1 : 0] D ;<enter>reg [SIZE - 1 : 0] Q ;<enter><enter>always @( posedge clk or negedge rst_n ) begin<enter>if( ~rst_n ) begin<enter>Q <= 'b0;<enter>end<enter>else begin<enter>Q <= D;<enter>end<enter>end<enter><enter>endmodule<enter> "触发器例化tb_ :ab LHdff dff #( ) dff_dut1(<enter>.clk ( clk ),<enter>.rst_n( rst_n ),<enter>.D ( ),<enter>.Q ( )<enter>); "共同的头文件 :ab MBc `ifndef COMMON_HEADER <cr>`define COMMON_HEADER<cr><cr>`define CYCLE 10<cr>`define HALF_CYCLE (CYCLE/2)<cr><cr>`define TB_BEGIN $display("=== BEGIN TESTBENCH %m ===\n");<cr>`define TB_END #`CYCLE $display("\n===== END TESTBENCH %m ===");<cr><cr>`endif """""""""""""""""""""""""""""""""预编译"""""""""""""""""""""""""""""""""" "延时宏定义 :ab YBYys `define DEL 1 "仿真精度 :ab YBYjd `timescale 1ns/1ps """"""""""""""""""""""""""""""""Testbench"""""""""""""""""""""""""""""""""" "产生时钟 :ab TBsz initial begin<enter>tb_clk = 0;<enter>end<enter>always #`HALF_CYCLE tb_clk = ~tb_clk; "产生复位信号 :ab TBfw initial begin<enter>tb_rst_n = 1;<enter>repeat(1) @( posedge tb_clk ) #1;<enter>tb_rst_n = 0;<enter>repeat(1) @( posedge tb_clk ) #1;<enter>tb_rst_n = 1;<enter>end "延时 :ab TBys repeat( 1 ) @( posedge tb_clk ) #1; "波形图 :ab TBbxt initial begin<enter>$dumpfile(" .vcd ");<enter>$dumpvars();<enter>end "随机数 :ab TBsjs integer seed;<enter>reg[31:0] num1;<enter>initial begin<enter>if ( !$value$plusargs("seed+%d", seed) ) begin<enter>seed = 0;<enter>end<enter>@(posedge tb_clk);<enter>#1;<enter>num1 = $random(seed);<enter>end "取对数,用来求位宽 :ab TBds function integer clogb2;<enter>input [31:0] value;<enter>begin<enter>value = value - 1;<enter>for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) begin<enter>value = value >> 1;<enter>end<enter>end<enter>endfunction "打开文件 :ab TBwj integer FILE;<enter> FILE=$fopen(" .txt ", "a+");<enter>$fdisplay(FILE, " = %h", );<enter>$fclose(FILE); "TB模板 :ab TBmb module _tb();<enter><enter> reg tb_clk <enter>reg tb_rst_n <enter><enter>task delay;<enter>input [31:0] num;<enter>begin<enter>repeat(num) @(posedge tb_clk);<enter>#1;<enter>end<enter>endtask<enter><enter>initial begin<enter>tb_clk = 0;<enter>end<enter>always #`HALF_CYCLE tb_clk = ~tb_clk;<enter><enter>initial begin<enter>tb_rst_n = 1;<enter>delay(1);<enter>tb_rst_n = 0;<enter>delay(1);<enter>tb_rst_n = 1;<enter>end<enter><enter>initial begin<enter>$dumpfile(" _tb.vcd ");<enter>$dumpvars();<enter>end<enter><enter>initial begin<enter>`TB_BEGIN<enter>delay(3);<enter><enter>`TB_END<enter>$finish;<enter>end<enter><enter><enter>endmodule :ab TBb `TB_BEGIN :ab TBe `TB_END "断言assert :ab TBas assert( tb_ == ) $strobe("%0d, !!TEST SUCCESS!!", $time);<enter>else $error("tb_ = %0d", tb_); "TB中initial块 :ab TBin initial begin<CR>`TB_BEGIN<CR><CR>`TB_END<CR>$finish;<CR>end """"""""""""""""""""""""""""""""注释"""""""""""""""""""""""""""""""""""""""" "注释头 :ab ZSt //*************************************************************<enter><enter>*@File name: <enter><enter>*@File type: <enter><enter>*@Version : 0.0.1<enter><enter>*@Author : Zehua Dong, HITWH<enter><enter>*@E-mail : hitdongzh@163.com<enter><enter>*@Date : <enter>*@Function : <enter><enter>*************************************************************<enter><enter> Head files<enter>`include "common.v"<enter><enter> Module definition "段注释 :ab ZSk /<enter>*Function Description:<enter>* <enter>* <enter>/// "端口注释 :ab ZSdk //===========================================================<enter>* Input and output ports<enter>* Internal signals<enter>=========================================================== "分割注释 :ab ZS //*******************************<enter><enter>******************************* """"""""""""""""""""""""""""""""任务"""""""""""""""""""""""""""""""""""""""" "延时任务 :ab RWys task delay;<enter>input [31:0] num;<enter>begin<enter>repeat(num) @(posedge tb_clk);<enter>#1;<enter>end<enter>endtask "任务模板 :ab RWmb task ;<enter>input [ :0] <enter>begin<enter>end<enter>endtask
上面的代码中新文件标题
那里,定义了代码的注释头,大家修改成自己的信息后,直接按F4即可插入。
此处给大家演示一下我平时写Verilog的步骤:
1、首先按F4,插入文件头,然后输入该文件的功能注释(对了我上面的演示忘记写模块名了哈哈哈,总是忘记,大家记得写呀)。
2、跳到最后一行,输入MBmk
,敲回车,就形成了一个模块的模板。
3、添加输入输出端口,clk和rst_n默认已经添加。请注意我的操作,在输入一个端口后,敲了很多空格(或者TAB),一个原因是美观,再者是为了方便写逗号,这样子你就可以通过列操作将逗号整齐的写到端口后面。但是对于某些软件来说,可能把空格也识别为端口名,所以这种做法要根据具体软件来决定是否使用。
为什么要将逗号写整齐呢?难道只是强迫症为了好看嘛?
当然不是,这样写端口,后面你在例化模块的时候就可以直接复制这里的代码,而不用手敲了。如下所示。
是不是方便了很多呢?
4、添加完端口名后,开始定义端口的输入输出,以及wire、reg等类型,只需要按yy
复制input clk;
那一行,然后有多少个端口就粘贴几次,快捷键为数字+p
,然后修改input
和output
关键字。当然信号位宽也要修改。
5、将改好的input
、output
的所有端口都复制一下,然后按p
进行粘贴,ctrl+q
列选,将input
、output
全部先改为wire,然后修改需要的端口为reg类型。
6、添加核心代码,通过GVIM中的别名,添加你想要的代码即可。
上述过程看着麻烦,其实等你实践的时候就知道有多爽了。比起你手动一行一行敲,这样可以提升你的编程效率,把时间花在刀刃上。
_vimrc文件路径:
:ab name code
:ab 为命令,name为你要制作的模板名字,code为代码,如果需要换行使用<enter>即可。
我的gvim自动缩进2空格,tab也为2空格,如果将代码复制进去格式不太好看的话可能是这个引起的,将以下代码复制到_vimrc文件
中即可:
"设置缩进
"设置Tab长度为2空格
set expandtab
set tabstop=2
"设置自动缩进长度为2空格
set shiftwidth=2
"继承前一行的缩进方式,适用于多行注释"
set autoindent
使用模板可以减少不必要的重复,大量缩短时间,希望我的分享对你有帮助,转载请说明出处~
从我的github上进行下载。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。