用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/Ljj05170930/verilog-code-plugin --skill new-verilog-project命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
创建 SystemVerilog 测试平台文件。触发词包括:创建TB、写testbench、新建测试平台、生成TB、写TB、创建仿真测试文件
编写和审查可综合的 Verilog RTL 代码。当用户要求编写、设计、实现、修复或审查任何 Verilog/RTL 模块、 硬件模块或数字逻辑时自动触发。触发词包括:写Verilog、写RTL、实现模块、设计电路、review代码、 审查Verilog、FSM、状态机、FIFO、pipeline、流水线、arbiter、仲裁器、counter、计数器、 shift register、移位寄存器、handshake、握手协议、AXI、APB、SPI、I2C、UART、 clock divider、分频器、debounce、去抖、edge detector、边沿检测、synchronizer、同步器、 dual-port RAM、双端口RAM。即使用户只说"写一个模块"或"实现这个功能"而没有显式提到"Verilog", 也应使用此 skill。涵盖新代码生成和已有 Verilog 代码的 review/debug。
基于 SOC 职业分类
| name | new-verilog-project |
| description | 新建 Verilog 仿真项目,搭建环境。触发词包括:新建项目、建立Verilog环境、初始化工程、搭建仿真环境、新建Verilog工程 |
在当前工作目录下创建完整的 Verilog 仿真项目结构。
./
├── RTL/ (仅在不存在时创建;已存在则保留原内容不动)
├── TB/
│ └── tb_top.sv (仅在 TB/ 内无仿真文件时由 tb-creator skill 生成)
├── .vscode/
│ └── tasks.json
├── .gitignore
├── gen_filelist.py
├── gen_dumpvars.py
├── clean.py
└── CLAUDE.md
{
"version": "2.0.0",
"tasks": [
{
"label": "Generate Filelist",
"type": "shell",
"command": "python",
"args": ["gen_filelist.py"],
"group": "build"
},
{
"label": "iverilog compile",
"type": "shell",
"command": "iverilog",
"args": [
"-o", "sim.vvp",
"-g2012",
"-f", "filelist.f"
],
"group": {
"kind": "build",
"isDefault": false
},
"problemMatcher": []
},
{
"label": "vvp run",
"type": "shell",
"command": "vvp sim.vvp -fst",
"group": {
"kind": "build",
"isDefault": false
},
"problemMatcher": []
},
{
"label": "Gen Dumpvars",
"type": "shell",
"command": "python",
"args": ["gen_dumpvars.py", "--patch"],
"group": "build",
"problemMatcher": []
},
{
"label": "clean",
"type": "shell",
"command": "python",
"args": ["clean.py"],
"group": "build",
"problemMatcher": []
},
{
"label": "compile and run",
"dependsOn": ["Generate Filelist","Gen Dumpvars","iverilog compile", "vvp run"],
"dependsOrder": "sequence",
"group": {
"kind": "build",
"isDefault": false
},
"problemMatcher": []
}
]
}
import os
extensions = ('.v', '.sv')
dirs = ['RTL', 'TB']
with open('filelist.f', 'w') as f:
for d in dirs:
if not os.path.exists(d):
continue
for root, _, files in os.walk(d):
for file in files:
if file.endswith(extensions):
path = os.path.join(root, file).replace('\\', '/')
f.write(path + '\n')
print("Generated filelist.f")
#!/usr/bin/env python3
"""
gen_dumpvars.py
自动扫描 RTL 文件中的非压缩数组,结合实例化层次,
生成 DUMP_ARRAY 宏调用,可选地直接更新 TB 的波形 initial 块。
用法:
python gen_dumpvars.py # 仅打印生成结果
python gen_dumpvars.py --patch # 同时更新 TB 文件
"""
import re, sys, argparse
from pathlib import Path
FILELIST = "filelist.f"
SV_KEYWORDS = {
'module','endmodule','input','output','inout','wire','reg','logic',
'integer','genvar','begin','end','if','else','for','always','initial',
'assign','parameter','localparam','generate','endgenerate','task',
'function','endtask','endfunction','case','casex','casez','endcase',
'posedge','negedge','repeat','while','fork','join','string','bit',
'byte','int','real','time','signed','unsigned','automatic',
'supply0',,,,,,,
}
():
src = re.sub(, , src)
src = re.sub(, , src, flags=re.S)
src
():
files = []
(path) f:
line f:
line = line.strip().replace(, )
line line.startswith():
files.append(line)
files
():
params = {}
m re.finditer(
,
body
):
name = m.group()
expr = m.group().strip()
:
val = (expr, {: {}}, (params))
params[name] = (val)
Exception:
params
():
:
((expr.strip(), {: {}}, params))
Exception:
():
params = extract_params(body)
arrays = []
a re.finditer(
,
body
):
name = a.group()
name SV_KEYWORDS:
hi = resolve(a.group(), params)
lo = resolve(a.group(), params)
hi lo :
arrays.append((name, (hi - lo) + ))
gen_insts = []
gen re.finditer(, body, re.S):
blk re.finditer(
,
gen.group(), re.S
):
label = blk.group()
blk_body = blk.group()
m re.finditer(
, blk_body
):
mtype, iname = m.group(), m.group()
mtype SV_KEYWORDS iname SV_KEYWORDS:
gen_insts.append((label, mtype, iname))
body_no_gen = re.sub(, , body, flags=re.S)
reg_insts = []
m re.finditer(
, body_no_gen
):
mtype, iname = m.group(), m.group()
mtype SV_KEYWORDS iname SV_KEYWORDS:
reg_insts.append((mtype, iname))
arrays, reg_insts, gen_insts
():
all_mods = {}
f files:
:
src = Path(f).read_text(encoding=, errors=)
clean = strip_comments(src)
m re.finditer(
, clean, re.S
):
name, body = m.group(), m.group()
all_mods[name] = parse_module(body)
Exception e:
(, file=sys.stderr)
all_mods
():
results = []
visited = ()
():
key = (mod_name, prefix)
key visited mod_name all_mods:
visited.add(key)
arrays, reg_insts, gen_insts = all_mods[mod_name]
arr_name, size arrays:
results.append((, size))
mtype, iname reg_insts:
mtype all_mods:
dfs(mtype, )
label, mtype, iname gen_insts:
mtype all_mods:
dfs(mtype, )
mtype, iname start_insts:
mtype all_mods:
dfs(mtype, iname)
results
():
lines = [
,
,
,
]
path, size entries:
lines.append()
lines.append()
.join(lines)
():
src = Path(tb_path).read_text(encoding=)
lines = src.split()
start_i = end_i =
i, line (lines):
re.search(, line):
window = .join(lines[i: i + ])
window:
start_i = i
depth =
j (i, (lines)):
depth += (re.findall(, lines[j]))
depth -= (re.findall(, lines[j]))
depth == j > i:
end_i = j
start_i end_i :
new_lines = (lines[:start_i]
+ new_block.split()
+ lines[end_i + :])
Path(tb_path).write_text(.join(new_lines), encoding=)
()
:
endmod_i =
i, line (lines):
re.search(, line):
endmod_i = i
endmod_i :
new_lines = (lines[:endmod_i]
+ []
+ new_block.split()
+ []
+ lines[endmod_i:])
Path(tb_path).write_text(.join(new_lines), encoding=)
()
:
(, file=sys.stderr)
():
ap = argparse.ArgumentParser(description=)
ap.add_argument(, action=,
=)
args = ap.parse_args()
files = read_filelist()
tb_files = [f f files Path(f).stem.startswith()]
all_mods = parse_all(files)
tb_mod =
start_insts = []
tf tb_files:
src = Path(tf).read_text(encoding=, errors=)
clean = strip_comments(src)
m = re.search(, clean, re.S)
m:
tb_mod = m.group()
_, reg_insts, _ = parse_module(m.group())
mtype, iname reg_insts:
mtype all_mods mtype != tb_mod:
start_insts.append((mtype, iname))
tb_mod:
(, file=sys.stderr)
sys.exit()
entries = collect(all_mods, start_insts)
seen, unique = (), []
path, size entries:
path seen:
seen.add(path)
unique.append((path, size))
block = gen_block(tb_mod, unique)
()
(block)
()
args.patch:
tf tb_files:
patch_tb(tf, block)
__name__ == :
main()
import os
import glob
import shutil
for fst in glob.glob("*.fst"):
base = os.path.splitext(fst)[0]
for ext in [".fst", ".vcd"]:
target = base + ext
if os.path.exists(target):
os.remove(target)
print(f"Deleted: {target}")
for f in ["filelist.f", "sim.vvp"]:
if os.path.exists(f):
os.remove(f)
print(f"Deleted: {f}")
for cache_dir in glob.glob("**/__pycache__", recursive=True):
shutil.rmtree(cache_dir, ignore_errors=True)
print(f"Deleted: {cache_dir}")
for pyc in glob.glob("**/*.pyc", recursive=True):
os.remove(pyc)
print(f"Deleted: {pyc}")
print("Clean done.")
# 仿真产物
*.fst
*.vvp
filelist.f
# Python 缓存
__pycache__/
*.pyc
## 回答规范
每次回答结束后,必须在末尾附上:
- 当前使用的模型名称
- 当前的effort 级别(如果有)
RTL 目录:使用 Glob 检查 RTL/ 下是否有任意文件:
RTL/.gitkeep(空文件,确保目录存在)RTL/ 做任何操作使用 Write 工具依次创建以下文件(直接覆盖,不询问):
.vscode/tasks.json.gitignoregen_filelist.pygen_dumpvars.pyclean.pyCLAUDE.md.claude/settings.local.json(内容如下,用于自动授权 iverilog 编译和仿真命令){
"permissions": {
"allow": [
"Bash(iverilog -o sim.vvp -g2012 -f filelist.f)",
"Bash(vvp sim.vvp -fst)"
]
}
}
TB 目录:使用 Glob 检查 TB/ 下是否存在 .v 或 .sv 文件:
tb-creator skill 生成 TB/tb_top.svTB/ 做任何操作tasks.json:创建或覆盖 .vscode/tasks.json,不询问用户任何问题
全部完成后,告知用户"Verilog 项目环境已就绪",并列出创建/跳过的文件清单。