3、RTL设计环境搭建:Verilog语法速览、Vivado/Quartus工具链介绍、仿真工具(VCS/Modelsim)配置

好,咱们正式开始动手之前,先把“家伙事儿”备齐。做RTL设计,说白了就是三件事:会写代码、会用工具、会看波形。这一章我就带你把这三大件儿捋一遍。

3.1 Verilog语法速览:够用就行

很多新人一上来就抱着Verilog语法书啃,我当年也干过这事儿。后来发现,做数字IC设计,常用的语法其实就那二十来条。你想想看,一个模块里无非就是:输入输出声明、寄存器定义、组合逻辑、时序逻辑、连线。别的都是锦上添花。

我个人习惯把Verilog语法分成三类:

  • 必用核心:module/endmodule、input/output、reg/wire、always @(posedge clk)、assign、if-else、case、begin/end
  • 常用辅助:parameter、localparam、generate、for循环、function、task
  • 仿真专用:initial、$display、$monitor、$time、#延迟

来,看一个最简单的SPI控制器顶层模块,感受一下:

module spi_controller (
    input  wire        clk,          // 系统时钟
    input  wire        rst_n,        // 异步复位,低有效
    input  wire        start,        // 启动传输
    input  wire [7:0]  tx_data,      // 发送数据
    output reg  [7:0]  rx_data,      // 接收数据
    output reg         busy,         // 忙标志
    // SPI 物理接口
    output reg         sclk,         // SPI时钟
    output reg         mosi,         // 主出从入
    input  wire        miso          // 主入从出
);

    // 状态机定义
    localparam IDLE  = 2'b00;
    localparam SHIFT = 2'b01;
    localparam DONE  = 2'b10;

    reg [1:0] state, next_state;
    reg [2:0] bit_cnt;   // 位计数器,0~7

    // 时序逻辑:状态跳转
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            state <= IDLE;
        else
            state <= next_state;
    end

    // 组合逻辑:下一状态
    always @(*) begin
        next_state = state;
        case (state)
            IDLE:  if (start) next_state = SHIFT;
            SHIFT: if (bit_cnt == 3'd7) next_state = DONE;
            DONE:  next_state = IDLE;
        endcase
    end

    // ... 省略数据路径和SCLK生成逻辑

endmodule

重点提醒:always @(posedge clk) 里用 非阻塞赋值 (<=),always @(*) 里用 阻塞赋值 (=)。这个规矩千万别搞反了。我曾经见过一个同事把阻塞赋值写在时序逻辑里,仿真怎么跑都对,综合出来直接崩了——查了两天才找到原因。

3.2 Vivado/Quartus工具链:两大主流FPGA工具

做RTL设计,你至少得熟悉一个FPGA工具链。目前市面上主流的就是Xilinx的Vivado和Intel的Quartus。我两个都用过,说实话,核心流程大同小异。

对比项 Vivado (Xilinx) Quartus (Intel)
支持的器件 Xilinx 7系列及以后 Intel Cyclone/Arria/Stratix
综合引擎 Synth 8 (内置) Quartus Prime Synthesis
仿真集成 自带XSim,可调用VCS/Modelsim 自带ModelSim Starter,可调用VCS
脚本支持 Tcl脚本,非常强大 Tcl脚本,功能稍弱
调试工具 Vivado Logic Analyzer (ILA) Signal Tap Logic Analyzer

我个人更偏爱Vivado的Tcl脚本能力。举个例子,你可以用一行命令完成整个工程的创建和编译:

create_project -force spi_project ./spi_project -part xc7a35tcsg324-1
add_files -norecurse {./rtl/spi_controller.v ./rtl/spi_fifo.v}
set_property top spi_controller [current_fileset]
launch_runs synth_1 -jobs 4
wait_on_run synth_1
open_run synth_1
report_timing_summary -file timing_report.rpt

嗯,这里要注意:Vivado和Quartus对Verilog语法的支持不完全一样。比如Vivado对SystemVerilog的支持更好,Quartus在旧版本里对某些语法会报错。我的建议是:写代码时尽量用最基础的Verilog-2001语法,这样两个工具都能跑。

3.3 仿真工具配置:VCS与Modelsim

仿真,是RTL设计里最花时间的环节。我统计过,一个项目里大概60%的时间都在仿真和调试。所以仿真工具用得好不好,直接决定你的开发效率。

3.3.1 Modelsim/QuestaSim 配置

Modelsim是Mentor(现属Siemens)的产品,个人学习和小项目用得非常广。配置其实很简单:

  1. 安装完成后,把 vsim 所在目录加到系统PATH里
  2. 写一个 run.do 脚本,一键跑仿真

这是我常用的do文件模板:

# run.do
vlib work
vlog -sv ./rtl/*.v ./tb/*.v
vsim -voptargs=+acc work.spi_tb
log -r /*
add wave -position insertpoint sim:/spi_tb/*
run 10us

你只要在Modelsim命令行里敲 do run.do,就全自动跑起来了。我个人习惯把do文件和工程放在一起,方便版本管理。

3.3.2 VCS 配置

VCS是Synopsys的旗舰仿真器,工业界标准。公司里做ASIC项目基本都用它。配置稍微复杂一点,但核心就三步:

# 第一步:编译
vcs -full64 -sverilog -debug_access+all \
    -f filelist.f \
    -l compile.log

# 第二步:运行
./simv -l run.log

# 第三步:查看波形
dve -vpd vcdplus.vpd &

我的小技巧:VCS编译时加上 -debug_access+all 参数,这样生成的仿真文件里包含所有信号信息,调试时想看啥就看啥。不过注意,这会增加仿真文件体积。如果是做回归测试,可以用 -debug_access+pp 只保留必要信息,速度能快不少。

3.4 知识体系总览

为了让你对整个环境搭建有个全局认识,我画了一张图:

RTL设计环境搭建知识体系 Verilog语法速览 • 模块声明 (module/endmodule) • 信号类型 (reg/wire/input/output) • 时序逻辑 (always @(posedge clk)) • 组合逻辑 (always @(*) / assign) • 条件语句 (if-else / case) • 参数化设计 (parameter) • 阻塞 vs 非阻塞赋值 • 仿真语句 ($display / #延迟) • 状态机编写技巧 • 代码风格与规范 FPGA工具链 • Vivado (Xilinx) - 工程创建与管理 - 综合 (Synthesis) - 实现 (Implementation) - 时序分析 (Timing Report) - ILA在线调试 • Quartus (Intel) - 工程设置与约束 - 分析与综合 - 布局布线 (Fitter) - Signal Tap调试 • Tcl脚本自动化 • 跨平台兼容性注意 仿真工具配置 • Modelsim/QuestaSim - 库管理 (vlib/vmap) - 编译 (vlog/vcom) - 仿真 (vsim) - do脚本自动化 - 波形查看与调试 • VCS (Synopsys) - 编译命令 (vcs) - 仿真运行 (simv) - 波形生成 (VPD/VCD) - DVE/Verdi调试 • 仿真脚本模板 • 覆盖率收集 三者相辅相成:语法是基础,工具链是平台,仿真工具是验证手段

避坑指南:我曾经在项目里遇到过一个坑——VCS和Modelsim对同一个RTL代码的仿真结果不一致。后来发现是VCS默认用+v2k模式,而Modelsim默认用-sv模式,对reg类型的默认值处理不同。从那以后,我写代码时都会显式初始化所有寄存器,或者在仿真脚本里统一仿真器选项。

好了,环境搭建这部分就聊到这儿。工具这东西,光看没用,你得亲手装一遍、跑一遍、踩一遍坑,才能真正记住。下一章咱们就开始写真正的SPI控制器代码了——到时候我会带你一步步把状态机、数据路径、时钟生成全部实现出来。

一句话总结:Verilog语法掌握20%的核心就能干活,Vivado和Quartus选一个精通就行,仿真工具配置好脚本后一键跑——这才是RTL设计的正确打开方式。

可可精品资料库