下面给出"纯 FPGA 芯片"方向的 100 道中文面试题,问题顺序与原来 STM32 100 题一一对应,方便快速检索。题目涵盖 FPGA 基础、Verilog/VHDL、时钟、IO、资源、时序、高速收发、调试、实战项目等,既照顾初学者,也保留深入追问空间。
-
FPGA 是什么?它基于什么硬件架构?
-
Xilinx 7 系列、UltraScale+、Intel Agilex 的内核架构差异有哪些?
-
什么是 Xilinx 原语(primitive)?它的作用是什么?
-
描述 FPGA 从上电到用户逻辑开始运行的完整过程(POR→配置→DONE)。
-
什么是 JTAG ISP 与 Slave-Serial ISP?它们有何不同?
-
FPGA 供电引脚(VCCINT、VCCAUX、VCCO、VTT、VREF)分别有什么作用?
-
什么是时钟树?为什么它在 FPGA 中很重要?
-
列举 FPGA 常见时钟源(外部晶振、MMCM、PLL、BUFG、GT 时钟)。
-
如何配置 MMCM 得到最高 600 MHz 时钟?给出计算步骤。
-
什么是 IOB?FPGA 的 IO 有几种工作模式?
-
推挽输出与开漏输出在 FPGA 里如何描述(OBUF vs OBUFT)?
-
如何把 FPGA 引脚配置为内部上拉输入?约束语法怎么写?
-
什么是引脚复用?如何把 IOB 设为 LVDS_25 差分对?
-
什么是 GIC 在 FPGA-SoC 里的角色?纯 FPGA 怎么办?
-
FPGA 内部中断优先级如何管理?(软核 MicroBlaze 向量表)
-
什么是外部中断引脚?如何同步到时钟域?
-
Systick 在 FPGA 软核里怎么实现?(AXI-Timer)
-
看门狗在 FPGA 里怎么实现?独立与窗口区别?
-
如何把 FPGA 从 Power-Gated 状态唤醒?
-
什么是位带?FPGA 没有位带怎么办?
-
UART 通信的基本原理?FPGA 如何实现 115200?
-
如何用 Verilog 写 115200 波特率发生器?给出公式。
-
FPGA 如何用中断方式接收不定长 UART 数据?
-
什么是 AXI-DMA?它有什么好处?
-
如何配置 AXI-DMA 做 UART 环回?
-
SPI 有几种模式?由什么信号决定?
-
如何用 Verilog 写 SPI Master 全双工?
-
I²C 起始/停止条件如何在 FPGA 时序里描述?
-
如何用 Verilog 软模拟 I²C?
-
I²C 从机地址如何组成?
-
FPGA 实现 I²C 要注意什么?(开漏、三态、建立/保持)
-
对比 UART、SPI、I²C 在 FPGA 的资源占用。
-
通用定时器在 FPGA 里如何写?(AXI-Timer)
-
如何用计数器产生 1 kHz PWM?
-
PWM 频率与占空比由哪些寄存器决定?
-
如何用 FPGA 捕获外部脉冲宽度?
-
什么是正交编码器接口?如何用 FPGA 实现?
-
高级定时器 vs 通用定时器------FPGA 里怎么定义"高级"?
-
如何用定时器触发 ADC IP 核?
-
ADC 分辨率是什么意思?FPGA 外接 AD9226 是多少位?
-
什么是"并行 ADC"与"串行 ADC"通道?
-
如何实现多通道 ADC 扫描?
-
ADC 采样时钟抖动如何影响 SNR?
-
如何校准 FPGA 外接 ADC 的增益/偏移?
-
高速 DAC(AD9708)在 FPGA 下的用途?
-
FPGA 内部如何实现高速比较器?(LUT+寄存器)
-
什么是 RTC 在 FPGA 外接场景?如何闹钟中断?
-
如何把数据备份到 FPGA 外接 FRAM?
-
什么是 FPGA DNA?如何读取?
-
FPGA 配置 Flash(SPI/QSPI)如何组织扇区?
-
如何在 Zynq 裸机下读写 QSPI Flash?
-
什么是"选项字节"在 FPGA 的对应?(写保护位)
-
如何在 FPGA 写一个 golden-image 双启动?
-
如何把 FPGA 逻辑搬到外部 DDR 运行?(partial reconfiguration)
-
什么是 MMU?软核 MicroBlaze 带 MMU 吗?
-
如何用 MPU 保护 MicroBlaze 内存段?
-
什么是 DSP48E2?哪些 FPGA 系列支持?
-
如何用 DSP48 写 256 点 FFT?
-
什么是硬 FPU?哪些 FPGA SoC 带硬核 A53+FPU?
-
使用 FPU 需要注意什么?(上下文保存)
-
FPGA 外接以太网 MAC 与 PHY 区别?
-
如何配置 LWIP 在 FPGA 软核跑 TCP?
-
USB 有哪几种传输类型?FPGA 如何实现?
-
如何把 FPGA 做成 USB HID?
-
如何把 FPGA 做成 USB CDC?
-
CAN 控制器在 FPGA 软核对帧如何区分?
-
如何配置 CAN 过滤器?
-
如何计算 CAN 波特率?
-
SDIO 与 SPI 模式读写 SD 卡速度差异?
-
如何通过 FMC 驱动 TFT 液晶屏?
-
什么是 FPGA 内部 TFT-LCDC IP?
-
D-PHY/CSI-2 RX 子系统用于什么?
-
如何用 FPGA 驱动 WS2812B?(串行级联时序)
-
如何用 FPGA 读旋转编码器?(去抖+四倍频)
-
如何用 FPGA 驱动步进电机?(PWM+方向)
-
如何在 FPGA 实现 PID 控制器?(Verilog 定点)
-
如何在 FPGA 软核跑 FreeRTOS?
-
FreeRTOS 任务状态有哪几种?
-
什么是信号量、互斥量、消息队列?
-
如何避免优先级反转?
-
什么是内存碎片?如何应对?
-
如何用 Vivado Block Design 自动生成连线?
-
Xilinx IP 的"裸机驱动"与"Linux 驱动"区别?
-
轮询、中断、DMA 三种 IP 模式对比?
-
如何处理 AXI-DMA 超时错误?
-
如何自定义 IP 的中断回调?
-
如何通过 JTAG 调试 FPGA?
-
ILA 断点有哪几种?
-
如何重定向 printf 到 UART?
-
如何使用 ILA 进行更高效调试?
-
如何测量 Verilog 代码执行时间?(ILA 时间戳)
-
如何配置 FPGA 进入低功耗?(时钟门控+Power-Gating)
-
低功耗下哪些资源可保持?
-
如何分析和优化 FPGA 功耗?(Vivado Power Report)
-
PCB 上 FPGA 复位和晶振电路注意什么?
-
什么是去耦电容?为什么靠近引脚?
-
高速差分对如何与数字部分隔离?
-
FPGA 配置失败常见原因?(DONE 不上拉、bitstream 损坏)
-
如何用看门狗提升 FPGA 系统可靠性?
-
如何在量产中实现 FPGA 远程在线升级?(Golden/Multiboot、ICAP、RSU)
------完------
以下是对您提出的100个Zynq嵌入式系统相关面试问题的完整、详细、专业级回答,由一位具有20年经验的嵌入式软硬件工程师兼计算机科学家撰写。内容涵盖Zynq架构、启动流程、外设驱动、电源管理、时钟系统、通信接口、安全机制、低功耗设计、PCB布局、调试方法等全栈知识。
1. Zynq 到底是什么?它"基于"什么硬件架构?
Zynq 是 Xilinx(现 AMD)推出的 SoC(System-on-Chip)平台 ,核心思想是将 可编程逻辑(PL, Programmable Logic) 与 硬核处理器系统(PS, Processing System) 集成在同一芯片上。
- 硬件架构基础 :
- Zynq-7000 系列 :基于 ARM Cortex-A9 MPCore 双核处理器(32位 ARMv7-A 架构),搭配 Artix-7 或 Kintex-7 级别的 FPGA 逻辑。
- UltraScale+ MPSoC 系列 (如 Zynq UltraScale+ MPSoC):采用 异构多核架构 ,包括:
- 应用处理器单元(APU):双/四核 Cortex-A53(64位 ARMv8-A)
- 实时处理器单元(RPU):双核 Cortex-R5F(带 FPU,用于实时控制)
- 可选 Mali-400 GPU
- PL 基于 UltraScale+ 架构(支持高速收发器、DSP48E2、Block RAM 等)
Zynq 的本质是 软硬协同 SoC ,通过 AXI 总线互连实现 PS 与 PL 的高速数据交换(最高可达数百 MB/s)。
2. Zynq-7000 与 UltraScale+ MPSoC 的"处理系统(PS)"内核区别有哪些?
| 特性 | Zynq-7000 | UltraScale+ MPSoC |
|---|---|---|
| 主 CPU | 双核 Cortex-A9 (32位) | 四核 Cortex-A53 (64位) + 双核 Cortex-R5F |
| 指令集 | ARMv7-A | ARMv8-A (A53), ARMv7-R (R5) |
| 虚拟化 | 不支持 | A53 支持虚拟化扩展 |
| 安全 | TrustZone (A9) | 更强:Secure Boot、CSU、PMC、加密引擎 |
| 内存管理 | MMU (A9) | A53: MMU, R5: MPU |
| 浮点 | A9 可选 VFPv3 | A53: NEON + VFPv4, R5: 单精度 FPU |
| 功耗管理 | 基础休眠 | 多域电源管理(PMC 控制) |
| 启动方式 | BootROM → FSBL | CSU ROM → PMU Firmware → ATF → U-Boot |
| 安全启动 | SHA-256 + RSA-2048 | SHA-3 + RSA-4096 / ECC |
关键差异 :MPSoC 引入了 Platform Management Unit (PMU) 和 Configuration Security Unit (CSU),支持更复杂的电源/安全策略。
3. 什么是 Xilinx 提供的"硬件抽象层"与"板级支持包"(BSP)?它们作用是什么?
-
硬件抽象层(HAL):
- 是 Xilinx SDK/PetaLinux 提供的一组 C 函数库,封装底层寄存器操作。
- 例如:
XUartPs_Send()、XGpio_SetDataDirection()。 - 目标:屏蔽硬件细节,使应用代码可移植。
-
板级支持包(BSP):
- 包含 HAL + 链接脚本 (.ld)、启动代码 (crt0.S)、配置头文件(xparameters.h)。
- 由 Vivado 自动生成,反映当前硬件设计(IP 地址、中断号、时钟频率等)。
- 作用:为裸机或 RTOS 提供 运行环境初始化。
注意:在 Linux 下,BSP 被 Device Tree 替代;在裸机/FreeRTOS 中,BSP 是必需的。
4. 描述 Zynq 从上电到开始执行 main() 的完整启动序列
Zynq-7000 启动流程:
- 上电复位 → BootROM (固化在芯片内部)执行。
- 检测启动模式(QSPI、SD、JTAG、NAND 等)
- 加载 FSBL(First Stage Boot Loader) 到 OCM(On-Chip Memory)
- FSBL 执行 :
- 初始化 DDR、MIO、时钟
- 加载 PL 比特流(可选)
- 加载 SSBL(Second Stage Boot Loader) ,通常是 U-Boot
- U-Boot 执行 :
- 初始化外设、网络、存储
- 加载 Linux 内核 + Device Tree + RootFS
- Linux 启动 →
init→ 用户空间 →main()(若为用户程序)
UltraScale+ MPSoC 启动流程更复杂:
- BootROM → PMU Firmware (运行在 PMU 上)→ ARM Trusted Firmware (ATF) → U-Boot → Linux
关键点:FSBL 是 Xilinx 定义的第一阶段引导程序,必须由用户编写或使用 Xilinx 提供模板。
5. 什么是 FSBL?什么是 CSU ROM?二者差别在哪?
-
FSBL(First Stage Boot Loader):
- 用户编写的 第一阶段引导程序(通常用 C 编写)
- 运行在 OCM(256 KB SRAM)
- 负责:DDR 初始化、PL 配置、加载 U-Boot
- 由 Xilinx SDK 生成模板
-
CSU ROM(Configuration Security Unit ROM):
- 仅存在于 UltraScale+ MPSoC
- 是 安全启动根信任锚,固化在芯片中
- 负责验证 PMU Firmware 的签名(SHA-3 + RSA/ECC)
- 不可修改,比 Zynq-7000 的 BootROM 更安全
区别:FSBL 是软件,CSU ROM 是硬件固件;CSU ROM 在安全启动链中地位更高。
6. Zynq 供电引脚分别给谁供电?
| 电源引脚 | 供电对象 | 典型电压 |
|---|---|---|
| VCCPINT | PS 内核逻辑(CPU、Cache、总线) | 1.0 V |
| VCCPAUX | PS 辅助电路(PLL、I/O bank 控制器) | 1.8 V |
| VCCO_MIO | MIO Bank 0/1/2/3 的 I/O 电压 | 1.8/2.5/3.3 V(可配) |
| VCCO_0 ~ VCCO_3 | 对应 MIO Bank 的输出驱动电压 | 同上 |
| VCCINT | PL 内核逻辑(LUT、FF、BRAM) | 0.95~1.0 V |
| VCCAUX | PL 辅助(配置逻辑、IO buffer) | 1.8 V |
| VCCBRAM | Block RAM 专用 | 1.0 V |
注意:MIO Bank 电压必须一致,不能跨 bank 混用不同电压。
7. 什么是 Zynq"时钟架构"?为什么 PS 与 PL 时钟树分开又耦合?
-
时钟架构:
- PS 有 独立 PLL 系统(ARM PLL、DDR PLL、IO PLL)
- PL 有 MMCM/PLL 原语(用户可配置)
- 两者通过 FCLK_CLKx 信号连接(PS 输出时钟到 PL)
-
为何分开又耦合?
- 分开:PS 需要稳定、低抖动时钟(尤其 DDR、CPU);PL 时钟需灵活(用户自定义频率/相位)
- 耦合:PS 需向 PL 提供参考时钟(如 100 MHz 给 AXI 接口);PL 也可反馈时钟给 PS(较少见)
设计原则:隔离噪声 + 提供同步接口。
8. Zynq-7000 PS 端主要时钟源
- 外部晶振:通常 33.333 MHz(也可 50 MHz)
- ARM PLL:倍频后供 Cortex-A9(最高 1 GHz)
- DDR PLL:供 DDR 控制器(通常 533 MHz)
- IO PLL:供外设(UART、SPI、USB 等)
- 衍生时钟 :通过 Clock Generator 分频得到各外设时钟
9. 如何把 ARM PLL 配置到最高 1 GHz?需要修改哪些寄存器?
Zynq-7000 最高 CPU 频率 = 1 GHz(需满足工艺/温度条件)
步骤:
-
确保输入时钟为 33.333 MHz
-
计算 PLL 参数:
- Feedback divisor (FBDIV) = 60 → 33.333 × 60 = 2000 MHz (VCO)
- Output divisor = 2 → 2000 / 2 = 1000 MHz
-
写寄存器(地址基于 SLCR 基址 0xF8000000):
c
编辑
// Unlock SLCR Xil_Out32(0xF8000008, 0xDF0D); // Set ARM PLL CFG: FBDIV=60, DIV2=1 Xil_Out32(0xF8000100, (60 << 12) | (1 << 9)); // Bypass reset, enable PLL Xil_Out32(0xF8000100, reg | 0x01); // Wait for lock while (!(Xil_In32(0xF8000100) & 0x02)); // Switch CPU clock to ARM PLL Xil_Out32(0xF8000120, 0x01); // ARM_CLK_CTRL
注意:超频需谨慎,确保散热和供电能力。
10. 什么是 MIO/EMIO?它们能配置成几种工作模式?
- MIO(Multiplexed I/O) :
- PS 固定引出的 54 个引脚(Bank 0~3)
- 可复用为 UART、SPI、I2C、GPIO 等
- EMIO(Extended MIO) :
- 通过 PL 引出的 GPIO(最多 64+64=128 位)
- 本质是 PS 的 GPIO 信号路由到 PL
工作模式(每 pin):
- 外设功能(如 UART1_TX)
- GPIO 输入/输出
- 高阻态(Tri-state)
- 内部上拉/下拉使能
配置寄存器 :
MIO_PIN_x(SLCR 偏移 0x700 + x×4)
11. PS 端 MIO 与 PL 端普通 IO 在电气特性上有哪些区别?
| 特性 | MIO (PS) | PL IO |
|---|---|---|
| 驱动能力 | 固定(4/8/12 mA) | 可编程(2~24 mA) |
| 电压标准 | 仅支持 LVCMOS18/25/33 | 支持 LVDS、SSTL、HSTL 等 |
| 上下拉 | 内部可配 | 需外部电阻或 IO 标准支持 |
| 速度 | ≤ 50 MHz(一般外设) | 可达 GHz(配合 GT transceiver) |
| ESD 保护 | 强(面向板级连接) | 一般 |
结论:MIO 适合连接标准外设;PL IO 适合高速/差分/定制接口。
12. 如何把 MIO pin-10 配置为 UART1_RX 并启用内部上拉?
c
编辑
// MIO10 属于 Bank 1,需先设 VCCO_1 = 1.8V(硬件)
// 寄存器地址:SLCR_MIO_PIN_10 = 0xF8000728
Xil_Out32(0xF8000728,
(1 << 13) | // pull-up enable
(0 << 12) | // disable pull-down
(4 << 7) | // disable tri-state
(0 << 6) | // disable L0 disable
(0 << 5) | // disable speed mode
(0 << 4) | // disable IO type
(0 << 1) | // disable disable rcvr
(1) // MIO10 = UART1_RX (peripheral function 1)
);
查表:Xilinx UG585 表 11-2 显示 MIO10 的 UART1_RX 功能编号为 1。
13. 什么是"引脚复用"?如何把 EMIO GPIO 引到 PL 端引脚?
- 引脚复用:一个物理引脚可配置为多种功能(UART/SPI/GPIO 等),通过寄存器选择。
- EMIO 到 PL 引脚 :
- 在 Vivado Block Design 中,将 PS IP 的 EMIO GPIO 引出为顶层端口
- 在约束文件(.xdc)中绑定该端口到具体 FPGA 引脚
- 在软件中通过
XGpio驱动操作
示例:EMIO[0] → top_level_pin → PACKAGE_PIN AA12
14. 什么是 GIC?它在 Zynq 中断体系里扮演什么角色?
- GIC(Generic Interrupt Controller) :
- ARM 定义的标准中断控制器(Cortex-A9/A53 均集成)
- 在 Zynq 中位于 PS 内部
- 作用 :
- 接收 192 个中断源(外设 + PL→PS 中断)
- 支持 优先级、屏蔽、分发(多核)
- 将中断路由到 CPU 的 IRQ/FIQ
寄存器基址:0xF8F01000(Zynq-7000)
15. Zynq 中断号如何分组?如何给 IRQ #61 设置优先级 0xA0?
-
中断分组(Zynq-7000):
- 0--31:SGI(软件生成)
- 32--63:PPI(私有外设,如 Timer、WDT)
- 64--191:SPI(共享外设,如 UART、GPIO、PL 中断)
-
IRQ #61 属于 PPI(可能是 TTC0)
-
设置优先级:
c
编辑
// GIC Distributor: Priority Register for INTID 61 // Each reg holds 4 priorities (8-bit each) uint32_t reg_addr = 0xF8F01400 + (61 / 4) * 4; uint32_t shift = (61 % 4) * 8; uint32_t val = Xil_In32(reg_addr); val = (val & ~(0xFF << shift)) | (0xA0 << shift); Xil_Out32(reg_addr, val);
注意:优先级数值越小,优先级越高(0x00 最高)。
16. 什么是 PL→PS 中断(IRQ-F2P)?如何级联 16 根?
-
IRQ-F2P :PL 向 PS 发送的 Fabric-to-Processor 中断
- 最多 16 根(IRQ_F2P[15:0])
- 映射到 GIC SPI 中断号 61--76(Zynq-7000)
-
级联方法:
- 在 PL 中用 AXI Interrupt Controller IP
- 将多个 PL 中断源接入该 IP
- 该 IP 输出单根中断到 PS 的 IRQ_F2P[0]
- 在软件中读取 IP 的状态寄存器判断具体源
优势:节省 PS 中断线资源。
17. Generic Timer 与 SCU Timer 区别?各自用途?
| 特性 | Generic Timer | SCU Timer |
|---|---|---|
| 位置 | 每个 A9 核私有 | SCU(Snoop Control Unit)共享 |
| 位宽 | 64-bit | 32-bit |
| 用途 | 高精度计时、调度 | 系统级定时(如 OS tick) |
| 中断 | 私有 PPI | 共享 SPI |
实际使用:Linux 用 Generic Timer 做 sched_clock;裸机常用 SCU Timer 做 delay。
18. Zynq 看门狗(SWDT)与 AWDT 有什么区别?如何防止"二次喂狗"攻击?
-
SWDT(System Watchdog Timer):
- 由 PS 控制,可被软件禁用
-
AWDT(Always-on Watchdog Timer):
- 位于 RTC 域,即使深睡也运行
- 无法被软件完全关闭(除非断电)
-
防"二次喂狗"攻击:
- 使用 窗口看门狗模式:只能在特定时间窗口内喂狗
- 结合 安全启动 + 加密校验,防止恶意代码篡改喂狗逻辑
- 在 SIL2/3 系统中,双看门狗(SWDT + AWDT) 互相监控
19. 如何把 Zynq 从"深睡"(Deep-Sleep) 唤醒?唤醒源有哪些?
- 深睡模式:关闭 PS 主电源(VCCPINT),仅保留 RTC、AWDT、部分 GPIO
- 唤醒源 :
- RTC Alarm
- AWDT 超时
- MIO GPIO(配置为唤醒引脚)
- USB 唤醒(若支持)
- 唤醒流程 :
- BootROM 重新执行 → 加载 FSBL → 恢复上下文(需软件保存)
注意:PL 配置丢失,需重新下载比特流。
20. 什么是 Zynq 的"寄存器位带"(bit-banding)?为什么 PL 端没有?
- Bit-banding :
- ARM Cortex-M 特性,允许 原子地操作单个 bit
- 通过映射 1 MB 位带区到 32 MB 别名区
- Zynq(A9/A53)不支持 bit-banding !
- 因为它是 Application Profile,非 Microcontroller Profile
- PL 更无此概念(FPGA 逻辑直接操作信号)
替代方案 :使用 LDREX/STREX 实现原子操作。
21. UART 控制器 16550 兼容模式指什么?波特率误差允许多大?
- 16550 兼容:寄存器布局、FIFO 结构、中断机制与 NS16550 兼容
- 波特率误差 :
- ≤ ±3% 可靠通信
- 超过 5% 可能导致帧错误
22. 如何配置 UART1 波特率 115200,参考时钟 50 MHz?
公式:
CD=16×BaudRateRefClk=16×11520050,000,000≈27.1267
取整 CD = 27,计算实际波特率:
Actual=16×2750e6≈115740.7→误差=+0.47%
寄存器设置:
c
编辑
// UART1 base = 0xE0001000
Xil_Out32(0xE0001000 + 0x00, 0x80); // DLAB=1
Xil_Out32(0xE0001000 + 0x00, 27); // DLL
Xil_Out32(0xE0001000 + 0x04, 0); // DLM
Xil_Out32(0xE0001000 + 0x00, 0x03); // 8N1, DLAB=0
23. PL 端 AXI-UART-lite 如何通过中断接收"不定长"数据包?
- 问题 :AXI UART Lite 无 FIFO 满中断,只有 接收数据就绪中断
- 解决方案 :
- 开启中断
- 中断服务程序读取字符
- 使用 超时机制 判断包结束(如 10ms 无新数据)
- 或约定 包尾标志(如 '\n')
注意:不适合高速流式数据,建议用 AXI UART 16550 或 DMA。
24. Central DMA、DMA-330、AXI-DMA?各适合什么场景?
| 类型 | 描述 | 适用场景 |
|---|---|---|
| Central DMA | PS 内置 DMA,用于 MIO 外设(如 SD、UART) | 低速外设数据搬移 |
| DMA-330 | ARM PL330,高性能,支持 scatter-gather | Linux 内核驱动(如 GEM) |
| AXI-DMA | PL IP,专为 PL↔PS 高速传输设计 | 视频流、雷达数据、高速 ADC/DAC |
性能:AXI-DMA > DMA-330 > Central DMA
25. 如何配置 AXI-DMA 在 MM2S 通道做 UART 自发自收?
不可行 !AXI-DMA 用于 内存 ↔ PL,不能直接连 UART。
正确做法:
- 用 AXI-DMA 将数据从 DDR 发送到 PL 的 FIFO
- PL 逻辑从 FIFO 读取并驱动 UART TX
- UART RX 接回 PL,写入另一 FIFO,再由 AXI-DMA 读回 DDR
本质:需 PL 逻辑桥接。
26. SPI 控制器支持哪几种"时钟相位/极性"?寄存器在哪一位?
-
四种模式:
- Mode 0: CPOL=0, CPHA=0
- Mode 1: CPOL=0, CPHA=1
- Mode 2: CPOL=1, CPHA=0
- Mode 3: CPOL=1, CPHA=1
-
寄存器 :
SPI Configuration Reg (0x00)- Bit 0: CPOL
- Bit 1: CPHA
27. 如何使 SPI0 做 Master、全双工、SCLK=20 MHz?
假设 IO_PLL = 100 MHz:
Divisor=2×20100=2.5→取整 3→实际 SCLK=16.67MHz
寄存器设置:
c
编辑
// Enable master, full-duplex
Xil_Out32(SPI0_BASE + 0x00, 0x186); // Master, no CS, 8-bit
Xil_Out32(SPI0_BASE + 0x04, 0x03); // Baud rate divisor = 3
Xil_Out32(SPI0_BASE + 0x00, 0x186 | 0x02); // Enable
注意:Zynq SPI 最高约 50 MHz(受限于 IO 速度)。
28. I²C 控制器如何产生"重复起始位"?寄存器流程?
- 发送地址 + Write
- 写寄存器地址
- 不发送 STOP
- 发送 Repeated Start (通过设置
CONTROL.REP_START = 1) - 发送地址 + Read
- 读数据,最后发 STOP
关键寄存器:
I2C_CONTROL:Bit 5 = REP_STARTI2C_DATA:写地址/数据I2C_INTERRUPT_STATUS:等待传输完成
29. 如何用 PL 端普通 IO"软模拟"I²C?给出 Verilog 状态机框架。
verilog
编辑
typedef enum {
IDLE, START, ADDR_WR, DATA_WR, REP_START, ADDR_RD, DATA_RD, STOP
} i2c_state_t;
always @(posedge clk) begin
case (state)
IDLE: if (start_cmd) state <= START;
START: begin
sda <= 1; scl <= 1;
#5 sda <= 0; // hold low
state <= ADDR_WR;
end
ADDR_WR: begin
// shift out 7-bit addr + 0
if (bit_count == 8) state <= DATA_WR;
end
// ... similar for others
STOP: begin
sda <= 0; scl <= 1;
#5 sda <= 1;
state <= IDLE;
end
endcase
end
关键:严格遵循 I²C 时序(tHD;STA, tSU;STO 等)。
30. I²C 从机 7 位地址与 10 位地址在 Zynq 寄存器里如何区分?
- 7-bit 地址 :直接写入
I2C_ADDRESS寄存器(bit 6:0) - 10-bit 地址 :
- 首字节 =
1111 0xx0(xx = 高2位) - 次字节 = 低8位
- Zynq 控制器自动处理,无需特殊寄存器设置
- 但需确保从机支持 10-bit
- 首字节 =
注意:Zynq I²C 控制器默认支持 10-bit 寻址。
31. Zynq I²C 外设常遇到的"时钟拉伸"问题如何排查?
- 现象:SCL 被从机拉低,主机卡死
- 排查步骤 :
- 用示波器确认 SCL 是否被拉低
- 检查从机是否忙(如 EEPROM 正在写)
- 在软件中增加 超时检测(轮询 SCL 状态)
- 若使用中断,确保及时响应
- 考虑降低时钟频率(减小从机压力)
设计建议:避免在中断中做 I²C,改用任务级。
32. 对比 UART、SPI、I²C 在 Zynq 中的资源占用与带宽
| 接口 | 带宽 | 引脚数 | CPU 占用 | PL 资源 |
|---|---|---|---|---|
| UART | ≤ 10 Mbps | 2 | 高(无 DMA) | 低 |
| SPI | ≤ 50 Mbps | 3--4 | 中(可用 DMA) | 低 |
| I²C | ≤ 400 kHz (Fast) | 2 | 高(bit-bang 风险) | 低 |
结论:高速用 SPI,简单传感器用 I²C,调试用 UART。
33. PS 端 TTC(Triple-Timer Counter)有哪些工作模式?
- Interval Mode:定时中断
- PWM Mode:输出方波
- Capture Mode:捕获外部事件时间戳
- Event Counter Mode:计数外部脉冲
34. 如何用 TTC 产生 1 kHz PWM?寄存器步骤?
假设 CPU_1x = 133 MHz:
Period=1000133e6=133000 ticks
步骤:
- 设置
CLK_CNTRL= 0x01(CPU_1x) CNT_CNTRL= 0x21(Waveform Mode + Match Enabled)INTERVAL_VAL= 133000 - 1MATCH[0]= 66500(50% 占空比)IER= 0x01(使能中断,可选)
35. PWM 占空比由 TTC 的哪个寄存器决定?
- MATCH[0] 寄存器:决定高电平持续时间
- 占空比 = MATCH[0] / INTERVAL_VAL
36. 如何用 TTC 捕获外部正脉冲宽度?精度如何计算?
- 配置为 Capture Mode
- 上升沿触发 capture1,下降沿触发 capture2
- 脉宽 = capture2 - capture1
- 精度 = 1 / CPU_1x 频率(如 133 MHz → 7.5 ns)
37. PL 端 AXI-Timer 的"产生/捕获"模式?
- Generate Mode:输出 PWM
- Capture Mode:记录输入信号边沿时间
- 通过
TCSR寄存器配置
38. PL 端"高速"AXI-Timer 与 PS 端 TTC 在性能上差多少?
- TTC:最大时钟 = CPU_1x(~133 MHz)→ 精度 ~7.5 ns
- AXI Timer:可接 PL 时钟(如 200 MHz)→ 精度 ~5 ns
- 差异不大,但 AXI Timer 可定制更高频率
39. 如何用 AXI-PWM-IP 触发 PL 端 ADC IP 核?
- 将 AXI-PWM 的输出连接到 ADC 的 采样使能(sample_en) 信号
- PWM 高电平时启动 ADC 转换
- 可实现 同步采样
40. XADC 与 ADC 的"分辨率"分别是多少位?采样率多高?
- XADC (Zynq 内置):
- 分辨率:12 位
- 采样率:1 MSPS(单通道)
- 外部 ADC (如 via SPI):
- 可达 16--24 位,10+ MSPS
41. 什么是 XADC 的"同步采样"模式?
- 使用 SYNC 引脚 外部触发
- 多个 XADC(或多通道)同时采样
- 用于三相电力测量等场景
42. 如何实现 16 通道 XADC 自动扫描?
- 配置
SEQ Register使能通道 0--15 - 设置
SEQ Mode = Continuous - 读取
FIFO获取结果(自动排序)
43. XADC 采样时间与输入阻抗如何折衷?
- 高输入阻抗 → 采样电容充电慢 → 需更长 Acquisition Time
- XADC 允许配置 Channel Averaging 和 Sampling Rate
- 建议:源阻抗 < 1 kΩ,否则加缓冲运放
44. 如何对 XADC 做"增益误差"校准?
-
使用 Internal Calibration :
c
编辑
XSysMon_SetSequencerMode(&SysMonInst, XSM_SEQ_MODE_SAFE); XSysMon_SelfCalibrate(&SysMonInst); -
或使用 外部精密电压源 进行两点校准(offset + gain)
45. 高速 DAC (AXI-DDS/AXI-DAC) 在 PL 端典型用途?
- 任意波形发生器
- 通信调制(QPSK、OFDM)
- 雷达 chirp 信号生成
46. 什么是 PL 端"高速比较器"原语?给出 LVDS 比较例子。
-
原语 :
IBUFDS+LUT或CFGLUT5 -
LVDS 比较 :
verilog
编辑
IBUFDS #(.DIFF_TERM("TRUE")) ibufds_inst ( .I(vp), .IB(vn), .O(cmp_out) );直接输出数字比较结果。
47. 什么是 RTCA (Real-Time Clock Alarm)?如何产生中断唤醒?
- RTCA 是 RTC 的 闹钟功能
- 设置
RTC_ALARM寄存器为目标时间 - 到时产生中断 → 可配置为唤醒源
48. 如何借助 RTC 的"电池备份域"保存 64 字节数据?
- 访问 Battery-backed SRAM(地址 0xF8005000)
- 即使主电源关闭,只要 VBAT 存在,数据不丢失
- 用于保存设备状态、校准参数等
49. Zynq 的"DNA"与"PS Serial Number"各多少位?怎么用?
- Device DNA :57 位,唯一芯片 ID,通过 JTAG 读取
- PS Serial Number :64 位,存储在 EFUSE 中,软件可读
- 用途:软件授权、设备追踪、安全认证
50. Zynq 启动镜像 BOOT.BIN 由哪些"分区"组成?
- Boot Header(固定格式)
- FSBL.elf
- system.bit(PL 比特流,可选)
- u-boot.elf(或 application.elf)
- Partition Header Table(描述各分区属性)
由 bootgen 工具生成。
51. 如何在 Linux 下读写 QSPI Flash 的 raw 页?
bash
编辑
# 使用 mtd 设备
flash_erase /dev/mtd0 0x0 0x100000
nandwrite /dev/mtd0 firmware.bin
hexdump /dev/mtd0
需在设备树中启用 cfi-flash 或 spi-nor 驱动。
52. 什么是"启动头"(Boot Header)?如何修改启动频率?
- Boot Header:BOOT.BIN 前 0x8C0 字节,含镜像信息
- 修改启动频率 :
- 在 FSBL 中调用
set_pll() - 或在 Vivado 中设置 PS IP 的时钟频率 → 自动生成正确头
- 在 FSBL 中调用
53. 如何写一段"裸机"FSBL 实现 PL 比特流先下载后跳转?
c
编辑
int main() {
init_uart();
init_ddr();
load_bitstream("system.bit"); // via SD/QSPI
Xil_DCacheFlush();
Xil_ICacheInvalidate();
void (*app)() = (void*)APP_ADDR;
app();
}
使用 Xilinx FSBL 模板 + 自定义加载逻辑。
54. 如何把 U-Boot relocate 到 DDR 高端地址运行?
- 修改
CONFIG_SYS_TEXT_BASEininclude/configs/zynq-common.h - 例如:
#define CONFIG_SYS_TEXT_BASE 0x30000000 - U-Boot 会自动 copy 自身到该地址并跳转
55. 什么是 MMU?A53 与 R5 的 MMU/MPU 差异?
- MMU:内存管理单元,支持虚拟地址 → 物理地址映射(Linux 必需)
- A53:完整 MMU(支持 4KB/2MB/1GB 页)
- R5 :只有 MPU(Memory Protection Unit),支持区域保护,无地址转换
56. 如何配置 A53 的 TTBR0/TTBR1 实现 DDR 1 GB 映射?
- 使用 1GB block descriptor(Level 1 页表)
- TTBR0 指向页表基址
- 页表项:
VA[38:30] → PA[38:30] | 0x40001(1GB block, inner shareable)
57. 什么是 NEON?哪些 Zynq 系列支持?
- NEON:ARM SIMD 指令集,加速 DSP/图像处理
- Zynq-7000 :Cortex-A9 不支持
- UltraScale+ MPSoC :Cortex-A53 支持 NEON
58. 如何用 NEON 写 128 点 FFT 蝶形运算?
使用 vld1, vmul, vadd, vsub 等指令处理复数对。
c
编辑
float32x4_t a = vld1q_f32(&x[i]);
float32x4_t b = vld1q_f32(&x[i+4]);
float32x4_t w = vld1q_f32(&twiddle[k]);
float32x4_t wb = vmulq_f32(b, w);
float32x4_t sum = vaddq_f32(a, wb);
float32x4_t diff = vsubq_f32(a, wb);
59. R5 的"单精度 FPU"与 A53 的"双精度 FPU"?
- R5F :支持 single-precision (32-bit) IEEE754
- A53 :支持 double-precision (64-bit) + NEON
60. 使用 FPU 中断现场保存要注意哪些寄存器?
- A53 :需保存
V0-V31,FPSR,FPCR - R5 :
S0-S31,FPSCR - 在中断入口用
vpush/fstmia保存
61. GEM 与 PHY 在 RGMII 接口上如何约束时序?
-
使用 IDELAY 调整 RX/TX 时序
-
约束文件中指定:
tcl
编辑
set_input_delay -clock rgmii_rx_clk -max 2.0 [get_ports rgmii_rxd*] set_output_delay -clock rgmii_tx_clk -max 2.0 [get_ports rgmii_txd*]
62. 如何配置 PetaLinux 下的 LWIP 实现 1000 M TCP 回环?
- 在
project-spec/meta-user/recipes-apps/添加 lwip app - 使用
netif_loopback()或直接tcp_connect()到 127.0.0.1 - 确保设备树启用 GEM
63. USB 2.0 OTG 控制器支持哪四种传输类型?
- Control Transfer
- Bulk Transfer
- Interrupt Transfer
- Isochronous Transfer
64. 如何将 Zynq 配置为 USB HID 鼠标?
- 在 Linux 中加载
g_hidgadget 驱动 - 或裸机使用 Xilinx USB driver + HID descriptor
65. 如何将 Zynq 配置为 USB CDC-ACM 虚拟串口?
bash
编辑
modprobe g_serial
echo "CDC ACM" > /sys/kernel/config/usb_gadget/g1/functions/acm.usb0
66. CAN 控制器如何区分标准帧、扩展帧、远程帧?
- 标准帧:IDE=0
- 扩展帧:IDE=1
- 远程帧:RTR=1
寄存器 CAN_ID 中包含这些位。
67. 如何给 CAN 控制器加"接受过滤掩码"?
配置 AFMR(Acceptance Filter Mask Register)和 AFIR(ID Register)
68. 如何计算 CAN 波特率 1 Mbps,参考时钟 40 MHz?
- Prescaler = 4
- TS1 = 7, TS2 = 2 → TQ = 10
- Bit rate = 40e6 / (4 × 10) = 1 Mbps
69. SDIO 与 SPI 模式读写 eMMC 速度差多少?
- SDIO:4-bit mode → ~104 Mbps
- SPI:≤ 20 Mbps
- 差 5 倍以上
70. 如何通过 FMC/HP 端口驱动 8080 并口 TFT?
- 用 PL 实现 8080 时序 FSM
- 数据总线接 HPx_Dxx,控制信号(RS, WR, RD)接 GPIO
- 通过 AXI GPIO 或自定义 IP 控制
71. DisplayPort 控制器 (DP)?能输出几路?
- UltraScale+ MPSoC 集成 DP TX
- 支持 1 路 DisplayPort 1.2a(4K@60Hz)
72. MIPI CSI-2 RX 子系统用于什么场景?最大速率?
- 用于 摄像头输入
- 最大 4-lane × 1.5 Gbps/lane = 6 Gbps
73. 如何用 PL 端 NRZ 时序驱动 WS2812B?
- WS2812B 要求:
- T0H = 0.35 µs, T0L = 0.8 µs
- T1H = 0.7 µs, T1L = 0.6 µs
- 用 100 MHz 时钟,计数器生成精确脉宽
- 状态机:IDLE → SEND_BIT → NEXT
74. 如何用 PL 端"正交解码"IP 读旋转编码器?
- 使用 Xilinx Quadrature Decoder IP
- 输入 A/B 相,输出 count 和 direction
- 通过 AXI-Lite 读取位置
75. 如何通过 AXI-GPIO 与 DRV8825 驱动步进电机?
-
GPIO[0] = STEP, GPIO[1] = DIR
-
软件循环:
c
编辑
XGpio_DiscreteWrite(&gpio, 1, 0x02); // DIR for (i=0; i<steps; i++) { XGpio_DiscreteWrite(&gpio, 1, 0x03); // STEP high delay_us(10); XGpio_DiscreteWrite(&gpio, 1, 0x02); // STEP low delay_us(10); }
76. 如何在裸机里写"位置式 PID"控制电机?
c
编辑
float pid(float setpoint, float feedback) {
static float err_sum = 0, last_err = 0;
float err = setpoint - feedback;
err_sum += err * dt;
float d_err = (err - last_err) / dt;
last_err = err;
return Kp*err + Ki*err_sum + Kd*d_err;
}
77. 如何在 A53 上跑 FreeRTOS?入口在哪?
- 使用 ARM64 port of FreeRTOS
- 入口:
prvPortStartFirstTask()(汇编) - 需关闭 MMU,使用物理地址
78. FreeRTOS 任务状态有哪几种?
- Ready
- Running
- Blocked
- Suspended
79. 什么是二进制信号量、互斥量、队列集?
- Binary Semaphore:任务同步(如 ISR 通知任务)
- Mutex:资源保护,支持优先级继承
- Queue Set:等待多个队列/信号量中的任意一个
80. 如何避免优先级反转?
- 使用 Mutex with Priority Inheritance
- FreeRTOS 中创建 mutex 时指定
queueQUEUE_TYPE_MUTEX
81. 什么是 DDR 碎片?如何借助 mempool 减缓?
- 碎片:频繁 malloc/free 导致空闲块不连续
- mempool:预分配固定大小块,避免动态分配
82. 如何用 Vivado "IP Integrator" 自动生成 AXI 外设模板?
- Create Block Design → Add IP → AXI GPIO / AXI Timer
- Run Connection Automation
- Generate Output Products → Export to SDK
83. Xilinx BSP 与裸机"standalone" 驱动差异?
- BSP:包含板级配置(xparameters.h)
- standalone:通用驱动库(xuartps.c 等)
- BSP 依赖 standalone
84. 轮询、中断、DMA 三种 Xilinx 驱动模式资源对比?
| 模式 | CPU 占用 | 延迟 | 吞吐 | 适用 |
|---|---|---|---|---|
| 轮询 | 高 | 低 | 低 | 调试 |
| 中断 | 中 | 中 | 中 | 中速 |
| DMA | 低 | 高 | 高 | 高速 |
85. 如何处理 DMA 超时的"timeout hook"?
在 Xilinx DMA 驱动中注册回调:
c
编辑
XAxiDma_SetTimeoutHandler(&dma, timeout_handler, NULL);
86. 如何自定义 xilinx_uartps 的接收回调?
c
编辑
XUartPs_SetHandler(&uart, recv_callback, NULL);
XUartPs_EnableInterrupt(&uart, XUARTPS_IXR_RXFULL);
87. 如何通过 JTAG-SWD 调试 FSBL?
- 使用 Xilinx SDK Debugger
- 在 FSBL 项目中设置断点
- 通过 JTAG 连接(需 DONE 引脚上拉)
88. 断点有哪几种?
- Software Breakpoint:插入 BKPT 指令
- Hardware Breakpoint:利用 DBGBCR 寄存器
- Watchpoint:监控数据地址访问
89. 如何重定向 printf 到 UART-1?
在 _write() 函数中调用 XUartPs_Send()
90. 如何使用 ITM / TPIU 做 4-bit trace?
- 配置 CoreSight 组件
- 使能 ITM Port 0
- 通过 SWO 引脚输出 trace data
91. 如何用 PMU 测 A53 指令周期?
- 使能 PMU counter 0 for
INST_RETIRED - 读
PMCCNTR_EL0
92. 如何配置 Zynq 进入"休眠"与"待机"?
- Suspend :Linux
echo mem > /sys/power/state - Standby :调用
XPm_RequestSuspend()
93. 深睡模式下哪些岛能独立存活?
- RTC domain(含 AWDT、Battery SRAM)
- R5 TCM(若供电保持)
- 部分 MIO GPIO(配置为唤醒)
94. 如何测量并优化 PS+PL 整体功耗?
- 工具:Xilinx Power Estimator, Vivado Power Analysis
- 步骤 :
- 降低时钟频率
- 关闭未用外设
- 使用低功耗模式
- 优化 PL 逻辑(减少 toggle rate)
95. PCB 上 MIO Bank 的 1.8 V/3.3 V 组怎么分区?
- Bank 0/1/2/3 各自独立
- 同一 Bank 内所有 MIO 必须同电压
- 例如:Bank 1 = 1.8V (UART), Bank 2 = 3.3V (SPI)
96. 什么是去耦电容?PS 端为什么要求 0402 100 nF 距引脚 <2 mm?
- 去耦电容:滤除高频噪声
- 0402 100nF:高频响应好
- <2 mm:减少 ESL,保证瞬态电流供应
97. 高速 GTX/GTH 差分对如何与低速数字区隔离?
- 3W rule:差分对间距 ≥ 3× 线宽
- 地平面完整,避免分割
- 包地处理(guard traces)
98. PL 配置失败常见原因有哪些?
- Bitstream 与硬件不匹配
- VCCINT/VCCBRAM 供电不足
- DONE 引脚未上拉
- INIT_B 被拉低
- 时钟不稳定
99. 如何用 SWDT+AWDT 双看门狗提升安全完整性 (SIL)?
- SWDT 由主程序喂狗
- AWDT 由 SWDT 服务程序喂狗
- 若 SWDT 死锁 → AWDT 超时复位
- 符合 IEC 61508 SIL2/3
100. 在生产现场如何基于 TF-A + U-Boot + OTA 实现 Zynq 固件远程升级?
- TF-A 验证下一阶段镜像签名
- U-Boot 从网络/TFTP 下载 new_BOOT.BIN
- 写入 QSPI Flash 备份区
- 更新 boot header 指向新镜像
- 重启生效
- 支持 回滚机制(若启动失败)
安全:全程 SHA3 + RSA 验签。
总结:以上100问覆盖 Zynq 全栈开发核心知识点,适用于高级嵌入式工程师面试或系统设计参考。如需某一点深入展开,可继续提问。