【ALINX 实战笔记】FPGA 大神 Adam Taylor 使用 ChipScope 调试 AMD Versal 设计
本篇文章来自 FPGA 大神、Ardiuvo & Hackster.IO 知名博主 Adam Taylor。在这里感谢 Adam Taylor 对 ALINX 产品的关注与使用。为了让文章更易阅读,我们在原文的基础上作了一些灵活的调整。原文链接已贴在文章底部,欢迎大家在评论区友好互动。
在上篇文章中,我们已经通过测试图案生成器,成功验证了 ALINX VD100 的图像显示链路。
这次终于要接入 MIPI 摄像头,进行真正的图像处理了!
在这个过程中,集成逻辑分析仪(ILA)将作为我们的调试“透视眼”,帮助我们逐步验证每一阶段的运行效果。
本项目规模不小,从图像采集到处理再到输出,每一环都可能出现问题——做好调试准备了吗?
那就让我们开始吧!
项目工具清单
本次开发平台基于 AMD Versal AI Edge 芯片,开发板采用 ALINX 的 VD100。
Versal AI Edge 系列是 AMD 推出的系统级异构芯片(SoC),专为边缘端 AI 应用优化,集成了 Arm Cortex-A72 应用处理器、Cortex-R5F 实时处理器、可编程逻辑(PL)以及 AI 引擎专用加速模块等多种处理单元。这些模块通过片上网络(NoC)实现高效互联,形成强大灵活的计算平台,非常适合本地化部署卷积神经网络(CNN)等 AI 推理任务。
ALINX VD100 开发板配备了 2 个 4 通道的 MIPI 摄像头输入接口,以及一个 LVDS LCD 显示输出,并且支持 Vivado免费版开发环境,对原型验证和早期开发者极其友好。
在进入 AI 阶段前,我们需要打好基础——构建一条稳定的图像处理通路。基本流程如下:
1. 图像采集(MIPI 摄像头)
2. 预处理(去马赛克、颜色空间转换、图像增强)
3. 缓存存储(VDMA + DDR)
4. 图像显示(LVDS LCD 输出)
一个可靠的图像通路必须满足三个条件:
1. 摄像头正常采集
2. 数据通路不丢包
3. 显示输出无错帧
通过早期验证这些关键环节,可确保 I/O 分配、时钟策略和图像处理流程的正确性,降低在集成上层 AI 逻辑或应用功能时的开发风险。只有基础打牢,后续的开发迭代才能更高效,项目推进也更有把握。
Versal 调试机制
虽然 Versal 器件的应用调试与 7 系列、UltraScale 及 UltraScale+ 系列大体相似(均可使用 ChipScope 工具),但在使用方式上也发生了一些变化:
_ | 旧平台(7/US/US+等) | Versal 平台 |
Debug hub 连接方式 | 通过 JTAG 接口 | 通过 CIPS 中的 AXI4 接口 |
Debug hub 插入方式 | 自动插入 | 自动/手动 (涉及 DFX 必须手动) |
Debug Core 接口协议 | 专有接口 | 标准 AXI4-Stream |
AXI-Stream ILA 特性 | 集成标准ILA+System ILA 支持 BRAM/URAM存储介质选择 | 标准 ILA 与 System ILA 分立 存储介质固定 |
Versal 的调试架构更加现代化,也更加灵活,但也意味着你在设计之初就必须考虑调试资源的布局,尤其是 CIPS 模块和 AXI 调试路径 的预留。
调试方法论
FPGA 开发是一个需要多次迭代的过程,只有遵循逻辑推理的方法,才能更高效地解决问题,不至于造成资源浪费。我在调试时遵循以下原则帮助我更快速地排查问题:
1. 问题拆解:将复杂问题拆解为更小的部分
2. 控制变量:减少变量与干扰项
3. 假设验证:做出合理预测,并验证预测结果
4. 前瞻规划:在设计初期就规划好调试方案与观测点位置
ILA 插桩策略
集成逻辑分析仪(ILA)使用起来非常占用逻辑和 BRAM 资源,且采样深度、监控信号的宽度也会直接影响 BRAM 的使用量——探针越宽、采样窗口越长,占用的内存越多,资源也越快耗尽。
在真实项目中使用 ILA 进行调试时,必须合理选择插桩位置,以平衡调试可视性与 FPGA 资源的使用。我的建议是,在遵循前述调试方法论的条件下:
1. 优先监控控制信号、复位线、状态/错误标志等关键位置。这些信号通常可以第一时间反映系统行为,帮助我们在调试早期就定位问题。
2. 逐步拓展至一些关键的 AXI 总线,尤其是连接 Versal 的片上网络(NoC)与处理系统(PS)的部分,这些接口是可编程逻辑(PL)、NoC 与 PS 之间的数据主通道,能揭示系统集成与数据传输过程中的一些微妙问题。
因此,在调试初期,我们可以从一组合理的控制信号、复位、状态/错误信息以及关键 AXI 接口信号入手,采用中等采样深度。
这样既能获得系统层面的良好可视性,又能为后续迭代调试保留资源空间。
Vivado 设计架构
基于 Versal AI Edge 的图像处理流水线,核心架构通过 CIPS 模块实现全局控制;图像帧通过一系列 IP 模块被采集与处理;应用程序、DDR 内存访问以及 CIPS 与可编程逻辑(PL)之间的通信,通过片上网络(NoC)实现高速互联。
系统的整体结构如下图所示:
具体使用的 IP 核取决于应用需求,但核心流水线一般包括:传感器接口、去马赛克(Demosaic)、颜色空间转换、图像增强、视频时序控制模块,以及 AXI Stream 的互联与控制逻辑。
ILA 模块
ILA_LCD_LVDS
→ 监控 LCD / LVDS 接口,观察状态与错误信号。
Video ILA
→ 使用四个通道,监控图像处理流程中的 AXI-Stream 视频信号,包括 MIPI 原始输出、去马赛克后的 RGB 流、24 位像素转换输出与 VDMA 输出流。
Memory ILA
→ 监控通过 NoC 访问 DDR 的 AXI4 总线,确保 DDR 的读写操作正常进行。
Output ILA
→ 监控 AXI-Stream 到视频输出的状态信息,如视频输出同步信号诊断(HSync/VSync 相位对齐监测)
IP 模块
CIPS
→ 配置处理系统(PS)、平台初始化,提供外设访问。
NoC
→ 提供高带宽的数据流通通道,连接多个互联节点,并集成 DDR 控制器用于外部内存访问。
SmartConnect
→ 连接各 IP 模块的 AXI-Lite 寄存器接口,使处理系统可以对其进行控制与配置。
MIPI CSI-2 RX
→ 支持 4 通道,每通道 1000 Mbps 的高速图像采集。
Demosaic(去马赛克)
→ 将图像传感器输出的 Bayer 模式像素数据转换为完整 RGB 图像,重建每个像素的颜色信息。
AXI Subset Converter
→ 将 40 位像素数据(每个 RGB 通道 10 位)转换为 24 位格式(每通道 8 位),每时钟周期保持 4 像素吞吐。
VDMA
→ 桥接 AXI4-Stream 与 AXI4 存储接口,在 NoC 上实现 DDR 帧存的存取,同时为处理阶段提供高效的缓存机制。
AXI4-Stream to Video Out
→ 将 AXI4-Stream 视频流转换为标准视频输出格式,生成 HSync、VSync 等同步信号以驱动显示设备。
VTC
→ 生成 HSync、VSync、有效视频等信号,并与AXI4-Stream to Video Out模块同步,确保显示时序正确。
LCD LVDS 接口
→ 将标准并行视频输出信号转换为串行 VESA LVDS 格式,适配基于 LVDS 的 LCD 显示屏。
Advanced IO Wizard
→ 配置 Versal 设备中的 XPIO,将 LVDS 输出数据串行化,满足 VESA LVDS 显示标准。
通过这些 ILA,我们能够同时观察静态的状态信号与动态的高带宽数据流,全面掌控图像处理系统的运行状态。
完整设计如图所示,可通过本项目所附的 TCL 脚本复现该设计。
在生成比特流时,必须定义 XDC I/O 约束文件,明确所有外部接口的物理引脚位置与电气标准。
关键接口的引脚配置如下:
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property DIFF_TERM_ADV TERM_100 [get_ports sys_clk_p]
set_property PACKAGE_PIN A23 [get_ports {clkout1_p[0]}]
set_property IOSTANDARD LVDS15 [get_ports {clkout1_p[0]}]
set_property PACKAGE_PIN F22 [get_ports {dataout1_p_0[0]}]
set_property PACKAGE_PIN A20 [get_ports {dataout1_p_1[0]}]
set_property PACKAGE_PIN C22 [get_ports {dataout1_p_2[0]}]
set_property PACKAGE_PIN A25 [get_ports {dataout1_p_3[0]}]
set_property IOSTANDARD LVDS15 [get_ports {dataout1_p_*[0]}]
set_property PACKAGE_PIN E24 [get_ports {lcd_en}]
set_property IOSTANDARD LVCMOS15 [get_ports {lcd_en}]
set_property PACKAGE_PIN D24 [get_ports {lcd_sync}]
set_property IOSTANDARD LVCMOS15 [get_ports {lcd_sync}]
set_property PACKAGE_PIN AC11 [get_ports {DDR4_act_n[0]}]
set_property PACKAGE_PIN AB12 [get_ports {DDR4_adr[0]}]
set_property PACKAGE_PIN AB17 [get_ports {DDR4_adr[10]}]
set_property PACKAGE_PIN AE13 [get_ports {DDR4_adr[11]}]
set_property PACKAGE_PIN AH12 [get_ports {DDR4_adr[12]}]
set_property PACKAGE_PIN AD15 [get_ports {DDR4_adr[13]}]
set_property PACKAGE_PIN AD21 [get_ports {DDR4_adr[14]}]
set_property PACKAGE_PIN AD17 [get_ports {DDR4_adr[15]}]
set_property PACKAGE_PIN AC13 [get_ports {DDR4_adr[16]}]
set_property PACKAGE_PIN AE22 [get_ports {DDR4_adr[1]}]
set_property PACKAGE_PIN AD22 [get_ports {DDR4_adr[2]}]
set_property PACKAGE_PIN AB15 [get_ports {DDR4_adr[3]}]
set_property PACKAGE_PIN AD12 [get_ports {DDR4_adr[4]}]
set_property PACKAGE_PIN AE17 [get_ports {DDR4_adr[5]}]
set_property PACKAGE_PIN AD16 [get_ports {DDR4_adr[6]}]
set_property PACKAGE_PIN AG11 [get_ports {DDR4_adr[7]}]
set_property PACKAGE_PIN AE14 [get_ports {DDR4_adr[8]}]
set_property PACKAGE_PIN AB14 [get_ports {DDR4_adr[9]}]
set_property PACKAGE_PIN AC16 [get_ports {DDR4_ba[0]}]
set_property PACKAGE_PIN AD11 [get_ports {DDR4_ba[1]}]
set_property PACKAGE_PIN AB18 [get_ports {DDR4_bg[0]}]
set_property PACKAGE_PIN AC19 [get_ports {DDR4_ck_t[0]}]
set_property PACKAGE_PIN AD19 [get_ports {DDR4_ck_c[0]}]
set_property PACKAGE_PIN AB21 [get_ports {DDR4_cke[0]}]
set_property PACKAGE_PIN AC17 [get_ports {DDR4_cs_n[0]}]
set_property PACKAGE_PIN AG12 [get_ports {DDR4_dm_n[0]}]
set_property PACKAGE_PIN AH13 [get_ports {DDR4_dm_n[1]}]
set_property PACKAGE_PIN AE28 [get_ports {DDR4_dm_n[2]}]
set_property PACKAGE_PIN AD24 [get_ports {DDR4_dm_n[3]}]
set_property PACKAGE_PIN V22 [get_ports {DDR4_dm_n[4]}]
set_property PACKAGE_PIN V28 [get_ports {DDR4_dm_n[5]}]
set_property PACKAGE_PIN N28 [get_ports {DDR4_dm_n[6]}]
set_property PACKAGE_PIN U25 [get_ports {DDR4_dm_n[7]}]
set_property PACKAGE_PIN AF14 [get_ports {DDR4_dq[0]}]
set_property PACKAGE_PIN AH18 [get_ports {DDR4_dq[10]}]
set_property PACKAGE_PIN AH20 [get_ports {DDR4_dq[11]}]
set_property PACKAGE_PIN AH14 [get_ports {DDR4_dq[12]}]
set_property PACKAGE_PIN AH22 [get_ports {DDR4_dq[13]}]
set_property PACKAGE_PIN AH15 [get_ports {DDR4_dq[14]}]
set_property PACKAGE_PIN AG22 [get_ports {DDR4_dq[15]}]
set_property PACKAGE_PIN AF26 [get_ports {DDR4_dq[16]}]
set_property PACKAGE_PIN AE26 [get_ports {DDR4_dq[17]}]
set_property PACKAGE_PIN AH27 [get_ports {DDR4_dq[18]}]
set_property PACKAGE_PIN AE27 [get_ports {DDR4_dq[19]}]
set_property PACKAGE_PIN AG18 [get_ports {DDR4_dq[1]}]
set_property PACKAGE_PIN AG27 [get_ports {DDR4_dq[20]}]
set_property PACKAGE_PIN AD26 [get_ports {DDR4_dq[21]}]
set_property PACKAGE_PIN AG26 [get_ports {DDR4_dq[22]}]
set_property PACKAGE_PIN AG28 [get_ports {DDR4_dq[23]}]
set_property PACKAGE_PIN AE24 [get_ports {DDR4_dq[24]}]
set_property PACKAGE_PIN AD25 [get_ports {DDR4_dq[25]}]
set_property PACKAGE_PIN AH24 [get_ports {DDR4_dq[26]}]
set_property PACKAGE_PIN AF25 [get_ports {DDR4_dq[27]}]
set_property PACKAGE_PIN AG23 [get_ports {DDR4_dq[28]}]
set_property PACKAGE_PIN AG25 [get_ports {DDR4_dq[29]}]
set_property PACKAGE_PIN AG15 [get_ports {DDR4_dq[2]}]
set_property PACKAGE_PIN AH23 [get_ports {DDR4_dq[30]}]
set_property PACKAGE_PIN AH25 [get_ports {DDR4_dq[31]}]
set_property PACKAGE_PIN Y22 [get_ports {DDR4_dq[32]}]
set_property PACKAGE_PIN V23 [get_ports {DDR4_dq[33]}]
set_property PACKAGE_PIN Y23 [get_ports {DDR4_dq[34]}]
set_property PACKAGE_PIN W24 [get_ports {DDR4_dq[35]}]
set_property PACKAGE_PIN AA22 [get_ports {DDR4_dq[36]}]
set_property PACKAGE_PIN V24 [get_ports {DDR4_dq[37]}]
set_property PACKAGE_PIN AA21 [get_ports {DDR4_dq[38]}]
set_property PACKAGE_PIN W25 [get_ports {DDR4_dq[39]}]
set_property PACKAGE_PIN AF18 [get_ports {DDR4_dq[3]}]
set_property PACKAGE_PIN V25 [get_ports {DDR4_dq[40]}]
set_property PACKAGE_PIN W27 [get_ports {DDR4_dq[41]}]
set_property PACKAGE_PIN AA28 [get_ports {DDR4_dq[42]}]
set_property PACKAGE_PIN W26 [get_ports {DDR4_dq[43]}]
set_property PACKAGE_PIN Y26 [get_ports {DDR4_dq[44]}]
set_property PACKAGE_PIN AA26 [get_ports {DDR4_dq[45]}]
set_property PACKAGE_PIN AB28 [get_ports {DDR4_dq[46]}]
set_property PACKAGE_PIN AB26 [get_ports {DDR4_dq[47]}]
set_property PACKAGE_PIN P27 [get_ports {DDR4_dq[48]}]
set_property PACKAGE_PIN K27 [get_ports {DDR4_dq[49]}]
set_property PACKAGE_PIN AF13 [get_ports {DDR4_dq[4]}]
set_property PACKAGE_PIN R28 [get_ports {DDR4_dq[50]}]
set_property PACKAGE_PIN L28 [get_ports {DDR4_dq[51]}]
set_property PACKAGE_PIN R27 [get_ports {DDR4_dq[52]}]
set_property PACKAGE_PIN K28 [get_ports {DDR4_dq[53]}]
set_property PACKAGE_PIN T28 [get_ports {DDR4_dq[54]}]
set_property PACKAGE_PIN M27 [get_ports {DDR4_dq[55]}]
set_property PACKAGE_PIN P25 [get_ports {DDR4_dq[56]}]
set_property PACKAGE_PIN L26 [get_ports {DDR4_dq[57]}]
set_property PACKAGE_PIN R26 [get_ports {DDR4_dq[58]}]
set_property PACKAGE_PIN M26 [get_ports {DDR4_dq[59]}]
set_property PACKAGE_PIN AF19 [get_ports {DDR4_dq[5]}]
set_property PACKAGE_PIN T25 [get_ports {DDR4_dq[60]}]
set_property PACKAGE_PIN K26 [get_ports {DDR4_dq[61]}]
set_property PACKAGE_PIN T26 [get_ports {DDR4_dq[62]}]
set_property PACKAGE_PIN J25 [get_ports {DDR4_dq[63]}]
set_property PACKAGE_PIN AG13 [get_ports {DDR4_dq[6]}]
set_property PACKAGE_PIN AE19 [get_ports {DDR4_dq[7]}]
set_property PACKAGE_PIN AH17 [get_ports {DDR4_dq[8]}]
set_property PACKAGE_PIN AG21 [get_ports {DDR4_dq[9]}]
set_property PACKAGE_PIN AG17 [get_ports {DDR4_dqs_t[0]}]
set_property PACKAGE_PIN AG16 [get_ports {DDR4_dqs_c[0]}]
set_property PACKAGE_PIN AG20 [get_ports {DDR4_dqs_t[1]}]
set_property PACKAGE_PIN AH19 [get_ports {DDR4_dqs_c[1]}]
set_property PACKAGE_PIN AC28 [get_ports {DDR4_dqs_t[2]}]
set_property PACKAGE_PIN AD27 [get_ports {DDR4_dqs_c[2]}]
set_property PACKAGE_PIN AF24 [get_ports {DDR4_dqs_t[3]}]
set_property PACKAGE_PIN AF23 [get_ports {DDR4_dqs_c[3]}]
set_property PACKAGE_PIN Y24 [get_ports {DDR4_dqs_t[4]}]
set_property PACKAGE_PIN AA23 [get_ports {DDR4_dqs_c[4]}]
set_property PACKAGE_PIN Y28 [get_ports {DDR4_dqs_t[5]}]
set_property PACKAGE_PIN Y27 [get_ports {DDR4_dqs_c[5]}]
set_property PACKAGE_PIN U27 [get_ports {DDR4_dqs_t[6]}]
set_property PACKAGE_PIN U28 [get_ports {DDR4_dqs_c[6]}]
set_property PACKAGE_PIN P26 [get_ports {DDR4_dqs_t[7]}]
set_property PACKAGE_PIN N27 [get_ports {DDR4_dqs_c[7]}]
set_property PACKAGE_PIN AC22 [get_ports {DDR4_odt[0]}]
set_property PACKAGE_PIN AC24 [get_ports {DDR4_reset_n[0]}]
set_property PACKAGE_PIN AB23 [get_ports {sys_clk_clk_p[0]}]
set_property PACKAGE_PIN AC23 [get_ports {sys_clk_clk_n[0]}]
set_property IOSTANDARD LVDS15 [get_ports {sys_clk_clk_n[0]}]
set_property IOSTANDARD LVDS15 [get_ports {sys_clk_clk_p[0]}]
create_clock -period 5.000 -name sys_clk -waveform {0.000 2.500} [get_ports {sys_clk_clk_p[0]}]
set_property PACKAGE_PIN G26 [get_ports {cam1_gpio[0]}]
set_property IOSTANDARD LVCMOS15 [get_ports {cam1_gpio[0]}]
set_property PULLUP true [get_ports {cam1_gpio[0]}]
set_property PACKAGE_PIN G27 [get_ports cam1_i2c_scl_io]
set_property PACKAGE_PIN F28 [get_ports cam1_i2c_sda_io]
set_property IOSTANDARD LVCMOS15 [get_ports cam1_i2c_scl_io]
set_property IOSTANDARD LVCMOS15 [get_ports cam1_i2c_sda_io]
set_property PULLUP true [get_ports cam1_i2c_scl_io]
set_property PULLUP true [get_ports cam1_i2c_sda_io]
set_property PACKAGE_PIN U23 [get_ports mipi_phy_if_0_clk_p]
set_property PACKAGE_PIN T23 [get_ports mipi_phy_if_0_data_p[0]]
set_property PACKAGE_PIN R23 [get_ports mipi_phy_if_0_data_p[1]]
set_property PACKAGE_PIN L23 [get_ports mipi_phy_if_0_data_p[2]]
set_property PACKAGE_PIN M22 [get_ports mipi_phy_if_0_data_p[3]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_clk_p]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_clk_n]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_p[0]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_n[0]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_p[1]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_n[1]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_p[2]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_n[2]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_p[3]]
set_property IOSTANDARD MIPI_DPHY [get_ports mipi_phy_if_0_data_n[3]]
set_property CLOCK_REGION X3Y0 [get_cells -hier -filter {name =~ *mipi_csi2_rx_subsyst_1/inst/phy/inst/inst/rxbyteclkhs_buf}]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -hier -filter {name =~ *mipi_csi2_rx_subsyst_0/inst/phy/inst/inst/*/inst/BANK_WRAPPER_INST0/fifo_wr_clk[0]}]
应用软件配置
应用软件将基于 Vitis 统一软件平台进行开发,负责执行以下关键任务:
-
配置摄像头(借助 ALINX 提供的初始化文件)。
-
配置视频时序控制器(VTC),输出 720p 所需的同步信号。
-
配置 Demosaic IP,实现正确的颜色重建。
-
通过 GPIO 控制信号启动摄像头。
-
配置 VDMA 与 DDR 进行高效读写。
完整软件项目已上传至我的 GitHub,可供参考与复用。
#include <stdio.h>
#include "math.h"
#include <ctype.h>
#include <stdlib.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xiicps.h"
#include "i2c/PS_i2c.h"
#include "demosaic/demosaic.h"
#include "cam_config.h"
#include "config.h"
#include "sleep.h"#include "xil_cache.h"#include "xgpiops.h"
#include "xscugic.h"
#include "vtc.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"//#include "ff.h"
/* ------------------------------------------------------------ */
/* Global Variables */
/* ------------------------------------------------------------ */#define LED_MIO 25
#define CAM1_EMIO 26
#define CAM2_EMIO 27XAxiVdma vdma;
XAxiVdma_DmaSetup vdmaDMA;
XAxiVdma_Config *vdmaConfig;XVtc Vtc_inst;//static int WriteError;int wr_index=0;
int rd_index=0;XIicPs ps_i2c0;
XIicPs ps_i2c1;
XGpioPs GPIO_PTR ;int PsGpioSetup() ;/** Framebuffers for video data*/u8 frameBuf0[1][DEMO_MAX_FRAME] __attribute__ ((aligned(4096)));
u8 *pFrames0; void InitVideoFmt(XIicPs *IicInstance,int w, int h)
{i2c_reg16_write(IicInstance, 0x36, 0x3808, (w>>8)&0xff);i2c_reg16_write(IicInstance, 0x36, 0x3809, (w>>0)&0xff);i2c_reg16_write(IicInstance, 0x36, 0x380a, (h>>8)&0xff);i2c_reg16_write(IicInstance, 0x36, 0x380b, (h>>0)&0xff);}void InitDisplay()
{Vtc_init(&Vtc_inst,VMODE_1280x720);}int main(void)
{int i;int Status;PsGpioSetup() ;for (i = 0; i < 1; i++) {pFrames0 = frameBuf0[i];}demosaic_init(XPAR_V_DEMOSAIC_0_BASEADDR,VIDEO_COLUMNS,VIDEO_ROWS);i2c_init(&ps_i2c0,100000);XGpioPs_WritePin(&GPIO_PTR, CAM1_EMIO, 1) ;usleep(500000);XGpioPs_WritePin(&GPIO_PTR, CAM1_EMIO, 0) ;usleep(500000);XGpioPs_WritePin(&GPIO_PTR, CAM1_EMIO, 1) ;usleep(500000);sensor_init(&ps_i2c0);InitVideoFmt(&ps_i2c0,VIDEO_COLUMNS,VIDEO_ROWS);InitDisplay();xil_printf("config done!\r\n");vdmaConfig = XAxiVdma_LookupConfig(XPAR_AXI_VDMA_0_BASEADDR);XAxiVdma_CfgInitialize(&vdma, vdmaConfig, vdmaConfig->BaseAddress);//video = VMODE_1280x720;vdmaDMA.FrameDelay = 0;vdmaDMA.EnableCircularBuf = 1;vdmaDMA.EnableSync = 0;vdmaDMA.PointNum = 0;vdmaDMA.EnableFrameCounter = 0;vdmaDMA.VertSizeInput = 720;vdmaDMA.HoriSizeInput = (1280)*3;vdmaDMA.FixedFrameStoreAddr = 0;vdmaDMA.FrameStoreStartAddr[0] = (u32) pFrames0[0];vdmaDMA.Stride = (1280)*3;XAxiVdma_DmaConfig(&vdma, XAXIVDMA_WRITE, &(vdmaDMA));XAxiVdma_DmaSetBufferAddr(&vdma, XAXIVDMA_WRITE,vdmaDMA.FrameStoreStartAddr);XAxiVdma_DmaConfig(&vdma, XAXIVDMA_READ, &(vdmaDMA));XAxiVdma_DmaSetBufferAddr(&vdma, XAXIVDMA_READ,vdmaDMA.FrameStoreStartAddr);XAxiVdma_DmaStart(&vdma, XAXIVDMA_WRITE);//Status = XAxiVdma_StartParking(&vdma, 0, XAXIVDMA_WRITE);XAxiVdma_DmaStart(&vdma, XAXIVDMA_READ);//XAxiVdma_StartParking(&vdma, 0, XAXIVDMA_READ);while(1){XGpioPs_WritePin(&GPIO_PTR, LED_MIO, 0) ;usleep(500000);XGpioPs_WritePin(&GPIO_PTR, LED_MIO, 1) ;usleep(500000);}return 0;
}int PsGpioSetup()
{XGpioPs_Config *GPIO_CONFIG ;int Status ;GPIO_CONFIG = XGpioPs_LookupConfig(XPAR_XGPIOPS_0_DEVICE_ID) ;Status = XGpioPs_CfgInitialize(&GPIO_PTR, GPIO_CONFIG, GPIO_CONFIG->BaseAddr) ;if (Status != XST_SUCCESS){return XST_FAILURE ;}XGpioPs_SetDirectionPin(&GPIO_PTR, LED_MIO, 1) ;XGpioPs_SetOutputEnablePin(&GPIO_PTR, LED_MIO, 1) ;return XST_SUCCESS ;
}
ILA 验证
当系统软件运行时,我们可以借助 ILA 来验证图像处理流水线是否按预期工作。
这些 ILA 在系统优化与调试过程中也发挥着关键作用。
在 Vivado 硬件管理器中,每个 ILA 会被映射为一个数字编号,映射关系如下:
-
ILA1:Memory ILA
-
ILA2:Output ILA
-
ILA3:LCD LVDS ILA
-
ILA4:Video ILA
验证的第一步是监控 AXI4-Stream to Video Out 模块的状态信号。
该 IP 会输出多个指示信号,用于表征 AXI 视频流与视频时序信号是否同步。
如果输入的视频时序存在不匹配或不稳定的情况,该模块将无法锁定,导致视频无法输出。
由于该模块内部包含 FIFO 存储器,我们可以通过 ILA 观察其上溢和下溢状态信号。这些信号对于诊断流水线中的数据不足(data starvation)或背压(backpressure)等性能问题尤为重要,能够指导我们改进存储带宽或缓冲策略。
在 ILA1(即 Output ILA)上观察这些信号,可以看到包含视频数据的 AXI Stream 信号与视频时序控制器生成的时序信号已经保持同步。如果 AXI Stream 信号格式不匹配(例如视频格式不符),AXI4 Stream to Video Out 模块将无法完成同步锁定。
验证过程的下一步是检查 LCD LVDS 输出接口。该阶段的关键状态指示可以确认内部时钟是否锁定,以及接口是否成功启用向显示屏传输数据。监控这些信号,有助于确保序列化视频流被正确生成并传输至 LCD 面板,若出现时钟错误或链路未启用等问题,也能迅速定位。
在验证图像处理通路本身时,首先要检查的是MIPI CSI-2 RX 子系统的视频输出。
在此阶段,我们应该观察到每个时钟周期输出 4 像素的 10 bit 原始数据。如果相机配置或 MIPI 接口存在问题,通常会在此处显现为无视频输出或格式异常。验证此输出有助于确认相机初始化是否正确以及 MIPI 链路是否正常建立。
MIPI CSI-2 RX 子系统的输出会送入Demosaic去马赛克模块,它会将 Bayer 格式的 10 位原始像素转换为 30 位 RGB 格式(每个颜色通道 10 位)。由于流水线保持每个时钟处理 4 像素的吞吐量,去马赛克模块输出的 AXI4-Stream 数据总宽度为 120 位(4 像素×30 位),在维持高吞吐量的同时提供完整重构的色彩数据。
LCD 显示屏需要 24 位 RGB 像素(每个颜色通道 8 位)。为满足这一要求,AXI 子集转换器将每像素深度从 30 位压缩至 24 位。系统继续保持每个时钟处理 4 像素的速率,因此转换器输出总线宽度为 96 位(4 像素×24 位),与下游视频输出路径的格式要求完全匹配。
在写入路径上,我们可以观察到 AXI4 总线将处理后的视频帧写入 DDR 存储器的过程。这些传输由 VDMA 发起,它作为 AXI4-Stream 视频流水线与 AXI4 存储器映射接口的桥梁,通过片上网络(NoC)实现帧数据的高效存储。监控这一过程可确保帧缓冲正确写入存储器,供后续读取显示。
读取路径始于 VDMA 通过 NoC 发起 AXI4 读操作,从 DDR 存储器中获取视频帧。这些操作将存储的帧数据重新送回 AXI4-Stream 域,使其能在流水线中继续流向显示端。观察这些 AXI4 读操作可以确认存储器访问功能正常,且帧数据的获取与视频输出时序保持同步。
图像处理流水线的最后环节是 VDMA 输出的 AXI4-Stream 信号,该接口每个时钟周期传输 1 个像素。该数据流输入 AXI4-Stream to Video Out 模块,与时序信号同步后输出至显示端。这一环节标志着系统从基于内存的缓冲机制向实时视频输出的转换,至此,整个图像处理流程闭环完成。
通过观测上述所有 ILA 信号,我们能够深入了解图像处理流水线的内部运行状态,有效排查和定位可能出现的各类问题。
通常这些问题可追溯至软件配置错误或单个 IP 核模块参数设置不当——在早期系统搭建和集成阶段尤为常见。
当然,判断系统是否正常工作的最直观方式仍然是——屏幕上成功显示出图像。但当遇到异常情况时,ILA 提供的深层信号可见性将成为故障诊断的关键工具。
总结
在本项目中,我们探讨了如何在 Versal AI Edge 器件上构建基础的图像处理流水线并验证其功能。
无论是图像识别、智能驾驶,还是工业检测,只要有图像数据的地方,就离不开这条看不见的流水线。而我们今天所做的,就是让它“可见”。
通过利用 ChipScope 及 ILA,我们能够观察并验证设计中的关键点,确保每个阶段都按预期运行。这种实时可视化功能使我们能够快速有效地识别在集成或应用阶段系统可能出现的问题及其根本原因,使后续的开发过程变得更加顺畅、可靠。
芯驿电子自 2012 年成立以来,旗下 AUMO 与 ALINX 两大品牌,在智能车载与 FPGA 行业解决方案领域持续深耕。
ALINX 提供完整的用户开发手册和工具链与全备的技术支持,帮助您缩短从原型到量产的周期。欢迎访问 ALINX 官网了解更多详情。
原文:Using ChipScope to Debug AMD Versal Designs - Hackster.io
相关文章:

【ALINX 实战笔记】FPGA 大神 Adam Taylor 使用 ChipScope 调试 AMD Versal 设计
本篇文章来自 FPGA 大神、Ardiuvo & Hackster.IO 知名博主 Adam Taylor。在这里感谢 Adam Taylor 对 ALINX 产品的关注与使用。为了让文章更易阅读,我们在原文的基础上作了一些灵活的调整。原文链接已贴在文章底部,欢迎大家在评论区友好互动。 在上篇…...
出现 Uncaught ReferenceError: process is not defined 错误
在浏览器环境中,process 对象是 Node.js 环境特有的,因此当你在浏览器中运行代码时,会出现 Uncaught ReferenceError: process is not defined 错误。这个错误是因为代码里使用了 process.env.BASE_URL,而浏览器环境下并没有 proc…...

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】附录-A. PostgreSQL常用函数速查表
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL常用函数速查表:从数据清洗到分析的全场景工具集引言一、字符串处理函数1.1 基础操作函数1.2 模式匹配函数(正则表达式)二、数值计算函数2.1 基础运算函数2.2 统计相关函数三、日期与时间函…...

【时空图神经网络 交通】相关模型2:STSGCN | 时空同步图卷积网络 | 空间相关性,时间相关性,空间-时间异质性
注:仅学习使用~ 前情提要: 【时空图神经网络 & 交通】相关模型1:STGCN | 完全卷积结构,高效的图卷积近似,瓶颈策略 | 时间门控卷积层:GLU(Gated Linear Unit),一种特殊的非线性门控单元目录 STSGCN-2020年1.1 背景1.2 模型1.2.1 问题背景:现有模型存在的问题1.2…...
零基础学Java——第十一章:实战项目 - 微服务入门
第十一章:实战项目 - 微服务入门 随着互联网应用的复杂性不断增加,单体应用(Monolithic Application)在可扩展性、可维护性、技术栈灵活性等方面逐渐暴露出一些问题。微服务架构(Microservices Architectureÿ…...

docker 学习记录
docker pull nginx docker 将本地nginx快照保存到当前文件夹下 docker save -o nginx.tar nginx:latestdocker 将本地nginx 加载 docker load -i nginx.tar docker运行nginx在80端口 docker run --name dnginx -p 80:80 -d nginxredis启动 docker run --name mr -p 6379:6379 -…...
自媒体工作室如何矩阵?自媒体矩阵养号策略
一、自媒体工作室矩阵搭建方法 1.纵向矩阵:在主流平台都开设账号,覆盖不同用户触达场景。 短视频:抖音、快手、视频号(侧重私域沉淀) 2.主账号导流:通过关联账号、评论区跳转链接实现流量互通 本地生活…...

南京邮电大学金工实习答案
一、金工实习的定义 金工实习是机械类专业学生一项重要的实践课程,它绝非仅仅只是理论知识在操作层面的简单验证,而是一个全方位培养学生综合实践能力与职业素养的系统工程。从本质上而言,金工实习是学生走出教室,亲身踏入机械加…...
【C++进阶篇】C++容器完全指南:掌握set和map的使用,提升编码效率
C容器的实践与应用:轻松掌握set、map与multimap的区别与用法 一. 序列式容器与关联式容器1.1 序列式容器 (Sequential Containers)1.2 关联式容器 (Associative Containers) 二. set系列使用2.1 set的构造和迭代器2.2 set的增删查2.2.1 插入2.2.2 查找2.2.3 删除 2.…...

世界模型+大模型+自动驾驶 论文小汇总
最近看了一些论文,懒得一个个写博客了,直接汇总起来 文章目录 大模型VLM-ADVLM-E2EOpenDriveVLAFASIONAD:自适应反馈的类人自动驾驶中快速和慢速思维融合系统快系统慢系统快慢结合 世界模型End-to-End Driving with Online Trajectory Evalu…...
物联网设备远程管理:基于代理IP的安全固件更新通道方案
在物联网设备远程管理中,固件更新的安全性直接关系到设备功能稳定性和系统抗攻击能力。结合代理IP技术与安全协议设计,可构建安全、高效的固件更新通道。 一、代理IP在固件更新中的核心作用 网络层隐匿与路由优化 隐藏更新源服务器:通过代理I…...
MyBatis 延迟加载与缓存
一、延迟加载策略:按需加载,优化性能 1. 延迟加载 vs 立即加载:核心区别 立即加载:主查询(如查询用户)执行时,主动关联加载关联数据(如用户的所有账号)。 场景…...

C++函数三剑客:缺省参数·函数重载·引用的高效编程指南
前引:在C编程中,缺省参数、函数重载、引用是提升代码简洁性、复用性和效率的三大核心机制。它们既能减少冗杂的代码,又能增强接口设计的灵活性。本文将通过清晰的理论解析与实战案列,带你深入理解这三者的设计思想、使用场景以及闭…...
ORACLE 11.2.0.4 数据库磁盘空间爆满导致GAP产生
前言 昨天晚上深夜接到客户电话,反应数据库无法正常使用,想进入服务器检查时,登录响应非常慢。等两分钟后进入服务器且通过sqlplus进入数据库也很慢。通过检查服务器磁盘空间发现数据库所在区已经爆满,导致数据库在运行期间新增审…...
面试题总结一
第一天 1. 快速排序 public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 分区操作,获取基准元素的最终位置int pivotIndex partition(arr, low, high);// 递归排序基准元素左边的部分quickSort(arr, …...

SWUST数据结构下半期实验练习题
1068: 图的按录入顺序深度优先搜索 #include"iostream" using namespace std; #include"cstring" int visited[100]; char s[100]; int a[100][100]; int n; void dfs(int k,int n) {if(visited[k]0){visited[k]1;cout<<s[k];for(int i0;i<n;i){i…...
专业版降重指南:如何用Python批量替换同义词?自动化操作不香嘛?
还在手动一个个改词降重?👀 是兄弟就别再CtrlF了,来试试Python自动同义词替换批量降重法,简直是论文改写效率神器! 这篇我们来一波实操干货: 👉 如何用Python写出一个自动替换论文关键词的脚本…...
一:操作系统之操作系统结构
深入浅出:一文读懂操作系统的五种核心结构 操作系统,作为计算机硬件与应用软件之间的桥梁,其内部组织结构是决定其性能、稳定性、可维护性和安全性的关键。就像建造房屋需要选择不同的建筑结构一样,设计操作系统也需要选择或混合…...

机器学习 Day18 Support Vector Machine ——最优美的机器学习算法
1.问题导入: 2.SVM定义和一些最优化理论 2.1SVM中的定义 2.1.1 定义 SVM 定义:SVM(Support Vector Machine,支持向量机)核心是寻找超平面将样本分成两类且间隔最大 。它功能多样,可用于线性或非线性分类…...
IIS入门指南:原理、部署与实战
引言:Web服务的基石 在Windows Server机房中,超过35%的企业级网站运行在IIS(Internet Information Services)之上。作为微软生态的核心Web服务器,IIS不仅支撑着ASP.NET应用的运行,更是Windows Server系统管…...
Linux运维——Shell脚本读取配置文件
Shell脚本读取配置文件 一、键值对格式配置文件(最常用)1.1、配置文件示例1.2、source命令导入1.3、sed解析1.4、解析数组 二、INI格式配置文件1.1、配置文件示例1.2、sed解析1.3、ini配置带数组(显式声明数组)1.4、ini配置带数组…...

答题pk小程序道具卡的获取与应用
道具卡是答题PK小程序中必不可少的一项增加趣味性的辅助应用,那么道具卡是如何获取与应用的呢,接下来我们来揭晓答案: 一、道具卡的获取: 签到获取:在每日签到中签到不仅可获得当日的签到奖励积分,同时连…...

leetcode3265. 统计近似相等数对 I-medium
1 题目:统计近似相等数对 I 官方标定难度:中 给你一个正整数数组 nums 。 如果我们执行以下操作 至多一次 可以让两个整数 x 和 y 相等,那么我们称这个数对是 近似相等 的: 选择 x 或者 y 之一,将这个数字中的两个…...

【架构篇】代码组织结构设计
代码组织结构设计:模块化分层与高效协作实践 摘要 本文以Java项目为例,解析后端代码组织的标准化结构,涵盖模块划分原则、依赖管理策略及实际应用场景。通过模块化设计提升代码可维护性、团队协作效率及系统扩展能力。 一、模块化设计的核心…...
2_Spring【IOC容器中获取组件Bean】
Spring中IOC容器中获取组件Bean 实体类 //接口 public interface TestDemo {public void doSomething(); } // 实现类 public class HappyComponent implements TestDemo {public void doSomething() {System.out.println("HappyComponent is doing something...")…...

日期数据渲染转换问题
今天在学习Springboot框架时,想做一个非常简单的增删改查巩固一下,结果在数据渲染上出现了一个小问题,如图数据库中的数据一切正常 但是在前端渲染时,是下面这个效果 这是因为数据库存储的日期类型数据在前端渲染时,没…...
Spring Boot拦截器详解:原理、实现与应用场景
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、拦截器概述 拦截器(Interceptor)是Spring MVC框架中用于对请求进行预处理和后处理的组件,主要作用于Controller层。相…...

ubuntu18.04编译qt5.14.2源码
ubuntu18.04编译qt5.14.2源码 文章目录 ubuntu18.04编译qt5.14.2源码[toc]1 前言2 参考文档3 下载源码3.1 方法13.2 方法23.3 方法3 4 ubuntu编译qt源码4.1 环境准备4.2 设置交换分区大小4.3 编译源码4.4 添加环境变量4.5 验证编译结果4.6 编译帮助文档(qch…...

创建指定版本的vite项目
1、获取vite的版本号 npm view create-vite versions 注:4.4.1版本即对应着node16版本的项目 2、创建制定版本的vite项目 npm init vite<version>...

iOS 初识RunLoop
iOS 初识RunLoop 文章目录 iOS 初识RunLoopRunLoop的概念RunLoop的功能RunLoop和线程的关系RunLoop的结构ModeObserverTimer 和 source小结 RunLoop的核心RunLoop的流程RunLoop的应用AutoreleasePool响应触控事件刷新界面常驻线程网络请求NSTimer 和 CADisplayLinkNSTimerGCDTi…...