“之前的文章嵌入式基礎構架 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指示燈
集成平臺
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 頻率需求,在關鍵路徑插入寄存器切片以滿足時序收斂要求。
//Two 16-bit bus segments at 0xc000_0000 (APB1) and c001_0000 (APB2)APB#(.DATA_WIDTH(32), .ADDR_WIDTH(16), .USER_WIDTH(0)) rootAPB[1:0]();//Root bridgeAPBBridge#(.BASE_ADDR(32'h0000_0000),//MSBs are not sent over FMC.BLOCK_SIZE(32'h1_0000),.NUM_PORTS(2)) root_bridge (.upstream(fmc_apb_pipe),.downstream(rootAPB));//Pipeline stages at top side of each root in case we need to improve timingAPB#(.DATA_WIDTH(32), .ADDR_WIDTH(16), .USER_WIDTH(0)) apb1_root();APBRegisterSlice#(.DOWN_REG(0), .UP_REG(0)) regslice_apb1_root(.upstream(rootAPB[0]),.downstream(apb1_root));APB#(.DATA_WIDTH(32), .ADDR_WIDTH(16), .USER_WIDTH(0)) apb2_root();APBRegisterSlice#(.DOWN_REG(0), .UP_REG(0)) regslice_apb2_root(.upstream(rootAPB[1]),.downstream(apb2_root));性能 為實測接口傳輸速率,我編寫了極簡版 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已完全足夠。
結論
整體實現出乎意料地順利,接口即插即用且運行穩定。受限于總線系統同步特性,超 125MHz 的高頻運行可能面臨挑戰。雖探索過動態 PLL 重配置與類鏈路訓練方案,但實際必要性存疑。
未來代碼演進方向可能包括: FMC端支持64位傳輸及采用AHB替代APB協議以降低順序傳輸開銷。但可以預見,該架構將成為我大型FPGA+MCU項目的長期技術基座。
本文轉載自:https://serd.es/2024/07/24/Memory-mapping-an-FPGA-from-a-STM32.html,經校對及翻譯。
-
FPGA
+關注
關注
1643文章
21950瀏覽量
613753 -
mcu
+關注
關注
146文章
17821瀏覽量
359940 -
嵌入式
+關注
關注
5136文章
19519瀏覽量
314540 -
STM32
+關注
關注
2289文章
11006瀏覽量
362139 -
內存映射
+關注
關注
0文章
15瀏覽量
7512
發布評論請先 登錄
RTOS和Linux中的內存映射及移植方法
如何實現FPGA進行內存映射的GPMC接口進行通信?
如何在MCU上進行內存管理與分配
為什么要進行內存對齊操作呢
基于SPB的FPGA嵌入式音頻處理系統的設計

評論