往期学员作品
沉浸式做项目




累计培养万名工程师
成电国芯FPGA培训基地课程以80%实操为核心,依托400家企业参与课程开发,采用XILINX合作体系与双师教学,通过大量实战项目锤炼工程能力。


























在FPGA开发中,50%的时序问题源于糟糕的编码习惯。本文从企业级代码规范出发,提炼出10个立竿见影的Verilog编码技巧,配合真实工程案例,助你规避常见陷阱,提升代码质量。
文末免费领取《Verilog代码规范检查表》PDF(含Xilinx/Altera双版本),一键排查代码隐患!

verilog
// ❌ 糟糕示例
wire a, b, c; 
// ✅ 优化示例
wire [7:0] adc_data_in;  // 来自ADC的8位输入数据
wire       uart_tx_en;    // UART发送使能信号
企业规范:
_in,输出信号后缀_outclk_<功能>,复位信号rst_<作用域>_n(低有效)verilog
// ❌ 产生锁存器!
always @(*) begin
    if (sel)
         out = a;
    // 缺少else分支!
end 
// ✅ 安全写法:补全default
always @(*) begin
    if (sel)
         out = a;
    else
            out = 8'hFF; // 明确默认值
end
? 对比动图:
(左:不完整条件导致锁存器;右:补全分支生成纯组合逻辑)
verilog
// ✅ 同步复位标准写法
always @(posedge clk) begin
    if (rst_n) begin
        cnt <= 8'b0;
    end else begin
        cnt <= cnt + 1;
    end
end
 // ⚠️ 异步复位仅用于特殊场景(如时钟恢复)
always @(posedge clk or negedge async_rst_n) begin
    if (!async_rst_n)
         state <= IDLE;
    else
         state <= next_state;
end
关键点:
verilog
// ❌ 混合赋值导致仿真与综合不一致
always @(posedge clk) begin
    a = b + c;  // 阻塞赋值
    d <= a;      // 非阻塞赋值
end
// ✅ 严格区分使用场景
// 时序逻辑
always @(posedge clk) begin
    data_ff <= data_in;  // 非阻塞
end
// 组合逻辑
always @(*) begin
    sum = a + b;         // 阻塞
end
verilog
// ✅ 标准三段式状态机
localparam S_IDLE = 3'b001,
           S_RUN  = 3'b010,
           S_DONE = 3'b100;
 // 第一段:状态寄存器
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        state <= S_IDLE;
    else
         state <= next_state;
end
// 第二段:下一状态逻辑
always @(*) begin
    case(state)
        S_IDLE: next_state = start ? S_RUN : S_IDLE;
        S_RUN:  next_state = (cnt == 10) ? S_DONE : S_RUN;
        S_DONE: next_state = S_IDLE;
        default:next_state = S_IDLE;
    endcase
end
// 第三段:输出逻辑
always @(posedge clk) begin
    if (state == S_RUN)
        cnt <= cnt + 1;
    else
         cnt <= 0;
end
verilog
// ❌ casex可能导致意外匹配
casex (sel)
    4'b1??? : out = a;c// 可能匹配到sel=1000以外的值
endcase
// ✅ 添加default并限定匹配范围
case(sel[3:1])  // 明确匹配位宽
    3'b100: out = a;
    default:out = 8'h00;
endcase
企业规范:
full_case和parallel_case避免锁存器unique和priority关键字(SystemVerilog)verilog
// ✅ 功能拆分示例
module uart_tx (
    input  clk,
    input  [7:0] data_in,
    output txd
);
module uart_rx (
    input  clk,
    input  rxd,
    output [7:0] data_out
);
// 顶层模块仅例化
module top;
    uart_tx u_tx(...);
    uart_rx u_rx(...);
endmodule
优势:
verilog
// ❌ 无效注释
reg [3:0] cnt; // 定义4位计数器 
// ✅ 有价值注释
// 波特率分频计数器:115200bps @ 50MHz
// 分频数 = 50e6 / (115200 * 16) ≈ 27
reg [4:0] baud_cnt; // 需覆盖0-26(5位足够)
translate_off注释verilog
// 仿真专用代码(不参与综合)
// synopsys translate_off
initial begin
    $dumpfile("wave.vcd");
    $dumpvars(0, tb_module);
end
// synopsys translate_on
工具链命令:
set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value "-verilog_define SIMULATION" -objects [get_runs synth_1]verilog
// ❌ 直接使用除法运算符
reg [31:0] div = data_in / 10; // 综合成DSP48单元 
// ✅ 位操作近似计算(误差<1%)
// 除以10 ≈ 右移3位(÷8) + 调整补偿
wire [31:0] div_opt = (data_in >> 3) + (data_in >> 5) - (data_in >> 7);
? 对比动图:
(左:直接调用除法器消耗18个DSP;右:位操作仅用逻辑资源)
立即获取《Verilog代码规范检查表》PDF,包含:
如果你希望:
✅ 掌握企业级FPGA代码规范
✅ 亲手完成千兆以太网加速器项目
✅ 获得华为/中兴资深工程师代码评审
立即免费试听 ? [Verilog七日进阶训练营试听链接]

通过规范编码,让你的代码一次编写,终身受用!