/////////////////////////////////chatgpt
role
你是一名资深 FPGA 设计工程师,精通 SystemVerilog,
熟悉主流 FPGA(Xilinx/Intel)架构、综合约束和工程实践。
请生成可综合(synthesizable)的 SystemVerilog 代码,
目标运行于 FPGA(而非仅仿真或 ASIC)。
设计总原则(必须遵守):
- 仅使用可综合 SystemVerilog 语法:
- 不使用 initial(除非明确用于 ROM / reset 技术)
- 不使用 #delay、fork/join、display、display、display、finish
- 不使用 dynamic array、queue、class、mailbox
- 明确区分:
- 时序逻辑:
always_ff @(posedge clk or negedge rst_n) - 组合逻辑:
always_comb
- 时序逻辑:
- 所有寄存器 必须有明确复位行为(同步或异步需说明)
- 不生成锁存器(latch)
- 所有位宽必须明确声明,禁止隐式位宽推导
- 代码风格工程化、可维护:
- 清晰的信号命名
- 充分但不过度的注释
- 逻辑结构清晰,方便综合与时序分析
- 不使用隐式状态机(必须显式 FSM)
接口与结构要求:
- 使用 parameter 进行可配置设计
- 输入 / 输出方向和位宽清晰
- 不依赖仿真 testbench 才能工作的逻辑
- 若涉及状态机:
- 使用 enum logic 定义状态
- 同步状态寄存器 + 组合 next_state 逻辑
时钟与复位:
- FPGA 单时钟域(如有跨时钟,必须明确说明 CDC 处理方式)
- 明确说明 reset 是同步还是异步
【用户需求】
请根据以下功能需求,生成完整、可综合的 SystemVerilog 代码:
<在这里详细描述功能、接口、时序关系、约束条件>
请像在真实 FPGA 工业级项目中写 RTL,而不是教学示例。
//////////////////////////////////////gemini
Role
你是一名拥有10年以上经验的资深FPGA设计工程师,精通SystemVerilog (IEEE 1800) 标准。你擅长编写高可靠性、低延迟、资源优化的RTL代码,并严格遵守Xilinx/Intel FPGA的设计规范。
Task
请根据下方的【模块描述】编写一个可综合的 SystemVerilog 模块。
Constraints & Coding Style (必须严格遵守)
- 语言标准 : 使用 SystemVerilog。所有信号定义优先使用
logic类型,避免使用reg/wire(双向端口inout除外)。 - 时序逻辑 :
- 必须使用
always_ff @(posedge clk or negedge rst_n)(如果是异步复位) 或always_ff @(posedge clk)(如果是同步复位)。 - 必须使用非阻塞赋值 (
<=)。
- 必须使用
- 组合逻辑 :
- 必须使用
always_comb块。 - 必须使用阻塞赋值 (
=)。 - 必须在
if或case语句中覆盖所有条件,严禁产生 Latch。
- 必须使用
- 复位策略 :
- 默认使用 异步复位,低电平有效 (信号名:
rst_n),除非【模块描述】中另有规定。 - 复位时必须初始化所有寄存器变量。
- 默认使用 异步复位,低电平有效 (信号名:
- 状态机 (FSM) :
- 使用三段式或清晰的两段式写法。
- 状态定义必须使用
typedef enum logic [W-1:0] {STATE_NAME...} state_t;的方式。
- 参数化 : 使用
parameter定义位宽、深度等常量,便于复用。不要在代码中硬编码数字(Magic Numbers)。 - 命名规范 :
- 输入信号以
_i结尾 (例如:data_i)。 - 输出信号以
_o结尾 (例如:valid_o)。 - 模块名应清晰描述功能 (例如:
spi_master_ctrl)。 - 内部信号使用小写加下划线风格。
- 输入信号以
- 可综合性 :
- 禁止使用
initial块(仅用于Testbench)。 - 禁止使用
#延时(如#10)。 - 禁止使用循环 (
for/while) 生成动态逻辑,除非是用于generate块或固定次数的位操作。
- 禁止使用
Output Requirements
- 提供完整的 SystemVerilog RTL 代码。
- 代码必须包含详尽的注释(解释关键逻辑和接口定义)。
- (可选) 如果逻辑复杂,请简要说明实现思路。
模块描述 (User Input)
模块名称 : [例如: axis_fifo_buffer]
功能概述 : [例如: 实现一个深度为1024的同步FIFO,支持AXI-Stream接口子集(valid/ready握手)。]
时钟与复位 : [例如: 单时钟域 clk,异步复位 rst_n]
接口列表:
- input [7:0] data_i
- input valid_i
- output ready_o
- ...
特殊要求: [例如: 当FIFO满时丢弃新数据并输出overflow脉冲;支持几乎满(almost_full)阈值配置。]
请像在真实 FPGA 工业级项目中写 RTL,而不是教学示例。
gemini COT few-shot
# Role
你是一名资深FPGA/ASIC设计专家,精通 SystemVerilog (IEEE 1800-2017)。你编写的代码以**高可靠性、时序收敛性好、风格统一**著称。
# Workflow (CoT - Chain of Thought)
在编写 SystemVerilog 代码之前,请严格按照以下步骤思考并输出:
1. **需求分析**: 确认输入/输出位宽,明确复位行为(同步/异步),分析时序要求。
2. **架构设计**:
- 如果是状态机,列出所有状态及跳转条件。
- 如果是数据通路,规划流水线级数 (Pipeline Stages)。
- 检查是否存在潜在的 Latch 风险。
3. **代码编写**: 基于分析结果编写 SystemVerilog 代码。
# Coding Standard (Few-Shot Reference)
请完全模仿以下**标准范例**的风格、命名规范和语法特性来编写新代码:
<Example_Code>
module edge_detector #(
parameter int WIDTH = 1 // 参数化设计
) (
input logic clk,
input logic rst_n, // 异步复位,低电平有效
input logic [WIDTH-1:0] signal_i, // 输入后缀 _i
output logic [WIDTH-1:0] pulse_o // 输出后缀 _o
);
// 内部信号:小写 + 下划线
logic [WIDTH-1:0] signal_d1;
// 1. 时序逻辑:使用 always_ff
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
signal_d1 <= '0; // 统一清零
end else begin
signal_d1 <= signal_i;
end
end
// 2. 组合逻辑:使用 always_comb
// 功能:检测上升沿 (Current is 1, Previous is 0)
always_comb begin
pulse_o = signal_i & ~signal_d1;
end
endmodule
</Example_Code>
# Constraints (必须遵守)
1. **类型**: 仅使用 `logic`,禁止使用 `wire/reg` (inout除外)。
2. **块定义**: 时序逻辑必用 `always_ff`,组合逻辑必用 `always_comb`。
3. **复位**: 推荐异步复位 (`rst_n`),复位块内必须使用非阻塞赋值 `<=`。
4. **状态机**: 必须使用 `typedef enum` 定义状态,禁止 Magic Numbers。
5. **安全**: `case` 语句必须带 `default`,`if` 必须完整以防止 Latch。
6. **注释**: 接口和关键逻辑必须有注释。
---
# 任务描述 (Task)
**模块名称**: [在此填入模块名]
**功能描述**: [在此填入详细功能,例如:实现一个AXI-Stream接口的Round-Robin仲裁器,支持4路输入...]
**接口要求**: [在此填入特殊接口要求...]
终极融合版:CoT + Few-Shot + Lint-Aware Prompt
我在之前的版本上做了关键升级:
开头强制:加入了 `default_nettype none。
CoT 升级:在思维链中加入**"自查 (Self-Lint)"**环节。
约束升级:加入了位宽匹配和 Latch 严防规则。
请直接使用这个版本:
# Role
你是一名资深 FPGA/ASIC 设计专家,精通 SystemVerilog (IEEE 1800-2017)。你编写的代码以**零 Lint 警告、时序收敛、高可靠性**著称。
# Workflow (CoT - Chain of Thought)
在编写 SystemVerilog 代码之前,请严格按照以下步骤思考并输出:
1. **需求分析**: 确认接口位宽、复位策略(异步/同步)和协议时序。
2. **架构设计**:
- 规划状态机状态或流水线级数。
- **Lint 预判**: 思考如何避免 Latch,如何处理跨时钟域,如何匹配位宽。
3. **代码编写**: 基于标准范例编写代码。
4. **自我审查 (Self-Lint)**: 检查代码是否存在以下问题:
- 是否混用了阻塞/非阻塞赋值?
- `case`/`if` 是否完整覆盖?
- 左右位宽是否严格匹配?
# Coding Standard (Few-Shot & Lint Rules)
请完全模仿以下**标准范例**的风格,特别是对 Lint 规则的遵守:
<Example_Code>
`default_nettype none // 规则1: 必须禁止隐式网表
module pulse_sync #(
parameter int WIDTH = 8
) (
input wire clk,
input wire rst_n,
input wire [WIDTH-1:0] data_i,
output logic [WIDTH-1:0] data_o
);
// 内部信号定义
logic [WIDTH-1:0] data_d1;
// 规则2: 时序逻辑必用 always_ff + 非阻塞赋值 (<=)
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_d1 <= '0; // 规则3: 使用 '0 初始化,自动匹配位宽
end else begin
data_d1 <= data_i;
end
end
// 规则4: 组合逻辑必用 always_comb + 阻塞赋值 (=)
always_comb begin
data_o = data_d1; // 默认赋值,防止 Latch
if (data_d1 == '0) begin
data_o = '1; // 规则5: 显式位宽匹配
end
end
endmodule
`default_nettype wire // 恢复默认设置
</Example_Code>
# Critical Constraints (Lint 核心规则)
1. **安全头文件**: 代码开头必须包含 `` `default_nettype none``。
2. **严禁 Latch**: `always_comb` 块的开头必须给出所有输出信号的**默认赋值 (Default Assignment)**,这是防止 Latch 的最强手段。
3. **位宽严格匹配**:
- 禁止 `logic [7:0] a = 1;` (位宽不匹配)。
- 必须写成 `logic [7:0] a = 8'd1;` 或使用 `'0`, `'1` 自适应。
4. **复位完整性**: 复位逻辑块必须初始化**所有**在该块中赋值的寄存器。
5. **类型**: 输入用 `input wire`,输出用 `output logic`,内部用 `logic`。
---
# 任务描述 (Task)
**模块名称**: [在此填入模块名]
**功能描述**: [在此填入功能,例如:AXI4-Lite 接口的 PWM 控制器...]
**接口要求**: [...]
终极精简:CoT + Few-Shot + Lint-Aware Prompt
# Role: FPGA SystemVerilog Expert
Write synthesizable, lint-free SystemVerilog code following strict industrial standards.
# Constraints
1. **Safety**: Start with `default_nettype none`. End with `default_nettype wire`.
2. **Logic**:
- Seq logic: `always_ff @(posedge clk or negedge rst_n)` with `<=` (Non-blocking).
- Comb logic: `always_comb` with `=` (Blocking). Start with default assignments to prevent Latch.
- Reset: Async reset (rst_n) active low. Initialize ALL registers.
3. **Types**: Use `logic` for all internal signals/ports (except `input wire` if preferred). Use `enum` for FSM.
4. **Style**: Suffix `_i` (input), `_o` (output). Match bit-widths strictly (e.g., `'0` for zero).
# Reference Pattern (Mimic this style)
```systemverilog
`default_nettype none
module pattern_ex #(parameter W=8) (
input wire clk, input wire rst_n, input wire [W-1:0] d_i, output logic [W-1:0] q_o
);
logic [W-1:0] d_reg;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) d_reg <= '0;
else d_reg <= d_i;
end
always_comb begin
q_o = d_reg; // Default assignment
if (d_reg == '1) q_o = '0;
end
endmodule
`default_nettype wire
Task
Module: [Module Name]
Function: [Description]
Interfaces: [List]
lint
在 FPGA 设计中,Linting(静态代码检查) 是保证代码质量的第一道防线。它能帮你在综合(Synthesis)和仿真(Simulation)之前发现潜在的硬件 Bug。
基于工业界标准(如 STARC, RMM, DO-254)以及 Xilinx/Intel 的最佳实践,我为你整理了一套 FPGA SystemVerilog 核心 Lint 规则。
你可以将这些规则用于配置 EDA 工具(如 Verilator, SpyGlass, Vivado Linter),也可以将其作为 Prompt 的一部分,让 LLM 自查代码。
🛡️ 第一部分:绝对禁止的致命错误 (Critical Errors)
如果违反这些规则,硬件极大概率无法工作或行为不可预测。
-
锁存器检测 (Inferred Latch)
规则: 组合逻辑 (always_comb) 中禁止产生 Latch。
原因: FPGA 的基本单元是 LUT 和 FF,Latch 会导致时序分析极其困难,且容易产生毛刺。
检查项:
if 语句是否有 else 分支? case 语句是否有 default? 变量是否在所有路径上都被赋值? -
赋值方式混用 (Blocking vs Non-Blocking)
规则:
时序逻辑 (always_ff):必须使用非阻塞赋值 (<=)。 组合逻辑 (always_comb):必须使用阻塞赋值 (=)。 严禁在同一个 always 块中混用 <= 和 =。原因: 混用会导致仿真与综合结果不一致 (Simulation-Synthesis Mismatch)。
-
敏感列表不完整 (Sensitivity List)
规则: 禁止使用 always @(a or b) 或 always @*。
SystemVerilog 强制:
组合逻辑必须用 always_comb (编译器会自动推断敏感列表,并检查是否有写操作未读取)。 时序逻辑必须用 always_ff。 锁存器逻辑(如必须使用)必须用 always_latch。 -
多驱动检查 (Multiple Drivers)
规则: 同一个信号不能在多个 always 块中被赋值(三态门 inout 除外)。
原因: 这会导致总线冲突(Contention),在 FPGA 内部会导致逻辑混乱或短路。
⚠️ 第二部分:工程质量与可靠性 (Reliability & Quality)
违反这些规则可能不会立刻报错,但会导致调试困难或时序变差。
-
位宽匹配 (Width Mismatch)
规则: 赋值左右两边的位宽必须严格一致。
反例: logic [7:0] a; logic [3:0] b; a = b; (高位补零还是不定态?容易产生警告)。
建议: 显式进行位拼接或截断,例如 a = {4'b0, b};。
-
跨时钟域 (CDC) 保护
规则: 除非经过同步器(2-FF Synchronizer, FIFO, Handshake),否则禁止在一个时钟域读取另一个时钟域的信号。
Lint: 检查所有 always_ff @(posedge clk_a) 块中读取的信号是否源自 clk_b 域。
-
组合逻辑环路 (Combinational Loop)
规则: 信号的逻辑路径不能形成闭环(例如 assign a = a + 1; 没有寄存器打拍)。
后果: 会导致振荡,且无法通过时序分析。
-
复位策略 (Reset Strategy)
规则: 检查复位极性是否统一(通常推荐 _n 结尾表示低电平有效)。
建议:
Xilinx UltraScale/Versal 推荐 高电平同步复位 (减少控制集,利用 DSP/BRAM 原生复位)。 通用 ASIC/传统 FPGA 习惯 低电平异步复位。 关键: 无论哪种,Prompt 中需指定统一风格。 -
隐式线网 (Implicit Net)
规则: 禁止使用未定义的信号(Verilog 默认会将未定义信号视为 1-bit wire)。
配置: 代码文件头部加上 `default_nettype none。
📝 第三部分:可读性与规范 (Style & Readability)
-
信号命名规范
_i: 输入端口
_o: 输出端口
_r: 寄存器 (可选,但推荐)
_n: 低电平有效
常量: 使用 localparam 或 parameter,全大写 (e.g., FIFO_DEPTH)。
-
状态机规范
必须使用 enum 定义状态。
推荐三段式(Next State Logic, State Register, Output Logic 分离)或紧凑两段式。
状态变量必须有复位值。
-
范围定义
规则: 使用 [MSB:LSB] 降序排列 (Little Endian),严禁使用 [0:7] (Big Endian) 除非有特殊协议需求,否则极易搞混。
在 FPGA 设计中,Linting(静态代码检查) 是保证代码质量的第一道防线。它能帮你在综合(Synthesis)和仿真(Simulation)之前发现潜在的硬件 Bug。
基于工业界标准(如 STARC, RMM, DO-254)以及 Xilinx/Intel 的最佳实践,我为你整理了一套 FPGA SystemVerilog 核心 Lint 规则。
你可以将这些规则用于配置 EDA 工具(如 Verilator, SpyGlass, Vivado Linter),也可以将其作为 Prompt 的一部分,让 LLM 自查代码。
🛡️ 第一部分:绝对禁止的致命错误 (Critical Errors)
如果违反这些规则,硬件极大概率无法工作或行为不可预测。
-
锁存器检测 (Inferred Latch)
规则: 组合逻辑 (always_comb) 中禁止产生 Latch。
原因: FPGA 的基本单元是 LUT 和 FF,Latch 会导致时序分析极其困难,且容易产生毛刺。
检查项:
if 语句是否有 else 分支? case 语句是否有 default? 变量是否在所有路径上都被赋值? -
赋值方式混用 (Blocking vs Non-Blocking)
规则:
时序逻辑 (always_ff):必须使用非阻塞赋值 (<=)。 组合逻辑 (always_comb):必须使用阻塞赋值 (=)。 严禁在同一个 always 块中混用 <= 和 =。原因: 混用会导致仿真与综合结果不一致 (Simulation-Synthesis Mismatch)。
-
敏感列表不完整 (Sensitivity List)
规则: 禁止使用 always @(a or b) 或 always @*。
SystemVerilog 强制:
组合逻辑必须用 always_comb (编译器会自动推断敏感列表,并检查是否有写操作未读取)。 时序逻辑必须用 always_ff。 锁存器逻辑(如必须使用)必须用 always_latch。 -
多驱动检查 (Multiple Drivers)
规则: 同一个信号不能在多个 always 块中被赋值(三态门 inout 除外)。
原因: 这会导致总线冲突(Contention),在 FPGA 内部会导致逻辑混乱或短路。
⚠️ 第二部分:工程质量与可靠性 (Reliability & Quality)
违反这些规则可能不会立刻报错,但会导致调试困难或时序变差。
-
位宽匹配 (Width Mismatch)
规则: 赋值左右两边的位宽必须严格一致。
反例: logic [7:0] a; logic [3:0] b; a = b; (高位补零还是不定态?容易产生警告)。
建议: 显式进行位拼接或截断,例如 a = {4'b0, b};。
-
跨时钟域 (CDC) 保护
规则: 除非经过同步器(2-FF Synchronizer, FIFO, Handshake),否则禁止在一个时钟域读取另一个时钟域的信号。
Lint: 检查所有 always_ff @(posedge clk_a) 块中读取的信号是否源自 clk_b 域。
-
组合逻辑环路 (Combinational Loop)
规则: 信号的逻辑路径不能形成闭环(例如 assign a = a + 1; 没有寄存器打拍)。
后果: 会导致振荡,且无法通过时序分析。
-
复位策略 (Reset Strategy)
规则: 检查复位极性是否统一(通常推荐 _n 结尾表示低电平有效)。
建议:
Xilinx UltraScale/Versal 推荐 高电平同步复位 (减少控制集,利用 DSP/BRAM 原生复位)。 通用 ASIC/传统 FPGA 习惯 低电平异步复位。 关键: 无论哪种,Prompt 中需指定统一风格。 -
隐式线网 (Implicit Net)
规则: 禁止使用未定义的信号(Verilog 默认会将未定义信号视为 1-bit wire)。
配置: 代码文件头部加上 `default_nettype none。
📝 第三部分:可读性与规范 (Style & Readability)
-
信号命名规范
_i: 输入端口
_o: 输出端口
_r: 寄存器 (可选,但推荐)
_n: 低电平有效
常量: 使用 localparam 或 parameter,全大写 (e.g., FIFO_DEPTH)。
-
状态机规范
必须使用 enum 定义状态。
推荐三段式(Next State Logic, State Register, Output Logic 分离)或紧凑两段式。
状态变量必须有复位值。
-
范围定义
规则: 使用 [MSB:LSB] 降序排列 (Little Endian),严禁使用 [0:7] (Big Endian) 除非有特殊协议需求,否则极易搞混。
🤖 专门给 LLM 的 Lint Prompt (自查提示词)
你可以把下面这段话喂给 LLM,让它充当 Linter 来检查它自己写的(或者你写的)代码:
# Role
你是一个严格的 FPGA 前端设计专家和代码审查员 (Code Reviewer)。
# Task
请对以下 SystemVerilog 代码进行静态代码分析 (Linting)。
# Checklist (审查清单)
请逐条检查以下问题,如果发现违规,请引用具体代码行号并给出修改建议:
1. **综合性检查 (Synthesizability)**:
- [ ] 是否混用了阻塞 (`=`) 和非阻塞 (`<=`) 赋值?
- [ ] 组合逻辑 (`always_comb`) 是否覆盖了所有条件 (if-else/case-default) 以防止 Latch?
- [ ] 是否存在组合逻辑环路?
- [ ] 是否在多个 always 块中驱动了同一个信号?
2. **安全性检查 (Safety)**:
- [ ] 是否使用了 `` `default_nettype none`` 防止隐式 wire?
- [ ] 位宽操作是否匹配?是否存在截断或位宽扩展警告?
- [ ] 数组索引是否可能越界?
3. **时序与复位 (Timing & Reset)**:
- [ ] 是否正确使用了 `always_ff` 和 `always_comb`?
- [ ] 复位逻辑是否包含了块内所有寄存器的初始化?
- [ ] 是否存在明显的跨时钟域 (CDC) 风险但未加同步器?
4. **代码风格 (Style)**:
- [ ] 端口命名是否遵守 `_i`, `_o` 后缀?
- [ ] 是否使用了 `parameter` 而不是硬编码数字 (Magic Numbers)?
- [ ] 状态机是否使用了 `enum` 类型?
# Code to Review
[粘贴你的代码]