--- name: design-format description: "Constrains Verilog/SystemVerilog format quality for generated or edited .v/.sv files. Enforces 4-space indent, no alignment padding, compact if(/for(/case(, always_ff/always_comb, localparam vs define.vh, ternary (x)? a : b, centered section headers, and a four-field file banner. Use when generating, writing, or reformatting Verilog or SystemVerilog, including RTL and testbench, and when dv-format or other HDL generators write files." --- # design-format 產生或修改任何 `.v` / `.sv` 時**全程強制執行**。不管驗證邏輯、合成語意、或 TB 寫法。 不管:負緣送、`drive_reset`、FSDB/SDF、PATTERN port 反向(`dv-format`);DUT 可合成約束(`rtl-constraint`)。 --- ## 縮排 - 一律 **4 個空格**,禁止 tab。 - 巢狀每層 +4 spaces。 - `` `ifdef `` / `` `else `` / `` `endif `` 與同層區塊對齊;分支內容再縮一層。 --- ## 禁止 Alignment Padding type / keyword 與 signal name 之間**只留一個空格**。不為了排成直欄補空白。同型別可併一行。 ```systemverilog // 正確 logic clk, rst_n; logic in_mode; logic signed [`DATA_WIDTH-1:0] in_x, in_y; logic [`DATA_WIDTH-1:0] mem_inx [0:NUM_DATA-1]; // 錯誤 logic clk, rst_n; logic in_mode; ``` --- ## Keyword 與括號 `if` / `for` / `case` 與 `(` **零空格**。 ```systemverilog // 正確 if(!rst_n) state <= IDLE; for(int i = 0; i < N; i++) acc = acc + x[i]; case(state) // 錯誤 if (!rst_n) for (int i = 0; i < N; i++) case (state) ``` --- ## Port Map `.name(signal)`:name 與 `(` 之間**零空格**,不做欄位對齊。最後一個 port **不加逗號**。 instance 本行縮排 4 spaces;port 列再 +4(共 8)。 ```systemverilog // 正確 CORDIC_PE u_dut ( .clk(clk), .rst_n(rst_n), .InMode(in_mode), .InX(in_x) ); // 錯誤 CORDIC_PE u_dut ( .clk (clk), .rst_n (rst_n), .InMode (in_mode) ); ``` --- ## Assignment `=` 與 `<=` 前後各一個空格。左邊變數不補空白去對 `=` / `<=`。 ```systemverilog // 正確 act_x = out_x; XN_r[0] <= InX; // 錯誤 act_x = out_x; XN_r[0]<=InX; ``` --- ## Ternary `(cond)? a : b`:`?` 緊貼條件括號,`?` 後與 `:` 前後各一個空格。 ```systemverilog // 正確 XN_r[0] <= (InX < 0)? -InX : InX; next_state = (InValid)? PROCESS : IDLE; // 錯誤 (InX < 0) ? -InX : InX (InX < 0)?-InX:InX ``` --- ## if / else **每個分支的執行內容只有一句時,不要寫 `begin/end`。** 條件與那一句必須在**同一行**:`if(...) stmt;` 一行,`else stmt;` 一行(`else if` 同理)。禁止把單句拆到下一行再縮排。 ```systemverilog // 正確 if(InValid) cnt <= cnt + 1; else cnt <= 0; if(i < NUM_DATA) drive_input(i); else drive_idle(); // 錯誤 — 單句拆到下一行 if(InValid) cnt <= cnt + 1; else cnt <= 0; // 錯誤 — 單句還包 begin/end if(InValid) begin cnt <= cnt + 1; end else begin cnt <= 0; end ``` ### begin / end block 任一分支超過一句才加 `begin/end`。`end` 與 `else` **必須分行**。禁止 `end else begin`。 ```systemverilog // 正確 if(condition) begin do_something(); do_more(); end else begin do_other(); do_another(); end // 錯誤 if(condition) begin do_something(); end else begin do_other(); end ``` --- ## always_ff / always_comb 新碼用 **`always_ff`** / **`always_comb`**。不要 `always @(posedge ...)`、不要 `always @(*)`。 `begin` 與 sensitivity **同一行**。 ```systemverilog always_ff @(posedge clk or negedge rst_n) begin ... end always_comb begin ... end ``` --- ## Sequential Reset RTL sequential 用 async reset: ```systemverilog always_ff @(posedge clk or negedge rst_n) begin if(!rst_n) begin state <= IDLE; cnt <= 0; end else begin state <= next_state; cnt <= cnt + 1; end end ``` 單 statement 可省略 `begin/end`:`if(!rst_n) state <= IDLE;` PATTERN 的 `drive_reset` 仍走 `dv-format`,不套這段。 --- ## for - `generate`:`for(genvar i = 0; i < N; i++)` - `always_*` / function:`for(int i = 0; i < N; i++)`,遞增用 **`i++`** - 單行 body 不加 `begin/end`;多行才加 - 禁止在迴圈外宣告 `integer` / `int` 再寫 `i = i + 1` ```systemverilog // 正確 generate for(genvar s = 0; s < `PIPE_STAGE; s++) begin : PIPE_STAGE_GEN ... end endgenerate for(int i = 0; i < N; i++) acc = acc + x[i]; // 錯誤 integer i; for(i = 0; i < N; i = i + 1) begin acc = acc + x[i]; end ``` --- ## Named Block / FSM `generate` 與主要 `always_*` 加 **`begin : LABEL`**(全大寫 + `_`)。 FSM 用 **`typedef enum`**,不要一堆 `localparam IDLE = ...`。 ```systemverilog typedef enum logic [1:0] {IDLE, PROCESS, OUT} STATETYPE; STATETYPE state, next_state; always_ff @(posedge clk or negedge rst_n) begin : FSM if(!rst_n) state <= IDLE; else state <= next_state; end ``` `case` 要有 **`default`**。 --- ## Constants ``.v`` 與 ``.sv`` **都不能散寫 `` `define ``**。專案常數先規劃進 **`define.vh`**,各 RTL 檔只 `` `include "define.vh" ``。 | 放哪 | 什麼 | |---|---| | **`define.vh`** | 跨檔 `` `define ``(位寬、stage 數、路徑)。用 `` `ifndef DEFINE_VH `` guard | | **該 module 的 `.sv` / `.v`** | 只有自己用的 **`localparam`** | | **禁止** | 在 `.sv` 或 `.v` 裡寫 `` `define `` | file banner **之後**、`module` **之前** 寫 `` `include "define.vh" ``(該檔需要時)。有 `` `timescale `` 時放在 include 附近、module 前;不規定時間單位。 ```systemverilog /****************************************************************************** * ...banner... ******************************************************************************/ `include "define.vh" module EVD ( ``` ```systemverilog `ifndef DEFINE_VH `define DEFINE_VH `define DATA_WIDTH 17 `define PIPE_STAGE 2 `endif ``` ```systemverilog // 錯誤 — .sv / .v 裡出現 `define `define DATA_WIDTH 17 module EVD (...); ``` --- ## Package / Function 共用型別與 combo helper 放 **`package`**。helper 用 **`function automatic`**。 ```systemverilog package AXI4_PKG; typedef enum logic [1:0] { AXI_OKAY, AXI_SLVERR, AXI_DECERR } resp_type; endpackage ``` ```systemverilog function automatic resp_type beat_response( input resp_type request_resp, input logic [ADDR_W-1:0] address ); begin ... end endfunction ``` --- ## Section Header 三行式,**上方空一行**。標題用空白**置中**,**不用 `-` 包夾**。 固定寬度 **63**:第 1、3 行是 `//` + **61** 個 `=`。 第 2 行:`//` + 左側空白 + 標題。 ``` inner = 61 left = floor((inner - len(title)) / 2) ``` 只補左側空白,不強制右側補齊。標題比 61 長時,三行一起加寬,仍置中。 ```systemverilog //============================================================= // Clock & Reset //============================================================= logic clk, rst_n; ``` ```systemverilog //============================================================= // Sim Mode & SDF Annotate //============================================================= ``` --- ## File Banner 每個 `.v` / `.sv` 開頭放這塊。欄位只有 **`File Name` / `Project` / `Module` / `Author`**。不要 `Student ID`、不要 `Tool`。 ```systemverilog /****************************************************************************** * Copyright (C) 2026 Marco * * File Name: PATTERN.sv * Project: Clock Domain Crossing * Module: PATTERN * Author: Marco * ******************************************************************************/ ``` 預設: - **Author**:`Marco ` - **YEAR**:當年 - **AUTHOR_NAME**:Author 的名字部分(`Marco`) - **Project**:目錄名或使用者指定 - 冒號後空白對齊到同一欄(上例 `File Name:` 後 4 spaces)