Skip to main content

verilog-code

编写和审查可综合的 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。

Quellinformationen

Repository
Ljj05170930/verilog-code-plugin
Letzte Quellaktivität
12. April 2026 um 11:49
Erkannte Sprache von SKILL.md
Chinesisch
Sterne
0
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
4 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
verilog-code
description
编写和审查可综合的 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。
user-invocable
true
# Verilog RTL 编码指南 ## 1. 模式检测 根据用户意图判断工作模式: **WRITE 模式**(用户要求创建/实现/设计模块): - 遵循下方所有编码规则 - 如果要实现的模块匹配已知设计模式(FSM、FIFO、pipeline 等),先读取 `references/design-patterns.md` 中对应章节作为起点 **REVIEW 模式**(用户要求检查/审查/debug 已有代码): - 读取 `references/review-checklist.md`,按照结构化流程逐项审查 - 如果发现的问题匹配已知错误类型,参考 `references/common-mistakes.md` --- ## 2. 硬件思维 — Verilog 不是软件 这是写出正确 Verilog 的根基。在写每一行代码前,用以下思维替代软件的顺序执行模型: **并行执行**:每个 `always` 块是一个独立的硬件电路,所有 `always` 块同时运行。它们不是"按顺序执行的函数",而是"同时工作的独立电路"。 **非阻塞赋值 `<=`(时钟块)**:在 `always @(posedge clk)` 中,所有 RHS 在时钟沿**同时采样**,然后所有 LHS **同时更新**。这意味着: ```verilog always @(posedge clk) begin a <= b; // a 拿到的是 b 的旧值 b <= a; // b 拿到的是 a 的旧值 → 实现了交换 end ``` 这不是"先执行第一行再执行第二行",而是一个寄存器组在时钟沿同时锁存。 **阻塞赋值 `=`(组合块)**:在 `always @(*)` 中使用,描述组合逻辑的连线关系。虽然有执行顺序,但综合结果是同一个门级电路。 **绝对禁止混用**:同一个 `always` 块内不得同时出现 `<=` 和 `=`。时钟块用 `<=`,组合块用 `=`。 **`wire` 是导线,`reg` 是存储或组合输出**:`reg` 不一定是寄存器——在组合 `always` 块中的 `reg` 综合后是纯组合逻辑。关键在于它被 `always` 块驱动。 --- ## 3. 可综合性规则 RTL 代码中**禁止使用**以下仿真专用语法: | 禁止的语法 | 原因 | 替代方案 | |---|---|---| | `initial` 块 | 无硬件对应物 | 使用复位信号初始化 | | `#10` 等延时 | 不可综合 | 用时钟周期控制时序 | | `$display`, `$monitor`, `$finish` | 系统任务 | 仅在 TB 中使用 | | `fork`/`join` | 无硬件对应物 | 用并行 always 块 | | `force`/`release`/`deassign` | 不可综合 | 用正常赋值逻辑 | **必须遵守的规则**: - **完整条件**:所有 `if` 必须有 `else`,所有 `case` 必须有 `default`。不完整的条件会推断出 latch,这几乎从来不是你想要的 - **敏感列表**:组合逻辑用 `always @(*)`,不要手动列出信号。时序逻辑用 `always @(posedge clk or negedge rst_n)`(异步复位)或 `always @(posedge clk)`(同步复位) - **复位**:每个触发器都必须有复位值。使用 active-low 异步复位 (`rst_n`) 作为项目惯例 - **单驱动**:同一信号只能在一个 `always` 块或一条 `assign` 中驱动,不可多驱动 - **无内部三态**:内部信号不要用三态,用 mux 代替 - **整数除法**:非 2 的幂的除法和取模通常不可综合,用移位代替 --- ## 4. 模块结构模板 所有模块遵循以下统一结构,与项目现有风格保持一致: ```verilog module module_name #( parameter DATA_WIDTH = 8, parameter ADDR_WIDTH = 4 ) ( input wire clk, input wire rst_n, // ---- Input ports ------------------------------------------------ input wire [DATA_WIDTH-1:0] data_in, input wire valid_in, // ---- Output ports ----------------------------------------------- output reg [DATA_WIDTH-1:0] data_out, output reg valid_out ); // ========================================================================= // Local parameters // ========================================================================= localparam DEPTH = 1 << ADDR_WIDTH; // ========================================================================= // Internal signals // ========================================================================= reg [DATA_WIDTH-1:0] data_reg; wire some_condition; // ========================================================================= // Combinational logic // ========================================================================= assign some_condition = /* ... */; // ========================================================================= // Sequential logic // ========================================================================= always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_reg <= {DATA_WIDTH{1'b0}}; data_out <= {DATA_WIDTH{1'b0}}; valid_out <= 1'b0; end else begin // 功能逻辑 end end endmodule ``` **结构约定**: - `clk` 和 `rst_n` 始终是前两个端口 - 端口用 `// ---- 注释行 ----` 分组 - 模块内部按区域划分:Local parameters → Internal signals → Combinational → Sequential - 区域之间用 `// ===` 注释分隔(匹配项目现有风格) - 参数名 `UPPER_SNAKE_CASE`,信号名 `snake_case`,模块名 `snake_case` - Active-low 信号加 `_n` 后缀(如 `rst_n`, `cs_n`) - 时钟信号加 `clk` 前缀(如 `clk`, `clk_div2`) --- ## 5. 关键编码规则 ### 5.1 计数器边界 计数器 wrap-around 比较 `MAX_VAL - 1`,不是 `MAX_VAL`。这是最常见的 off-by-one 错误: ```verilog // 正确:0 到 N-1 共 N 个计数 if (count == MAX_COUNT - 1) begin count <= {WIDTH{1'b0}}; end else begin count <= count + 1'b1; end ``` ### 5.2 位宽匹配 显式指定所有字面量的位宽,不要使用无宽度字面量: ```verilog // 错误 count <= count + 1; // 1 是 32 位整数 data <= 0; // 0 是 32 位整数 // 正确 count <= count + 1'b1; data <= {DATA_WIDTH{1'b0}}; ``` 使用 `$clog2()` 从深度推导地址宽度: ```verilog localparam ADDR_WIDTH = $clog2(DEPTH); ``` ### 5.3 复位方法论 异步 active-low 复位,复位分支始终放在 if-else 的第一个分支: ```verilog always @(posedge clk or negedge rst_n) begin if (!rst_n) begin // 所有寄存器的复位值 — 不要漏掉任何一个 state <= IDLE; count <= {WIDTH{1'b0}}; data_out <= {DATA_WIDTH{1'b0}}; valid_out <= 1'b0; end else begin // 正常功能逻辑 end end ``` ### 5.4 FSM 编码 使用 `localparam` 定义状态,不要用 `` `define``。始终有 `default` 分支回到安全状态: ```verilog localparam [1:0] S_IDLE = 2'd0, S_LOAD = 2'd1, S_PROC = 2'd2, S_DONE = 2'd3; reg [1:0] state, state_next; ``` 组合逻辑中的 next-state 信号用 `_next` 后缀,寄存器版本不加后缀。 ### 5.5 流水线规则 - 所有数据信号必须经过**相同级数**的流水线寄存器 - `valid` 信号必须与数据**同步流水** - 添加反压(backpressure)时,stall 信号必须同时冻结数据和 valid ### 5.6 Valid/Ready 握手协议 - `valid` 不能依赖 `ready`(发送端不看接收端是否准备好就可以发起请求) - `ready` 可以依赖 `valid` - `valid` 一旦拉高,在 `ready` 为低期间不得撤回 - `valid` 为高期间数据必须保持稳定 ### 5.7 内存/数组声明 ```verilog // 正确:使用 [0:DEPTH-1] 显式声明范围 reg [DATA_WIDTH-1:0] mem [0:DEPTH-1]; // 读写模式 always @(posedge clk) begin if (wr_en) mem[wr_addr] <= wr_data; rd_data <= mem[rd_addr]; // 读优先,1 周期延迟 end ``` --- ## 6. 输出自检清单 生成 Verilog 代码后,在呈现给用户之前,逐条对照以下清单验证: - [ ] 每个 `if` 都有 `else`,每个 `case` 都有 `default` - [ ] 没有 `initial` 块、`#delay`、系统任务(`$display` 等) - [ ] 复位分支中列出了所有寄存器的复位值,无遗漏 - [ ] 时钟 `always` 块只用 `<=`,组合 `always` 块只用 `=`,无混用 - [ ] 所有字面量显式指定位宽(无裸 `0`、`1` 等整数字面量) - [ ] 组合逻辑敏感列表是 `@(*)`,时序逻辑是 `@(posedge clk or negedge rst_n)` - [ ] 计数器边界条件正确(比较 N-1 而不是 N,注意 off-by-one) - [ ] 无多驱动信号(同一信号在多个 always/assign 中赋值) - [ ] `clk`, `rst_n` 是模块的前两个端口 - [ ] 参数名 `UPPER_SNAKE_CASE`,信号名 `snake_case` - [ ] 组合 always 块中的信号在所有分支中都有赋值(防止 latch 推断) - [ ] FSM 的 case 语句有 default 分支,且 default 回到安全状态 --- ## 7. 参考文件 以下参考文件在需要时读取,不要每次都全部加载: - **`references/design-patterns.md`** — 当实现的模块匹配以下任何模式时读取: FSM、FIFO、pipeline、handshake/skid buffer、arbiter、counter、shift register、 edge detector、debouncer、clock divider、dual-port RAM、synchronizer - **`references/common-mistakes.md`** — 当调试综合错误、仿真不匹配、或需要理解某个 常见 Verilog 陷阱时读取 - **`references/review-checklist.md`** — 在 REVIEW 模式下读取,按照结构化流程审查代码 --- ## 8. Icarus Verilog 兼容性 RTL 代码使用 Verilog-2001/2005 语法,确保与 Icarus Verilog (`iverilog -g2012`) 兼容: - RTL 中使用 `reg`/`wire`,不要用 SystemVerilog 的 `logic` - 不要在 RTL 中使用 `always_ff`/`always_comb`/`always_latch`(这些是 SV 语法,仅 TB 中使用) - `$clog2()` 在 `-g2012` 模式下支持 - `generate` 块正常支持 - TB 文件是 SystemVerilog (`.sv`),由 `tb-creator` skill 处理,本 skill 不管 TB ## 9. 项目工作流提示 生成 RTL 文件后,提醒用户: - RTL 文件放在 `RTL/` 目录下 - 运行 VS Code 的 "compile and run" 任务来编译和仿真 - 如果有新的 RTL 文件,`gen_filelist.py` 会自动扫描 `RTL/` 目录
Auf GitHub ansehen