“之前的文章嵌入式基础构架 from andrew@labs介绍了大型嵌入式项目的构架,本文将深入介绍 MCU 到 FPGA 的内存映射方案。”
首先回顾,我为未来多数大型嵌入式项目规划的架构是:使用较大规模(AMD Xilinx Kintex-7 或 Artix/Kintex UltraScale+)FPGA 处理高速数据层,搭配 STM32H735 作为控制层,两者通过内存映射接口连接。
为何选择双芯片方案?
这让人联想到 Xilinx Zynq/Versal 等 SoC FPGA 平台,但存在几个关键差异使其更符合我的需求和偏好:
• 在裸机无操作系统或精简 RTOS 环境下,使用 MCU 级的 Cortex-M 内核比应用处理器更易编程
• 大容量片上 SRAM(564kB)和Flash(1MB)免除了耗时的 DDR SDRAM 布局需求(典型固件 RAM/Flash 使用量均<200kB)
• 分离式引脚布局(两个小型 BGA 而非单个大型 BGA)在较少 PCB 层数下更易扇出,布局时可灵活安排 FPGA 与 MCU 间距
• 分布式架构强化安全边界:FPGA 可拒绝未经验证的 MCU 比特流,FPGA 也无法访问 MCU 内存及外设
• 可灵活搭配不同 MCU 与 FPGA 组合,优化功能、IO、BOM 成本等参数
• STM32 内置硬件 AES 和随机数发生器 IP 核,而 Zynq(令人惊讶地)缺失这些功能
内存接口
经过几次四线 SPI 方案的失败尝试,我最终确定使用灵活存储控制器(FMC)作为 STM32 的 AXI 总线与 FPGA 内部互连之间的主控端桥接方案。该模块高度可配置,可支持传统(如PC133)SDRAM、异步/同步SRAM/PSRAM、并行NOR/NAND闪存等接口。
最关键的是,与 STM32H735 的 OCTOSPI 外设不同,FMC 模块自身不包含硬件缓存或预取机制:仅依赖 Cortex-M7 提供的常规 L1 指令/数据缓存。甚至无需调整这些缓存,因为 FMC 的首个存储区默认映射在地址 0xc000_0000,且 MPU(内存保护单元)已将其预配置为强序、无缓存、设备内存类型,完全无需手动修改MPU寄存器来禁用该地址范围的缓存。
对于 FPGA 桥接而言,最适用的 FMC 操作模式是同步 PSRAM 模式。该模式提供连续时钟(在内存访问突发间隙仍保持运行,FPGA 可据此驱动内部逻辑、锁相环等),并支持硬件等待信号,允许FPGA在流水线延迟或低速外设导致响应时间超过FMC寄存器预设等待周期时主动暂停总线。
连接26个 LVCMOS33 电平引脚(包括时钟、16位复用地址/数据总线、控制信号、字节写使能、1个片选和3个高位地址线)约占用7系列HR或 UltraScale+ HD I/O Bank 的半数资源。此配置为 FPGA 提供1 MB地址空间(2^(16+3) = 512K个16位字寻址能力),若需更复杂设计扩展地址空间,还可额外引出更多地址线。
硬件设计
由于手头没有现成整合 MCU、FPGA 及互连走线的开发板,我快速在 KiCAD 中设计了一款测试板。该板采用六层生益 S1000-2M 基材(成本优化的 FR-4 材料),因无高速信号需求且追求低成本。
此板设计用于搭配第二代 48V 至 12V 中间总线转换器(IBC),并承担其启动验证功能,因此集成了 PicoBlade 控制接口和 Mini-Fit Jr 12V 输入连接器。尽管已收到新版 IBC 板,但因时间不足尚未贴片,目前暂时使用库存的第一代改进版IBC原型供电。
板载器件包括:
• QFN-48 封装的 STM32L431 作为电源管理与时序控制器(便于在复杂设计前验证功能并开发固件)
• 201-BGA 封装的 STM32H735 作为主处理器
• FTGB196 封装的 Xilinx XC7S25 Spartan-7 FPGA 作为桥接端。虽可用更低规格FPGA(如库存的XC7S6或15),但为将其打造为通用 FPGA+MCU 开发平台,并满足启动阶段逻辑分析仪核所需的逻辑资源与 RAM,最终选择XC7S25。
FPGA与MCU通过多接口互连:
前述FMC接口
OCTOSPI通道
10/100 RMII接口
当前固件未启用 OCTOSPI 与 RMII,原因包括前文讨论的缓存问题及FMC远超RMII的传输速率(后续详述)。
MCU 的第二 OCTOSPI 通道连接至未使用的四线 SPI Flash,计划未来探索其应用。OCTOSPI 本为外置 Flash 设计,先前遇到的异常均源于将其强行适配非目标场景。
FPGA扩展接口:
• RGMII连接KSZ9031RNX千兆以太网PHY
• PMOD接口用于GPIO扩展
• 4个LED状态指示灯
MCU独立扩展:
• 专用PMOD接口
• 4个LED指示灯
• 3.3V UART调试串口通过排针引出
集成平台
STM32H735是一款高度复杂的芯片(数据手册篇幅达3357页),因此本文仅图示讨论相关的功能模块。
从 MCU 视角看,FPGA 映射为一个 64 MB 的 APB SFR 地址空间(本板仅实现 1 MB 物理连接),起始地址为 0xc000_0000。在链接脚本中,我将该区域命名为 FMC_APB1 和 FMC_APB2,以避免与 MCU 片上 APB1/APB2 总线(位于 0x4000_0000 外设地址段)产生混淆。
当前未支持64位访问,因 FPGA 端总线为32位且尚未实现将64位突发传输拆分为两次32位事务的逻辑。32位读/写访问已完全支持(含等待状态传播);16位与8位访问基本实现,但由于多数外设原生支持32位寄存器,目前对此类窄位宽访问的全面测试优先级较低。
FPGA设计(基于SystemVerilog实现)包含以下模块:
• 三速 10/100/1000 RGMII MAC,搭配内存映射式 RX FIFO 与 TX FIFO
• MDIO 控制器
• 32位 GPIO 端口,连接至 PHY 复位引脚、杂项控制/状态信号、FPGA内部信号及PMOD引脚
• 若干辅助模块,用于查询FPGA器件ID、温度监控及其他系统健康传感器
FPGA端AMBA互连实现 我长期回避在FPGA设计中使用 AMBA 互连,主要因 Xilinx 强制将 AXI(庞大且笨重)作为通用方案,且每个控制信号均需独立端口(何必如此?)。不过自 Vivado 对 SystemVerilog 接口提供良好支持后(约2017年时虽支持接口但无法处理接口数组),这一情况有所改观。
最终决定采用32位APB协议作为内部控制平面互连标准而非全盘AXI化。其优势包括: 轻量化设计,显著节省资源; 寄存器配置场景下速率完全够用;必要时该协议亦可承载可观数据吞吐。
设计顶层架构主要由IO声明与APB互连网络构成。
FMC 桥接器
FMC桥接器是 STM32 FMC 总线与 AMBA APB 协议的双向转换模块(完整实现细节可查阅源码)。
该桥接器包含内部PLL(当前仅支持7系列 FPGA,UltraScale+ 支持即将加入),通过锁定自由运行的FMC时钟生成两个同频输出时钟。输出时钟相位可根据具体 FPGA 的 IO 时序要求、板级走线延迟等因素调整,以优化建立/保持时间裕量。
• 捕获时钟:用于采样输入FMC控制/写数据信号,并向FPGA内部负载输出APB PCLK时钟
• 发射时钟:用于向MCU回传读数据
在较高时钟频率下,可能需要将发射时钟相位相对于捕获时钟后移,以提升系统同步总线的时序裕量(此处向ST工程师喊话:下一代 FMC 能否加入 DQS 等源同步读时钟机制?)
该桥接器将 FMC 事务直接转换为 APB 读写操作,并根据 FMC 字节写使能信号设置 APB PSTRB 信号。APB 延迟通过 NWAIT 信号反馈至 FMC 总线,因此外设可任意延长响应时间(但会导致STM32的AXI总线阻塞,需注意风险)。
当前 PSLVERR 信号尚未启用,未来计划将其映射为锁存中断信号,触发 MCU 端 "segfault" ISR 进行错误处理。
APB#(.DATA_WIDTH(32), .ADDR_WIDTH(20), .USER_WIDTH(0)) fmc_apb();FMC_APBBridge#( .CLOCK_PERIOD(7.27), //137.5 MHz .VCO_MULT(8), //1.1 GHz VCO .CAPTURE_CLOCK_PHASE(-30), .LAUNCH_CLOCK_PHASE(-30)) fmcbridge( .apb(fmc_apb), .clk_mgmt(clk_125mhz), .fmc_clk(fmc_clk), .fmc_nwait(fmc_nwait), .fmc_noe(fmc_noe), .fmc_ad(fmc_ad), .fmc_nwe(fmc_nwe), .fmc_nbl(fmc_nbl), .fmc_nl_nadv(fmc_nl_nadv), .fmc_a_hi(fmc_a_hi), .fmc_cs_n(fmc_ne1));
APB桥接器设计
我的APB桥接模块通过单个APB请求者端口,将其桥接至任意数量的完成者节点,每个节点映射至连续且等长的地址空间区域(通过SystemVerilog接口数组配置)。该架构摒弃了繁琐的GUI地址空间编辑器与自动代码生成,仅通过参数化模块实现。
在复杂系统中,外设通常混合存在两类需求:
• 精简型:仅需少量控制位的小型寄存器映射
• 复杂型:包含内存映射缓冲区的较大规模设计
本架构采用桥接树结构应对此需求。测试系统的根桥接器划分两个64 kB总线段:
通用外设段:二次划分为1 kB子段
以太网FIFO段:二次划分为4 kB子段
桥接器采用纯组合逻辑设计,以最大化时序-延迟权衡的灵活性。实际应用中,开发者可根据目标 PCLK 频率需求,在关键路径插入寄存器切片以满足时序收敛要求。
性能 为实测接口传输速率,我编写了极简版 iperf3 兼容服务端程序作为基准测试。尽管实际应用中不会对基于 FPGA 的 STM32 系统进行极限吞吐压测(未实现速率限制),但此测试可有效评估互连带宽性能。
测试选择反向 UDP 模式(STM32发送端,PC接收端)以最小化 CPU 占用,聚焦总线压力测试。需注意:此结果仅作为互连带宽对比基准,不代表实际应用代码(需处理复杂任务)可达到的性能水平。
当前 APBEthernetInterface 驱动未启用 DMA,仅通过忙循环实现数据内存拷贝(微调对齐优化)。由于所有内存访问均由 CPU 执行,为最大化性能,将数据包缓冲区及 TCP/IP 协议栈内部数据结构均置于 DTCM(紧耦合内存)中。
在 FMC 时钟 125MHz、PLL输出时钟相位均设为 -30度(考虑 BUFG 插入延迟)的配置下,当前测试固件可实现10秒持续 284 Mbps 的吞吐量。
当前方案仍有提速空间。FMC 理论上可运行于当前速率两倍(250MHz),但实际测试中稳定性欠佳。在下一代"正式"设计中,计划采用更高性能 FPGA(但需注意 UltraScale+ HDIO 相较7系列 HR 可能略慢),并通过时序约束优化与PLL相位调试探索极限速率。不过就当前需求而言,284 Mbps已完全足够。
精彩评论