verilogのvim用スニペットファイル書いた

僕はvimのsnippetプラグインにShougoさんのneosnippet を使っています.
neosnippetには,CやRubyPythonなどの人気のある言語のsnippetファイルは同梱されているのですが,
さすがにverilog HDL用のsnippetファイルは用意されていません.
そもそも,vimはhdl系の便利プラグインが少ない気がします(emacsにはverilog-modeとかある).
まぁ探せばきっとオレオレスクリプトは転がってるんでしょうが,
neosnippetのスニペットファイルは非常に簡単に作成できそうなので,
どうせならと作ってみました.

verilog.snip

snippet   module
abbr    module() endmodule;
    module ${1:module_name} (${2:port_list}
            );
        ${3:code};

    endmodule//$1${4}

snippet reg
abbr    reg;
    reg ${1:#:reg_name};

snippet regarray
abbr    [] reg;
    reg [${1}:${2:#:0}] ${3:#:reg_name};

snippet regmem
abbr    [] reg [];
    reg [${1}:${2:#:0}] ${3:#:reg_name} [${4}:${5:#:0}];

snippet wire
abbr    wire;
    wire ${1:wire_name};

snippet wirearray
abbr    [] wire;
    wire [${1}:${2:#:0}] ${3:wire_name};

snippet input
abbr    input;
    input ${1:input_name};

snippet inputarray
abbr    [] input;
    input  [${1}:${2:#:0}] ${3:input_name};

snippet output
abbr    output;
    output ${1:output_name};

snippet outputarray
abbr    [] output;
    output [${1}:${2:#:0}] ${3:output_name};

snippet function
abbr    function  endfunction;
    function ${1:#:function_name};
        ${2:portlist};
        begin
            ${3:code};
        end
    endfunction //$1

snippet casex
alias mul mux sel mul
abbr    casex endcase
    casex(${1:SEL})
        ${2:case_input}: ${3:case_output} = ${4};
        $2: $3 = ${5};
        $2: $3 = ${6};
        $2: $3 = ${7};
        default: $2: $3 = {};
    endcase //casex($1)

snippet always
abbr    always() begin end
    always@(${1:sensitivity_list}) begin
        ${2:code}
    end

snippet always_posCLK
abbr    always(posedge clock) begin end
    always@(posedge clock) begin
        ${1:code}
    end

snippet if
abbr    if() begin end
    if(${1:#:condition}) begin
       ${2:code}
    end${3}

snippet if_elif_else
abbr    if() else if() else
    if(${1:#:condition1}) begin
       ${2:code1}
    end else if(${3:#:condition2}) begin
       ${4:code2}
    end else begin
       ${5:code3}
    end

snippet if_else
abbr    if() else end
    if(${1:#:condition}) begin
       ${2:code1}
    end else begin
       ${3:code2}
    end

snippet initial
abbr    initial begin end
    initial begin
       ${1:code}
    end

snippet ternary
abbr    a?b:c
    ${1:a} ? ${2:b} : ${3:c}

snippet parameter
abbr parameter
    parameter ${1:parameter_name} = ${2:parameter_val};

snippet define
abbr define
    `define ${1:define_name} ${2:define_val};

snippet blockram_read_first
alias   bram_read_first
abbr    BlockRAM
    always @(posedge ${1:clock}) begin
        if (${2:en}) begin
            if (${3:we}) ${4:RAM}[${5:addr}]<=${6:di};
            ${6:do} <= $4[$5];
        end
    end${0}

snippet blockram_write_first
alias   bram_write_firtst
abbr    BlockRAM
    always @(posedge ${1:clock}) begin
        if (${2:en}) begin
            if (${3:we}) begin
                ${4:RAM}[${5:addr}]<=${6:di};
                ${7:do} <= $6;
            end else $7 <= $4[$5];
        end
    end${0}
    
snippet blockram_no_change
alias   bram_no_change
abbr    BlockRAM
    always @(posedge ${1:clock}) begin
        if (${2:en}) begin
            if (${3:we}) ${4:RAM}[${5:addr}]<=${6:di};
            end ${7:do} <= $4[$5];
        end
    end${0}
  • module endmodule展開
  • register系の展開
  • wire系の展開
  • input/output系の展開
  • parameter defineの展開
  • function casex ifelifelse always initialの展開
  • blockramの展開

ができるようになっています.
最近書いたverilogコード見ながら作ったので,
verilogスニペットでなんでこれがねぇんだ.」 みたいなものがあるかもしれません.
snippetファイル書いてみた所感としては

  • すごく簡単にわかりやすく書ける.Shougoさんは天才や.
  • ドキュメント読んで無かったからスニペットファイル内はハードタブじゃないと,補完後のインデントがうまくいかないのに気づかなかった.
  • だんだん,補完機能との境界がわからなくなった(regとか別にsnippetにしなくてもいいよね…).
  • あれが便利これが便利,で大きくするよりも汎用性持たせた方がいいと思う(スニペットを誤爆しそうになる).
    • 枠組みとなるスニペットファイルを作って,その中で小さいスニペットを一杯展開していくのがいい.
    • 例えば,functionの中にcasex入れたセレクターを作るよりも,function展開してから中でcasex展開したほうが良さげ.
    • 後,moduleのポートリストに最初からinput/output入れとくのもやめといた.

これで辛く厳しいverilogコーディングも少しはましになるとおもいます!