引言——
闲来无事,兴起整个基于FPGA的逻辑分析仪吧,前段时间看到开源的100M采样率的pico逻辑分析仪挺感兴趣的,但手中暂无pico,那就用手中的NANO 9K FPGA手搓一个。
该项目采用TANG NANO 9K(GW1NR-9)实现,最大采样率为27MHz,采样深度48K。(勉强能用,其实PLL倍频输出下也能达到GW1NR-9的工作频率上限125M)。
移植难度:⭐ 纯verilog
Gitlab代码地址:pieceofApple/GW1NR-9_Logicanalyzer: 该项目采用TANG NANO 9K(GW1NR-9)实现,最大采样率为27MHz,采样深度48K。
注意:经过多次测试,如通过FPGA接收RX再连接至RX-EXT输出,将RX-EXT连接至采样通道无法采样数据,但外部串口直接接到CH通道可以正常采样。故尽量避免FPGA内部输出信号到采样通道采样!
系统概述
硬件规格
- FPGA: TANG NANO 9K (GW1NR-LV9QN88PC6/I5)
- 系统时钟: 27MHz
- 采样通道: 8通道 (CH0-CH7)
- 缓冲区大小: 48KB (49152字节)
- 最大采样率: 27MHz
- 通信接口: UART (115200波特率, 8N1)
- 默认采样率: 100kHz
功能特性
- ✅ 8通道逻辑信号采样
- ✅ 可配置采样率(10kHz – 27MHz)
- ✅ 8种触发模式(立即、边沿、电平、模式、序列)
- ✅ 预触发功能(捕获触发前的数据)
- ✅ 可配置频率输出(用于测试信号生成)
- ✅ 可配置占空比(0-100%)
- ✅ 实时波形显示和分析
- ✅ 频率和占空比测量
- ✅ PulseView支持(VCD/CSV导出)
硬件引脚配置
引脚分配表
| 功能 | 引脚号 | 方向 | 电压 | 说明 |
|---|---|---|---|---|
| 系统时钟 | 52 | 输入 | 1.8V | 27MHz系统时钟 |
| 复位信号 | 4 | 输入 | 1.8V | 低电平复位 |
| UART TX | 17 | 输出 | 3.3V | 板载Type-C UART发送 |
| UART RX | 18 | 输入 | 3.3V | 板载Type-C UART接收 |
| UART TX_EXT | 33 | 输出 | 3.3V | 外部UART发送(与TX同步) |
| UART RX_EXT | 34 | 输出 | 3.3V | RX信号输出(与RX同步) |
| CH0 | 25 | 输入 | 3.3V | 逻辑分析仪通道0 |
| CH1 | 26 | 输入 | 3.3V | 逻辑分析仪通道1 |
| CH2 | 27 | 输入 | 3.3V | 逻辑分析仪通道2 |
| CH3 | 28 | 输入 | 3.3V | 逻辑分析仪通道3 |
| CH4 | 29 | 输入 | 3.3V | 逻辑分析仪通道4 |
| CH5 | 30 | 输入 | 3.3V | 逻辑分析仪通道5 |
| CH6 | 31 | 输入 | 3.3V | 逻辑分析仪通道6 |
| CH7 | 32 | 输入 | 3.3V | 逻辑分析仪通道7 |
| 频率输出 | 84 | 输出 | 1.8V | 可调频率输出 |
| LED状态 | 10-13 | 输出 | 1.8V | 状态指示LED |
引脚说明
UART接口
- 引脚17 (uart_tx): 板载Type-C UART发送,连接到PC
- 引脚18 (uart_rx): 板载Type-C UART接收,接收PC命令
- 引脚33 (uart_tx_ext): 外部UART发送,与引脚17同步输出相同数据
- 引脚34 (uart_rx_ext): RX信号输出,实时输出引脚18的信号(与RX同步)
- 可用于示波器测量
- 可连接到逻辑分析仪输入通道(如CH2)进行采样
- 支持外部串口设备直接连接进行数据采样
逻辑分析仪输入
- 引脚25-32 (CH0-CH7): 8个逻辑分析仪输入通道
- CH0-CH2 (引脚25-27): 无内部上拉,适合采样外部信号(如RX_EXT输出)
- CH3-CH7 (引脚28-32): 带内部上拉电阻(PULL_MODE=UP)
- 所有输入引脚配置为3.3V LVCMOS
- 支持0-3.3V逻辑电平输入
状态指示LED
- LED0 (引脚10): 状态指示位0
- LED1 (引脚11): 状态指示位1
- LED2 (引脚13): 状态指示位2
LED状态编码:
000(IDLE): 全灭001(CONFIG): LED0亮010(ARM): LED1亮011(SAMPLING): LED0+LED1亮100(READY): LED2亮101(TRANSMIT): LED0+LED2亮110(SET_FREQ): LED1+LED2亮
功能特性
1. 采样功能
- 8通道同步采样: 同时采样8个通道的逻辑信号
- 可配置采样率: 10kHz – 27MHz(通过分频比配置)
- 48KB缓冲区: 可存储49152个采样点
- 自动传输: 采样完成后自动通过UART发送数据
通道配置说明:
- CH0-CH2 (引脚25-27): 无内部上拉电阻,适合采样外部信号源
- 推荐用于:外部串口信号(RX_EXT)、频率输出(freq_out)、其他外部数字信号
- 优点:无上拉电阻干扰,能准确采样外部信号电平
- CH3-CH7 (引脚28-32): 带内部上拉电阻(PULL_MODE=UP)
- 推荐用于:需要上拉的信号、按键输入、开漏输出等
- 优点:悬空时为高电平,适合需要上拉的场景
2. 触发功能
支持8种触发模式:
| 模式 | 代码 | 说明 |
|---|---|---|
| 立即触发 | 0 | 无触发条件,立即开始采样 |
| 上升沿触发 | 1 | 检测到上升沿时触发 |
| 下降沿触发 | 2 | 检测到下降沿时触发 |
| 双边沿触发 | 3 | 检测到任意边沿时触发 |
| 高电平触发 | 4 | 检测到高电平时触发 |
| 低电平触发 | 5 | 检测到低电平时触发 |
| 模式触发 | 6 | 数据匹配指定模式时触发 |
| 序列触发 | 7 | 先匹配模式1,再匹配模式2时触发 |
触发参数:
- 触发通道掩码: 选择哪些通道参与触发(8位,1=启用)
- 触发模式1: 用于模式触发和序列触发的第一阶段
- 触发模式2: 用于序列触发的第二阶段
- 预触发采样: 在触发前采样指定数量的样本
3. 频率输出功能
- 可配置频率: 1Hz – 10MHz(通过分频比配置)
- 可配置占空比: 0-100%
- 输出引脚: 引脚84 (freq_out)
4. 数据分析功能
- 频率测量: 自动计算信号频率
- 占空比测量: 自动计算信号占空比
- 波形显示: 实时显示8通道波形
- 数据导出: 支持VCD和CSV格式导出
UART命令格式
命令列表
| 命令 | 代码 | 数据长度 | 说明 |
|---|---|---|---|
| CMD_START | 0x01 | 0 | 开始采样 |
| CMD_STOP | 0x02 | 0 | 停止采样 |
| CMD_SET_FREQ | 0x06 | 4字节 | 设置频率输出(小端序) |
| CMD_SET_SAMPLE_RATE | 0x07 | 4字节 | 设置采样率(小端序) |
| CMD_SET_DUTY | 0x08 | 4字节 | 设置占空比(小端序) |
| CMD_SET_TRIGGER | 0x09 | 6字节 | 设置触发配置 |
命令详细格式
CMD_SET_FREQ (0x06) – 设置频率输出
数据格式: 4字节,小端序(Little-Endian)
[字节0] 分频比低字节
[字节1] 分频比次低字节
[字节2] 分频比次高字节
[字节3] 分频比高字节
计算公式:
- 分频比 = 27MHz / 目标频率
- 实际频率 = 27MHz / 分频比
示例: 设置10kHz频率
- 分频比 = 27,000,000 / 10,000 = 2700
- 发送:
0x06 0xAC 0x0A 0x00 0x00(2700 = 0x00000AAC)
CMD_SET_SAMPLE_RATE (0x07) – 设置采样率
数据格式: 4字节,小端序
[字节0] 分频比低字节
[字节1] 分频比次低字节
[字节2] 分频比次高字节
[字节3] 分频比高字节
计算公式:
- 分频比 = 27MHz / 目标采样率
- 实际采样率 = 27MHz / 分频比
示例: 设置1MHz采样率
- 分频比 = 27,000,000 / 1,000,000 = 27
- 发送:
0x07 0x1B 0x00 0x00 0x00(27 = 0x0000001B)
CMD_SET_DUTY (0x08) – 设置占空比
数据格式: 4字节,小端序
[字节0] 高电平周期数低字节
[字节1] 高电平周期数次低字节
[字节2] 高电平周期数次高字节
[字节3] 高电平周期数高字节
注意: 必须先设置频率,再设置占空比
CMD_SET_TRIGGER (0x09) – 设置触发配置
数据格式: 6字节
[字节0] 触发类型 (0-7)
[字节1] 触发通道掩码 (8位,1=启用该通道)
[字节2] 触发模式1 (用于模式触发和序列触发)
[字节3] 触发模式2 (用于序列触发的第二阶段)
[字节4] 预触发数量低字节
[字节5] 预触发数量高字节
触发类型:
0x00: 立即触发0x01: 上升沿触发0x02: 下降沿触发0x03: 双边沿触发0x04: 高电平触发0x05: 低电平触发0x06: 模式触发0x07: 序列触发
示例: 设置上升沿触发(CH0),预触发1000个样本
- 发送:
0x09 0x01 0x01 0x00 0x00 0xE8 0x030x01: 上升沿触发0x01: 仅CH0启用 (0x01 = 00000001)0x00: 触发模式1(不使用)0x00: 触发模式2(不使用)0xE8 0x03: 预触发1000 (0x03E8 = 1000)
快速开始
1. 环境准备
硬件要求:
- TANG NANO 9K FPGA开发板
- USB Type-C数据线
- 待测信号源(可选)
软件要求:
- Python 3.7+
- 串口驱动(通常自动安装)
- matplotlib(用于波形显示)
- PulseView(可选,用于高级分析)
安装Python依赖:
pip install pyserial matplotlib
2. 基本使用
最简单的使用方式:
python examples/read_data.py COM11
这将:
- 连接到FPGA(COM11)
- 使用默认采样率(100kHz)
- 立即开始采样
- 自动接收数据
- 显示波形和分析结果
3. 外部串口使用
使用外部串口设备进行采样:
本逻辑分析仪支持通过外部串口设备发送数据,并通过RX_EXT引脚输出,然后连接到逻辑分析仪输入通道进行采样。
连接方式:
- 将外部串口设备的TX连接到FPGA的RX(引脚18)
- 将FPGA的RX_EXT(引脚34)连接到逻辑分析仪输入通道(如CH2,引脚27)
- 外部串口设备发送的数据会被FPGA接收,同时通过RX_EXT输出
- 逻辑分析仪可以采样RX_EXT输出的信号
使用示例:
# 设置采样率为1MHz,显示采样率为500kHz,占空比0.8,导出CSV
python examples/read_data.py COM11 --sample-rate 1M --display-rate 500k --duty 0.8 --export-csv
注意事项:
- 确保外部串口设备的波特率与FPGA UART配置一致(115200 bps)
- 采样率应足够高,建议至少是信号频率的5-10倍
- CH0-CH2通道无内部上拉,适合采样外部信号
4. 常用命令示例
设置采样率为1MHz:
python examples/read_data.py COM11 --sample-rate 1M
上升沿触发(CH0):
python examples/read_data.py COM11 --trigger rising --trigger-mask 0x01
模式触发(匹配0x55):
python examples/read_data.py COM11 --trigger pattern --trigger-pattern 0x55
导出为VCD格式(PulseView):
python examples/read_data.py COM11 --export-vcd
完整示例(采样率+触发+导出):
python examples/read_data.py COM11 --sample-rate 1M --trigger rising --trigger-mask 0x01 --pre-trigger 1000 --export-vcd
触发功能
触发模式详解
1. 立即触发 (immediate)
说明: 无触发条件,发送开始命令后立即开始采样
使用场景:
- 需要捕获所有数据
- 不需要等待特定条件
示例:
python examples/read_data.py COM11 --trigger immediate
2. 上升沿触发 (rising)
说明: 检测到上升沿(0→1)时触发
使用场景:
- 捕获信号启动时的数据
- 分析上升沿后的信号变化
示例:
# CH0上升沿触发
python examples/read_data.py COM11 --trigger rising --trigger-mask 0x01
# 所有通道上升沿触发
python examples/read_data.py COM11 --trigger rising --trigger-mask 0xFF
3. 下降沿触发 (falling)
说明: 检测到下降沿(1→0)时触发
使用场景:
- 捕获信号停止时的数据
- 分析下降沿后的信号变化
示例:
python examples/read_data.py COM11 --trigger falling --trigger-mask 0x01
4. 双边沿触发 (both)
说明: 检测到任意边沿(上升或下降)时触发
使用场景:
- 捕获信号变化时的数据
- 分析边沿前后的信号
示例:
python examples/read_data.py COM11 --trigger both --trigger-mask 0x01
5. 高电平触发 (high)
说明: 检测到高电平时触发
使用场景:
- 捕获高电平期间的数据
- 分析高电平状态
示例:
python examples/read_data.py COM11 --trigger high --trigger-mask 0x01
6. 低电平触发 (low)
说明: 检测到低电平时触发
使用场景:
- 捕获低电平期间的数据
- 分析低电平状态
示例:
python examples/read_data.py COM11 --trigger low --trigger-mask 0x01
7. 模式触发 (pattern)
说明: 数据匹配指定模式时触发
使用场景:
- 捕获特定数据模式
- 分析特定数据序列
示例:
# 匹配0x55模式(01010101)
python examples/read_data.py COM11 --trigger pattern --trigger-pattern 0x55
# 仅CH0-CH3匹配0x05
python examples/read_data.py COM11 --trigger pattern --trigger-mask 0x0F --trigger-pattern 0x05
8. 序列触发 (sequence)
说明: 先匹配模式1,再匹配模式2时触发
使用场景:
- 捕获特定数据序列
- 分析复杂的数据模式
示例:
# 先匹配0x55,再匹配0xAA
python examples/read_data.py COM11 --trigger sequence --trigger-pattern 0x55 --trigger-pattern2 0xAA
预触发功能
说明: 在触发条件满足前,先采样指定数量的样本
使用场景:
- 捕获触发前的数据
- 分析触发前后的完整波形
示例:
# 上升沿触发,预触发1000个样本
python examples/read_data.py COM11 --trigger rising --pre-trigger 1000
工作原理:
- 系统进入ARM状态,等待触发
- 持续采样数据到缓冲区(循环覆盖)
- 检测到触发条件时,继续采样预触发数量的样本
- 然后开始正常采样,直到缓冲区满
注意事项:
- 预触发数量不能超过缓冲区大小(49152)
- 建议预触发数量 < 10000,以确保有足够空间存储触发后的数据
PulseView支持
什么是PulseView?
PulseView是一个开源的逻辑分析仪软件,支持多种硬件和文件格式。本逻辑分析仪支持导出VCD和CSV格式,可以在PulseView中打开和分析。
导出格式
1. VCD格式 (Value Change Dump)
特点:
- 标准格式,广泛支持
- 包含时间信息
- 适合波形分析
导出方法:
python examples/read_data.py COM11 --export-vcd
输出文件: logic_analyzer_data.vcd
2. CSV格式 (Comma-Separated Values)
特点:
- 易于处理和分析
- 可以用Excel打开
- 适合数据分析
导出方法:
python examples/read_data.py COM11 --export-csv
输出文件: logic_analyzer_data.csv
在PulseView中打开
方法1: 直接打开VCD文件
- 启动PulseView
- 选择
File→Open - 选择
logic_analyzer_data.vcd - 波形将自动加载
方法2: 导入CSV文件
- 启动PulseView
- 选择
File→Import - 选择
CSV格式 - 选择
logic_analyzer_data.csv - 配置导入参数(采样率、通道数等)
PulseView高级功能
协议解码
PulseView支持多种协议解码:
- UART
- SPI
- I2C
- 1-Wire
- 等等
使用方法:
- 在PulseView中打开VCD文件
- 选择信号
- 右键 →
Add Decoder→ 选择协议 - 配置协议参数(波特率、数据位等)
测量和分析
- 时间测量: 测量信号周期、脉宽等
- 频率分析: 分析信号频率
- 统计信息: 统计高/低电平时间
- 搜索功能: 搜索特定模式
高级功能
1. 频率输出配置
设置频率输出:
python examples/read_data.py COM11 --freq 10000
设置频率和占空比:
python examples/read_data.py COM11 --freq 10000 --duty 50
频率范围: 1Hz – 10MHz
占空比范围: 0-100%
2. 采样率配置
预设采样率:
27M: 27MHz(最大)13.5M: 13.5MHz9M: 9MHz6.75M: 6.75MHz5.4M: 5.4MHz1M: 1MHz500k: 500kHz100k: 100kHz(默认)50k: 50kHz10k: 10kHz1k: 1kHz
使用示例:
# 使用预设值
python examples/read_data.py COM11 --sample-rate 1M
# 使用自定义值
python examples/read_data.py COM11 --sample-rate 500000
3. 显示采样率
说明: 用于计算和显示的采样率(不影响FPGA硬件采样率)
使用场景:
- FPGA采样率与显示采样率不同时
- 需要调整显示时间轴时
示例:
python examples/read_data.py COM11 --sample-rate 1M --display-rate 500k
4. 命令行选项完整列表
python examples/read_data.py <COM端口> [选项]
选项:
--no-plot 不显示波形图
--save 保存原始数据到文件 (.bin)
--export-vcd 导出为 VCD 格式(PulseView 支持)
--export-csv 导出为 CSV 格式(PulseView 支持)
--stop 手动停止采样(否则等待缓冲区满)
--freq <Hz> 设置频率输出(在采样前)
--duty <值> 设置占空比(在采样前,需要先设置频率)
--sample-rate <Hz> 设置FPGA硬件采样率
--display-rate <Hz> 指定显示用采样率(仅用于计算和显示)
--trigger <类型> 设置触发类型
--trigger-mask <值> 触发通道掩码(十六进制)
--trigger-pattern <值> 触发模式1(十六进制)
--trigger-pattern2 <值> 触发模式2(十六进制)
--pre-trigger <数量> 预触发采样数量
常见问题
Q1: 无法连接到FPGA
可能原因:
- 串口号错误
- 串口被其他程序占用
- USB驱动未安装
解决方法:
- 检查设备管理器中的串口号
- 关闭其他可能占用串口的程序
- 重新安装USB驱动
Q2: 采样数据不正确
可能原因:
- 采样率设置过低
- 信号频率过高
- 通道连接问题
- 通道上拉电阻影响(CH3-CH7有上拉,CH0-CH2无上拉)
解决方法:
- 提高采样率(至少是信号频率的5-10倍)
- 检查信号连接
- 使用示波器验证信号
- 对于外部信号采样,建议使用CH0-CH2(无上拉电阻)
- 对于需要上拉的信号,使用CH3-CH7
Q3: 触发功能不工作
可能原因:
- 触发条件不满足
- 触发通道掩码设置错误
- 信号状态不符合触发条件
解决方法:
- 检查信号状态是否满足触发条件
- 确认触发通道掩码正确
- 使用立即触发模式测试
Q4: 频率测量不准确
可能原因:
- 采样率设置不正确
- 信号边沿不够清晰
- 信号频率过高
解决方法:
- 确保采样率至少是信号频率的10倍
- 检查信号质量
- 使用更高的采样率
Q5: PulseView无法打开VCD文件
可能原因:
- 文件格式错误
- PulseView版本过旧
- 文件损坏
解决方法:
- 重新导出VCD文件
- 更新PulseView到最新版本
- 检查文件是否完整
技术规格
性能参数
| 参数 | 规格 |
|---|---|
| 最大采样率 | 27MHz |
| 最小采样率 | ~1kHz |
| 采样深度 | 49152样本/通道 |
| 通道数 | 8通道 |
| 输入电压范围 | 0-3.3V |
| 输入逻辑电平 | LVCMOS 3.3V |
| 通信波特率 | 115200 bps |
| 缓冲区大小 | 48KB |
资源使用
- BRAM: ~48KB (用于数据缓冲区)
- LUT: 根据配置变化
- FF: 根据配置变化
更新日志
v1.0 (当前版本)
- ✅ 8通道逻辑分析仪
- ✅ 可配置采样率(10kHz – 27MHz)
- ✅ 8种触发模式
- ✅ 预触发功能
- ✅ 频率输出和占空比配置
- ✅ PulseView支持(VCD/CSV导出)
- ✅ RX/RX_EXT同步输出
- ✅ 外部串口数据采样支持
- ✅ CH0-CH2无上拉配置,适合外部信号采样
- ✅ 已验证外部串口数据采样功能正常
许可证
本项目采用开源许可证,详见LICENSE文件。
联系方式
如有问题或建议,请提交Issue或Pull Request。