FPGA 入门
本文适合 FPGA 新手入门,从原理讲解到 Vivado 仿真全流程拆解,带你彻底搞懂二选一多路器的设计与验证逻辑,全程无跳步,跟着做就能跑通!
本文章基于小梅哥实验案例
文章目录
- [FPGA 入门](#FPGA 入门)
- 前言
- 一、环境准备
- 二、设计与实现
- [三、验证激励:编写 Testbench 仿真文件](#三、验证激励:编写 Testbench 仿真文件)
- [四、一键仿真:Vivado 行为级仿真全流程](#四、一键仿真:Vivado 行为级仿真全流程)
- 总结
前言
多路器是数字电路中最基础的数据选择组件,它的核心功能是根据选择信号,从多个输入信号中挑选一个输出。
我们今天要实现的二选一多路器,功能非常直观:
-
当选择信号 SEL=0 时,输出 OUT = A
-
当选择信号 SEL=1 时,输出 OUT = B
它的电路符号和逻辑关系如下:

注:图中 0 号端口接输入 A,1 号端口接输入 B,SEL 为选择控制端
一、环境准备
本文以Vivado 2020.2为例
创建新工程
- 打开 Vivado,点击首页【Create New Project】
- 工程设置:
- Project Name:自定义工程名如mux2
- Project Location:必须选择全英文路径!禁止包含中文、空格、特殊字符!
- 后续步骤一路默认,器件选择可任选一款 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 仿真的核心,它的作用是给设计模块输入激励信号,验证输出是否符合预期。
- 添加仿真源文件
在左侧Sources窗口右键【Simulation Sources】→【Add Sources】




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

显示全局

放大


波形分析:手把手教你读仿真结果
仿真完成后,波形窗口会显示所有信号的变化,我们可以通过表格逐段验证功能

- 当sel=0时,输出mux2_out完全跟随a变化,不受b的影响;
- 当sel=1时,输出mux2_out完全跟随b变化,不受a的影响;
- 所有场景的输出都与预期一致,说明多路器逻辑完全正确!
总结
本文从原理、代码、仿真到波形分析,完整演示了二选一多路器的 FPGA 实现流程。掌握这个流程后,所有数字电路模块的开发都可以遵循「设计代码→Testbench 激励→仿真验证→上板调试」的标准流程