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 激励→仿真验证→上板调试」的标准流程

相关推荐
HQB20267 小时前
EG1198|屹晶微电子 120V 内置 MOS 异步降压 DC‑DC(高性价比)
嵌入式硬件·硬件工程
嵌入式软硬件攻城狮7 小时前
9.读写DDR测试
fpga开发
果壳science9 小时前
张祥前实验如何获取正电荷
笔记·科技·嵌入式硬件·硬件工程·制造
南山电子nscn9 小时前
中科芯CETC汽车电池管理系统BMS进口芯片国产型号替代指南
单片机·汽车·bms
沉淀的.晴天9 小时前
can总线
stm32
桀人10 小时前
认识AT24C02
stm32·单片机·嵌入式硬件
国科安芯11 小时前
星间激光通信终端CANFD控制网络的时延确定性与辐射可靠性
网络·嵌入式硬件·信息与通信·canfd·低轨卫星·商业航天·抗辐射
一直C11 小时前
嵌入式 Linux 驱动开发学习笔记:内核定时器、platform 总线与 I²C 驱动
linux·驱动开发·嵌入式硬件·学习·imx6ull
传感器与混合集成电路11 小时前
150MHz主频、8路DAC与6路PWM:JLH221360伺服控制SIP解析
嵌入式硬件
comyccccc12 小时前
STM32PID控制板设计全解析学习笔记
单片机·嵌入式硬件