入门篇:从零理解硬件描述语言

知识库
知识库文档
/tech-stacks/verilog-systemverilog/tutorial/入门篇:从零理解硬件描述语言.md

文档

Verilog / SystemVerilog 数字设计入门

本章目标

从零开始理解数字电路设计思想,掌握可综合 Verilog 编码规范,完成 FPGA 基础实验。


1. 硬件描述语言的思维方式

软件 vs 硬件

概念 软件 (C/Python) 硬件 (Verilog)
执行 顺序执行 并发执行
变量 按时间变化 代表物理连线
循环 重复执行指令 展开为重复电路
"运行" CPU 执行指令 电路持续工作

关键转变

不要写代码,要描述电路。你写的每行 Verilog 都应能在脑中想象出对应的逻辑门/触发器。


2. 组合逻辑 vs 时序逻辑

组合逻辑

// 纯组合:输出仅取决于当前输入
assign sum = a + b;

always @(*) begin
    case (sel)
        2'b00: out = a;
        2'b01: out = b;
        2'b10: out = c;
        default: out = 0;
    endcase
end

时序逻辑

// 时序:输出取决于时钟沿
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        count <= 0;
    else if (enable)
        count <= count + 1;
end

3. 可综合编码规范

✅ 可以综合

// 阻塞赋值用于组合逻辑
always @(*) y = a & b;

// 非阻塞赋值用于时序逻辑
always @(posedge clk) q <= d;

// 有限状态机
always @(posedge clk) state <= next_state;

❌ 不可综合

#10 clk = ~clk;           // 延时
$display("hello");        // 系统任务
fork ... join             // 不可综合的并发
initial begin ... end     // 仅仿真

4. 状态机设计

Moore 型(输出仅取决于状态)

typedef enum logic [1:0] {
    IDLE, WORKING, DONE
} state_t;

state_t state = IDLE, next_state;

// 状态转移
always_comb begin
    next_state = state;
    case (state)
        IDLE:    if (start) next_state = WORKING;
        WORKING: if (finish) next_state = DONE;
        DONE:    if (ack) next_state = IDLE;
    endcase
end

// 输出逻辑
always_comb begin
    busy = (state == WORKING);
    done = (state == DONE);
end

5. 仿真测试平台

module tb;
    reg clk = 0, rst_n = 0;
    reg start = 0;
    wire busy, done;

    // DUT 例化
    my_module uut (.clk, .rst_n, .start, .busy, .done);

    always #5 clk = ~clk;  // 100MHz

    initial begin
        $dumpfile("tb.vcd");
        $dumpvars(0, tb);

        #10 rst_n = 1;
        #10 start = 1;
        #10 start = 0;

        // 等待 done
        @(posedge done);
        $display("Test passed at t=%0t", $time);

        #50 $finish;
    end
endmodule

6. FPGA 开发流程

设计输入 (Verilog)
  → 行为仿真 (iverilog/Modelsim)
  → 综合 (Yosys/Vivado)
  → 布局布线 (nextpnr/Vivado)
  → 时序仿真
  → 比特流生成
  → FPGA 烧录
  → 板级验证

思考题

  1. 解释 blocking vs non-blocking 赋值在综合后的差异
  2. 什么是亚稳态?如何避免?
  3. 为什么 FPGA 设计中需要约束文件(.xdc/.sdc)?

信息

路径
/tech-stacks/verilog-systemverilog/tutorial/入门篇:从零理解硬件描述语言.md
更新时间
2026/5/31