FPGA入门(一):手把手教你用 Vivado 创建工程并仿真

FPGA 入门

本文适合 FPGA 新手入门,从原理讲解到 Vivado 仿真全流程拆解,带你彻底搞懂二选一多路器的设计与验证逻辑,全程无跳步,跟着做就能跑通!
本文章基于小梅哥实验案例


文章目录


前言

多路器是数字电路中最基础的数据选择组件,它的核心功能是根据选择信号,从多个输入信号中挑选一个输出。

我们今天要实现的二选一多路器,功能非常直观:

  • 当选择信号 SEL=0 时,输出 OUT = A

  • 当选择信号 SEL=1 时,输出 OUT = B

它的电路符号和逻辑关系如下:

注:图中 0 号端口接输入 A,1 号端口接输入 B,SEL 为选择控制端


一、环境准备

本文以Vivado 2020.2为例

创建新工程

  1. 打开 Vivado,点击首页【Create New Project】
  2. 工程设置:
  • Project Name:自定义工程名如mux2
  • Project Location:必须选择全英文路径!禁止包含中文、空格、特殊字符!
  1. 后续步骤一路默认,器件选择可任选一款 7 系列 FPGA


二、设计与实现

添加设计源文件

在左侧Sources窗口右键【Design Sources】→【Add Sources】→【Create File】,文件类型选Verilog,命名为mux2.v,点击 OK。

c 复制代码
// 模块定义:模块名mux2,端口包含输入a、b、sel,输出out
module mux2(
    a,
    b,
    sel,
    out
    );

// 端口类型声明:输入信号为input,输出信号默认wire类型
input  a;    // 数据输入A
input  b;    // 数据输入B
input  sel;  // 选择信号SEL
output out;  // 多路器输出OUT

// 核心逻辑:用三目运算符实现二选一
// 当sel=0时,out = a;当sel=1时,out = b
assign out = (sel == 0) ? a : b;

endmodule

代码逐行解释

  • module和endmodule:Verilog 模块的边界标识,所有逻辑代码必须写在模块内。
  • input/output:端口方向声明,output默认是wire类型,适合组合逻辑的连续赋值。
  • assign:Verilog 的连续赋值语句,专门用于驱动wire类型信号,适合实现组合逻辑。
  • 三目运算符(条件)?表达式1:表达式2:直观实现选择逻辑,条件为真时取表达式 1,否则取表达式 2。

三、验证激励:编写 Testbench 仿真文件

Testbench是 FPGA 仿真的核心,它的作用是给设计模块输入激励信号,验证输出是否符合预期。

  1. 添加仿真源文件
    在左侧Sources窗口右键【Simulation Sources】→【Add Sources】


  2. 完整Testbench 代码
c 复制代码
// 时间刻度定义:时间单位1ns,时间精度1ns,#20表示延迟20ns
`timescale 1ns/1ns

// 测试模块无输入输出端口,仅用于仿真激励
module mux2_tb;

// 测试激励信号:用reg类型,用于驱动设计模块的输入端口
reg S0;   // 对应设计模块的输入a
reg S1;   // 对应设计模块的输入b
reg S2;   // 对应设计模块的选择信号sel

// 输出观测信号:用wire类型,接收设计模块的输出
wire mux2_out;

// 例化(调用)设计模块,完成端口映射
mux2 mux2_inst(
    .a(S0),       // 将测试文件的S0信号,连接到模块的a端口
    .b(S1),       // 将测试文件的S1信号,连接到模块的b端口
    .sel(S2),     // 将测试文件的S2信号,连接到模块的sel端口
    .out(mux2_out)// 将模块的out端口,连接到测试文件的mux2_out信号
);

// 仿真激励块:initial块仅在仿真开始时执行一次
initial begin
    // 初始状态:sel=0,a=0,b=0 → 预期输出out=0
    S2=0; S1=0; S0=0;
    #20; // 保持当前状态20ns,让信号稳定

    // sel=0,a=1,b=0 → 预期输出out=1
    S2=0; S1=0; S0=1;
    #20;

    // sel=0,a=0,b=1 → 预期输出out=0(sel=0时不受b影响)
    S2=0; S1=1; S0=0;
    #20;

    // sel=0,a=1,b=1 → 预期输出out=1
    S2=0; S1=1; S0=1;
    #20;

    // sel=1,a=0,b=0 → 预期输出out=0
    S2=1; S1=0; S0=0;
    #20;

    // sel=1,a=1,b=0 → 预期输出out=0(sel=1时不受a影响)
    S2=1; S1=0; S0=1;
    #20;

    // sel=1,a=0,b=1 → 预期输出out=1
    S2=1; S1=1; S0=0;
    #20;

    // sel=1,a=1,b=1 → 预期输出out=1
    S2=1; S1=1; S0=1;
    #20;

    $stop; // 仿真结束,停止波形记录(可选,推荐添加)
end

endmodule

Testbench 关键知识点拆解

  1. timescale 1ns/1ns:定义仿真的时间单位和精度,所有#延迟都以 1ns 为单位计算,不定义会导致仿真时间混乱。
  2. reg与wire的区别:
  • 主动赋值的激励信号如 S0、S1、S2必须用reg类型;
  • 被动接收的输出信号如 mux2_out必须用wire类型,搞反会报驱动错误。
  1. 模块例化:mux2 mux2_inst(...)是调用我们的多路器模块,采用.端口名(测试信号)的命名映射方式,不容易出错,推荐新手都用这种方式。
  2. 激励穷举:我们的测试激励覆盖了sel、a、b的所有 8 种组合,确保所有输入场景都被验证,避免隐藏 bug。

四、一键仿真:Vivado 行为级仿真全流程

显示全局

放大

波形分析:手把手教你读仿真结果

仿真完成后,波形窗口会显示所有信号的变化,我们可以通过表格逐段验证功能

  • 当sel=0时,输出mux2_out完全跟随a变化,不受b的影响;
  • 当sel=1时,输出mux2_out完全跟随b变化,不受a的影响;
  • 所有场景的输出都与预期一致,说明多路器逻辑完全正确!

总结

本文从原理、代码、仿真到波形分析,完整演示了二选一多路器的 FPGA 实现流程。掌握这个流程后,所有数字电路模块的开发都可以遵循「设计代码→Testbench 激励→仿真验证→上板调试」的标准流程

相关推荐
czwxkn4 小时前
PCB设计-器件:2.电感
嵌入式硬件
佳木逢钺4 小时前
从零开始:基于STM32H750的硬件设计与软件开发完整流程详解
stm32·单片机·嵌入式硬件
Deitymoon6 小时前
ESP8266——透传
单片机·网络协议·tcp/ip
zhangrelay6 小时前
云课实践速通系列-基础篇汇总-必修-通识基础和专业基础-2026--工科--自动化、电气、机器人、测控等
linux·笔记·单片机·学习·ubuntu·机器人·自动化
Deitymoon7 小时前
ESP8266——UDP传输
单片机·网络协议·udp
踏着七彩祥云的小丑8 小时前
嵌入式——认识电子元器件——光电器件系列
单片机·嵌入式硬件
羽获飞8 小时前
从零开始学嵌入式之STM32——31.高级定时器
stm32·单片机·嵌入式硬件
相醉为友8 小时前
040 Linux/裸机/RTOS 项目开发的跨平台兼容性——C语言静态接口抽象底层原理分析
linux·c语言·mcu
iCxhust10 小时前
一块电路板的自觉
单片机·嵌入式硬件·嵌入式·微机原理