{   
    "counter": {
        "prefix": "counter",
        "body": [
            "//define the time counter",
            "parameter       SET_TIME = $1'd$4;",
            "reg [${1:32}:0]      count$2;",
            "reg             ${3:impulse};",
            "always@(posedge clock) begin",
            "    if (count$2 == SET_TIME) begin",
            "        count$2 <= $1'd0;",
            "        $3 <= 1'd1;",
            "    end",
            "    else begin",
            "        count$2 <= count$2 + 1'd1;",
            "        $3 <= 1'd0;",
            "    end",
            "end"
        ]
    },

    "divclk": {
        "prefix": "div",
        "body": [
            "reg [${1:3}:0] count$2;",
            "reg       clk_div$2;",
            "always@(posedge ${3:clock}) begin",
            "    if (count$2 == ${4:3}) begin",
            "        count$2 <= $1'd0;",
            "        clk_div$2 <= ~clk_div$2;",
            "    end",
            "    else begin",
            "        count$2 <= count$2 + 1'd1;",
            "    end",
            "end"
        ]
    },

    "lock": {
        "prefix": "lock",
        "body": [
            "reg  gate$2;",
            "reg  gate$2_buf;",
    
            "wire gate$2_pos =   gate$2 & ~gate$2_buf;",
            "wire gate$2_neg =  ~gate$2 &  gate$2_buf;",
    
            "always@(posedge clock) begin",
            "   gate$2 <= ${1:signal};",
            "   gate$2_buf <= gate$2;",
            "end"
        ]
    },

    "posedge": {
        "prefix": "pos",
        "body": [
            "posedge"
        ]
    },

    "negedge": {
        "prefix": "neg",
        "body": [
            "negedge"
        ]
    },

    "resetn": {
        "prefix": "resetn",
        "body": [
            "reg  rst_n_s1, rst_n_s2;",
            "wire sys_rstn",
            "always @ (posedge clock or negedge rstn) begin",
            "    if (rstn) begin",
            "        rst_n_s2 <= 1'b0;",
            "        rst_n_s1 <= 1'b0;",
            "    end",
            "        rst_n_s1 <= 1'b1;",
            "        rst_n_s2 <= rst_n_s1;",
            "    end",
            "end",
            "assign sys_rstn = rst_n_s2;"
        ],
        "description" : "Asynchronous sys_rstn synchronous release (intel device)"
    },

    "reset": {
        "prefix": "reset",
        "body": [
            "reg  rst_s1, rst_s2;",
            "wire sys_rst",
            "always @ (posedge clock or posedge reset) begin",
            "    if (reset) begin",
            "        rst_s2 <= 1'b0;",
            "        rst_s1 <= 1'b0;",
            "    end",
            "        rst_s1 <= 1'b1;",
            "        rst_s2 <= rst_s1;",
            "    end",
            "end",
            "assign sys_rst = rst_s2;"
        ],
        "description" : "Asynchronous reset synchronous release (xilinx device)"
    },
        
    "initial sim": {
        "prefix": "inits",
        "body": [
            "initial begin",
            "   \\$dumpfile(\"wave.vcd\");",
            "   \\$dumpvars(0, ${1:testbench});",                     
            "   #6000 \\$finish;",                      
            "end"
        ],
        "description": "initial for simulation"
    },

    "initial array": {
        "prefix": "inita",
        "body": [
            "integer ${1:i};",
            "initial begin",
            "   for ($1 = 0; $1<${2:range}; $1=$1+1) begin",
            "        ${3:data}[$1] = 0;",
            "    end",   
            "end"
        ],
        "description": "initial for a array"
    },

    "debug": {
        "prefix": "debug",
        "body": ["(* mark_debug = \"true\" *)"]
    },

    "time": {
        "prefix": "time",
        "body": ["`timescale 1ns / 1ps"]
    },

    "assign": {
        "prefix": "assign",
        "body": ["assign $1 = $2;"]
    },

    "always_ff block": {
        "prefix": "ff",
        "body": [
            "always_ff @( ${1:clock} ) begin : ${2:blockName}",
            "    $0;",
            "end"
        ],
        "description": "Insert an always_ff block"
    },

    "always_comb block": {
        "prefix": "comb",
        "body": [
            "always_comb begin : ${1:blockName}",
            "    $0;",
            "end"
        ],
        "description": "Insert an always_comb block"
    },

    "always": {
        "prefix": "alw",
        "body": [
            "always @(*) begin",
            "    $1;",
            "end"
        ],
        "description": "always @(*)"
    },

    "alwaysposclk": {
        "prefix": "alclk",
        "body": [
            "always @(posedge clock) begin",
            "    $1;",
            "end"
        ],
        "description": "always @(posedge clock) directly"
    },

    "alwayssyncrst": {
        "prefix": "alsync",
        "body": [
            "always @(posedge clock) begin",
            "    if(reset) begin",
            "        $1 <= 0;",
            "    end",
            "    else begin",
            "        $2 <= $3;",
            "    end",
            "end"
        ],
        "description": "synchronous rst (xilinx device)"
    },

    "alwaysasyncrst": {
        "prefix": "alasync",
        "body": [
            "always @(posedge clock or posedge reset) begin",
            "    if(reset) begin",
            "        $1 <= 0;",
            "    end",
            "    else begin",
            "        $2 <= $3;",
            "    end",
            "end"
        ],
        "description": "asynchronous rst (xilinx device)"
    },

    "alwayssyncrstn": {
        "prefix": "alsyncn",
        "body": [
            "always @(posedge clock) begin",
            "    if(!rstn) begin",
            "        $1 <= 0;",
            "    end",
            "    else begin",
            "        $2 <= $3;",
            "    end",
            "end"
        ],
        "description": "synchronous rstn (intel device)"
    },

    "alwaysasyncrstn": {
        "prefix": "alasyncn",
        "body": [
            "always @(posedge clock or negedge rstn) begin",
            "    if(!rstn) begin",
            "        $1 <= 0;",
            "    end",
            "    else begin",
            "        $2 <= $3;",
            "    end",
            "end"
        ],
        "description": "asynchronous rstn (intel device)"
    },

    "beginend": {
        "prefix": "beginend",
        "body": [
            "begin",
            "    $1",
            "end"
        ],
        "description": "begin ... end"
    },

    "case": {
        "prefix": "case",
        "body": [
            "case (${1:conditions})",
            "    $2: $3",
            "\tdefault: $4",
            "endcase"
        ],
        "description": "case () ... endcase"
    },

    "module with parameters": {
        "prefix": "modp",
        "body": [
            "module ${1:name} #(",
            "    parameter    IWIDTH = ${2:12},",
            "    parameter    OWIDTH = $2",
            ") (",
            "    input      clock,",
            "    input      reset,",
            "    input  [IWIDTH - 1 : 0] ${3:data_i},",
            "    output [OWIDTH - 1 : 0] ${4:data_o}",
            ");",
            "    $5",
            "endmodule  //$1\n"
        ],
        "description": "Insert a module with parameter"
    },

    "module without parameters": {
        "prefix": "mod",
        "body": [
            "module ${1:moduleName} (",
            "    input      clock,",
            "    input      reset,",
            "    $2",
            ");",
            "    $3",
            "endmodule //$1\n"
        ],
        "description": "Insert a module without parameter"
    },

    "simple module": {
        "prefix": "module",
        "body": [
            "module ${1:moduleName}($2);",
            "    $3",
            "endmodule //$1\n"
        ],
        "description": "Insert a common module"
    },
    
    "generate_for": {
        "prefix": "genfor",
        "body": [
            "genvar ${1:i};",
            "generate for($1 = 0 ; $1 < $2; $1 = $1 + 1) begin : ${3:U}",
            "    $4",
            "end",
            "endgenerate"
        ]
    },
    
    "generate_if": {
        "prefix": "genif",
        "body": [
            "generate if(${1:conditional}) begin : ${2:U}",
            "    ${3:}",
            "end",
            "endgenerate"
        ]
    },
    
    "generate_case": {
        "prefix": "gencase",
        "body": [
            "generate",
            "case (${1:NUM})",
            "32'd1 : begin : ${2:case1_name}",
            "$3",
            "        end",
            "32'd2 : begin : ${4:case1_name}",
            "$5",
            "        end",
            "default : begin : NOP end",
            "endcase",
            "endgenerate"
        ]
    },    

    "if block": {
        "prefix": "if",
        "body": [
            "if (${1:conditions}) begin",
            "    $0",
            "end"
        ],
        "description": "Insert a if block"
    },

    "include": {
		"prefix": "include",
		"body": [
			"`include \"$1\""
		],
		"description": "`include \"..\""
	},

    "define": {
		"prefix": "define",
		"body": [
			"`define $1 $2"
		],
		"description": "`define var = val"
	},

	"parameter": {
		"prefix": "param",
		"body": [
			"parameter $1 = $2;"
		],
		"description": "paramter var = val;"
	},

    "localparam": {
		"prefix": "param",
		"body": [
			"localparam $1 = $2;"
		],
		"description": "localparam var = val;"
	},

	"ifelse": {
		"prefix": "ifelse",
		"body": [
			"if (${1:conditions}) begin",
			"    $2",
			"end",
            "else begin",
			"    $3",
            "end"
		],
		"description": "if (...) begin ... end else begin ... end"
	},

    "else": {
		"prefix": "else",
		"body": [
            "else begin",
			"    $1",
            "end"
		],
		"description": "else begin ... end"
	},

    "elseif": {
		"prefix": "elif",
		"body": [
            "else if(${1:conditions}) begin",
			"    $2",
            "end"
		],
		"description": "else if(conditions) begin ... end"
	},

    "for loop": {
		"prefix": "for",
		"body": [
			"for ($1 = $2; $3; $4) begin",
			"    $0",
			"end"
		],
		"description": "for (...) begin ... end"
	},

	"while loop": {
		"prefix": "while",
		"body": [
			"while ($1) begin",
			"    $2",
			"end"
		],
		"description": "while (...) begin ... end"
	},

	"function": {
		"prefix": "function",
		"body": [
			"function $1;",
			"    $2;",
			"    $3",
			"endfunction"
		],
		"description": "function (...) ... endfunction"
	},

	"bit":{
		"prefix":"bit",
		"body":"bit"
	},

	"int":{
		"prefix":"int",
		"body":"int"
	},

	"byte":{
		"prefix":"byte",
		"body":"byte"
	},

	"logic":{
		"prefix":"logic",
		"body":"logic"
	},

    "reg": {
        "prefix": "reg",
        "body": [
            "reg $1;"
        ],
        "description": "reg reg_name;"
    },
    
    "regarray": {
        "prefix": "rega",
        "body": [
            "reg [$1:$2] $3;"
        ],
        "description": "reg [N:0] reg_name;"
    },
    
    "regmemory": {
        "prefix": "regm",
        "body": [
            "reg [$1:$2] $3 [$4:$5];"
        ],
        "description": "reg [N:0] reg_name [0:M];"
    },
    
    "wire": {
        "prefix": "wire",
        "body": [
            "wire $1;"
        ],
        "description": "wire wire_name;"
    },
    
    "wirearray": {
        "prefix": "wirea",
        "body": [
            "wire [$1:$2] $3;"
        ],
        "description": "wire [N:0] wire_name;"
    },

	"packed":{
		"prefix":"packed",
		"body":"packed"
	},

	"this":{
		"prefix": "this",
		"body": "this"
	},

	"array":{
		"prefix":"array",
		"body":"[${1:8}:${2:0}]$0",
		"description":"insert [x:y]"
	},

	"typedef struct packed":{
		"prefix":"typedefstructpacked",
		"body":[
			"typedef struct packed {",
			"    $0",
			"} ${1:struct_name};"
		],
		"description":"typedef struct packed { ... } name"
	},

	"class":{
		"prefix":"class",
		"body":[
			"class ${1:className};",
			"\tfunction new();",
			"        $0",
			"\tendfunction //new()",
			"endclass //${1}"
		],
		"description":"class name; ... endclass"
	},

	"class extends":{
		"prefix":"classextends",
		"body":[
			"class ${1:className} extends ${2:superClass};",
			"\tfunction new();",
			"        $0",
			"\tendfunction //new()",
			"endclass //${1} extends ${2}"
		],
		"description":"class name extends super; ... endclass"
	},

	"task":{
		"prefix":"task",
		"body":[
			"task ${1:automatic} ${2:taskName}(${3:arguments});",
			"    $0",
			"endtask //${1}"
		],
		"description":"task name; ... endtask"
	},

	"interface":{
		"prefix":"interface",
		"body":[
			"interface ${1:interfacename};",
			"    $0",
			"endinterface //${1}"
		],
		"description":"interface name; ... endinterface"
	},

	"set Module":{
		"prefix":"setmodule",
		"body":[
			"${1:mod_name} ${2:instance_name} (${3:.*}$0);"
		],
		"description":"set module, mod i0 (.*);"
	},

	"typedef enum":{
		"prefix":"typedefenum",
		"body":[
			"typedef enum ${1:data_type} { $0 } ${2:name};"
		],
		"description":"typedef enum (data_type) { ... } name"
	},

	"enum":{
		"prefix":"enum",
		"body":[
			"enum ${1:data_type} { $0 } ${2:name}"
		],
		"description":"enum (data_type) { ... } name"
	},

	"queue":{
		"prefix":"queue",
		"body":"${1:data_type} ${2:queue_name}[$];",
		"description":"insert queue."
	},

	"mailbox":{
		"prefix":"mailbox",
		"body":[
			"mailbox mbx",
			"${1:mbx = new();}"
		],
		"description":"insert mailbox instance"
	},

	"Associative array":{
		"prefix":"AA",
		"body":"${1:data_type} ${2:name}[${3:index_type}];$0",
		"description":"insert Associative array(AA)."
	},

	"assert":{
		"prefix": "assert",
		"body": [
			"assert (${1:condition}) ${2}",
			"else   ${3:error_process}"
		],
		"description": "insert assert() ... else ..."
	},

	"fork-join":{
		"prefix": "forkjoin",
		"body": [
			"fork",
			"    $0",
			"join"
		],
		"description": "fork ... join"
	},

	"forever":{
		"prefix": "forever",
		"body": [
			"forever begin",
			"    $0",
			"end"
		],
		"description": "forever begin ... end"
	},

    "signed":{
		"prefix": "$signed",
		"body": [
			"\\$signed($1)"
		],
		"description": ""
	},

    "unsigned":{
		"prefix": "$unsigned",
		"body": [
			"\\$unsigned($1)"
		],
		"description": ""
	},

    "wavedrom comment": {
        "prefix" : "wavedrom",
        "body": [
            "/* @wavedrom",
            "{",
            "    $1",
            "}",
            "*/"
        ]
    }
}