PCIe數據采集系統詳解
????????在上篇文章中,廢了老大勁兒我們寫出了PCIe數據采集系統;其中各個模塊各司其職,相互配合。完成了從數據采集到高速存儲到DDR3的全過程。今天我們呢就來詳細講解他們之間的關系?以及各個模塊的關鍵點?他們到底是怎么協同工作的?
總體模塊圖
各模塊關鍵點
1. 在第一個時鐘管理模塊
有用到:差分時鐘緩沖器,MMCM,全局時鐘緩沖器
差分時鐘緩沖器將PCIe的差分信號轉換為單端信號展示,輸出但不單列;
MMCM產生 pcie_user_clk_bufg 和?ddr3_user_clk_bufg ,同時產生?pll_locked鎖存;
全局時鐘緩沖器將pcie_user_clk_bufg 和?ddr3_user_clk_bufg原語應用于全局網絡并輸出相應信號;
2.在第二個系統控制模塊
其主要目的是實現將異步復位信號同步,輸出三個復位信號(系統,PCIe,DDR3;均使用了兩個同步寄存器打拍同時配合PLL鎖存信號)優勢有以下:
- 消除亞穩態風險,提高系統穩定性。
- 簡化時序分析,降低設計實現難度。
- 精確控制復位釋放時序,確保多時鐘域系統協調工作。
- 增強抗干擾能力,避免復位毛刺引發的問題。
在該模塊體現為:確保 PCIe 模塊在其專用時鐘(pcie_user_clk
)穩定后同步釋放復位,避免 PCIe 鏈路初始化錯誤;控制 DDR3 控制器的復位時序,配合 DDR3 初始化校準流程(init_calib_complete信號),確保內存控制器正確啟動。
并且該模塊輸入一些系統標志如:pcie_perst_n(PCIe物理層復位);init_calib_complete(DDR3初始化完成標志)等,以供相應模塊使用,在本系統控制模塊未處理,但是經由屬于系統的控制部分所以列出。
接收系統狀態和錯誤標志,通過 LED 實時顯示
3.第三個PCIe模塊
出現了user_clk(125M)user_clk(125M)user_clk(125M)use從r_clk(125M
必須與第一個時鐘管理模塊進行區分的是:pcie_user_clk(125M);
pcie_user_clk
?是系統為 PCIe 模塊提供的時鐘源。user_clk
?是 PCIe IP 核向用戶邏輯輸出的同步時鐘,確保數據在用戶邏輯和 PCIe 之間正確傳輸。-
user_clk
的特殊作用:PCIe IP 核內部會根據鏈路狀態(如 Gen1/Gen2/Gen3)動態調整時鐘相位和頻率。user_clk
是 IP 核內部同步后的時鐘,確保與 PCIe 事務時序(非事務層)嚴格對齊。
PCIe 端點模塊的內部結構: PCIe 端點 IP 核通常包含:
- 物理層(PHY):處理電氣信號,使用參考時鐘(如 100MHz 差分時鐘)。
- 鏈路層 / 事務層:處理 TLP(事務層包),使用系統提供的
pcie_user_clk
。 - 用戶接口:提供與用戶邏輯通信的時鐘(即
user_clk
)。
在該模塊中,輸入的是差分信號與復位信號;主要輸出用戶時鐘,MMIO接口與鏈路完成標志。
數據通道采用 128 位寬接口(PCIe Gen2 標準),帶字節使能控制;
// 參數定義:PCIe基地址寄存器(BAR)大小parameter BAR0_SIZE = 16'h1000; // 4KBparameter BAR1_SIZE = 16'h4000; // 16KB// 內部信號wire pcie_clk; // PCIe時鐘wire pcie_rst_n; // PCIe復位 (低有效)wire [63:0] cfg_dw0, cfg_dw1, cfg_dw2, cfg_dw3; // 配置空間數據字
- BAR 寄存器:定義 PCIe 配置空間中內存映射區域的大小
- 配置空間:PCIe 設備通過 64 字節配置空間向主機暴露參數
PCIe 設備通過一個256 字節的配置空間向主機暴露自身參數,類似一個 "設備檔案"。
主機通過讀取這個空間了解設備信息(如廠商、功能、支持的 BAR 數量等),并配置設備行為。
-
前 64 字節(標準頭):所有 PCIe 設備必須實現,包含通用信息
- 設備標識:Vendor ID、Device ID、Class Code 等
- 基地址寄存器 (BAR):定義設備可訪問的內存 / IO 空間,存儲主機分配給設備的基地址
- 中斷配置:IRQ 線、MSI/MSI-X 支持
-
后 192 字節:可選擴展區域,用于高級功能(如 PCIe 能力結構)
為什么需要 BAR?
- 地址解耦:設備無需預先知道主機分配的地址,通過 BAR 動態映射
- 資源管理:主機可根據系統情況靈活分配地址空間
- 多設備共存:多個 PCIe 設備可共享同一地址空間,通過 BAR 區分
- 安全隔離:主機可限制設備訪問的地址范圍,提高系統安全性
同時在MMIO控制器例化部分,實現了將 PCIe 事務轉換為 FPGA 內部存儲器讀寫操作(存儲器映射)
PCIe 初始化流程詳解
PCIe 設備初始化需要完成復雜的狀態轉換,代碼中的狀態機對應以下關鍵階段:
-
復位階段 (INIT_RESET)
- 等待系統復位釋放
- 初始化內部計數器和標志位
-
鏈路訓練階段 (INIT_WAIT_LT)
- 監測
link_up
信號,確認物理層連接建立 - 超時處理防止鏈路訓練失敗導致的死鎖
- 監測
-
數據鏈路層初始化 (INIT_WAIT_DLL)
- 等待數據鏈路層鎖定(
dll_up
信號) - 建立可靠的數據傳輸通道
- 等待數據鏈路層鎖定(
-
進入 L0 工作狀態 (INIT_WAIT_L0)
- 確認 LTSSM 狀態機進入 L0 狀態(正常工作狀態)
- 完成 PCIe 初始化的最后階段
-
初始化完成 (INIT_COMPLETE)
- 設置
pcie_init_done
標志,通知系統 PCIe 鏈路就緒 - 持續監測鏈路狀態,確保連接穩定
- 設置
4.第四個MMIO控制器模塊
輸入了MMIO數據/地址,實現了 PCIe 總線與 FPGA 內部邏輯之間的 MMIO (存儲器映射 I/O) 控制器,負責解析 PCIe 事務層包 (TLP) 并轉換為內部寄存器訪問。
在該模塊編寫中,就是使用了正常的always邏輯進行數據的解析打包與傳輸,沒有任何技巧(簡化了設計),同時定義了兩個內存映射區域的基地址;提供了基礎的 PCIe 到內部寄存器的映射功能,但缺少:
完整的TLP解析邏輯,BAR地址范圍審查,背壓機制(發送通道就緒時才能接收新數據),同時MMIO的錯誤清楚機制并沒有撰寫;后續可根據具體的項目要求改進。
示例代碼如下:
module mmio_controller (input clk, // 用戶時鐘 (125MHz)input reset_n, // 復位信號// PCIe數據通道input [127:0] rx_data, // 接收數據input [15:0] rx_be, // 接收字節使能input rx_valid, // 接收數據有效output rx_ready, // 接收準備好// 省略其他接口...// 新增錯誤處理接口input [7:0] error_flags, // 外部錯誤標志輸入output mmio_clear_error, // 清除錯誤命令output [7:0] active_errors // 當前活躍錯誤
);// 寄存器地址定義localparam ERROR_STATUS_REG = 32'h0000_0004; // 錯誤狀態寄存器localparam ERROR_CLEAR_REG = 32'h0000_0008; // 錯誤清除寄存器// 內部信號reg [31:0] mmio_addr_reg;reg mmio_rd_reg, mmio_wr_reg;reg [127:0] mmio_wdata_reg;reg [7:0] error_status; // 錯誤狀態寄存器reg clear_error_cmd; // 清除錯誤命令暫存// 錯誤狀態更新always @(posedge clk or negedge reset_n) beginif (!reset_n) beginerror_status <= 8'h00;end else begin// 錯誤標志可以被設置,但只能通過寫清除寄存器清除error_status <= error_status | error_flags;// 處理錯誤清除命令if (mmio_wr_reg && (mmio_addr_reg == ERROR_CLEAR_REG)) beginerror_status <= error_status & (~mmio_wdata_reg[7:0]);endendend// 地址解碼增強always @(posedge clk or negedge reset_n) beginif (!reset_n) beginmmio_addr_reg <= 0;mmio_rd_reg <= 0;mmio_wr_reg <= 0;mmio_wdata_reg <= 0;clear_error_cmd <= 0;end else if (rx_valid) begin// 解析PCIe接收數據中的MMIO地址和命令mmio_addr_reg <= rx_data[31:0];mmio_wdata_reg <= rx_data[127:32];mmio_rd_reg <= rx_data[128];mmio_wr_reg <= rx_data[129];// 檢測錯誤清除命令clear_error_cmd <= mmio_wr_reg && (mmio_addr_reg == ERROR_CLEAR_REG);endend// 輸出錯誤清除信號(脈沖有效)assign mmio_clear_error = clear_error_cmd;// 輸出當前活躍錯誤assign active_errors = error_status;// 其他代碼保持不變...
endmodule
5.第五個數據采集模塊
輸入了開始采集命令start_acq(ctrl);輸出標志是采集完成信號;
其功能是雙通道采集數據,然后打包數據塊進行輸出,以適應于高速傳輸模式;
前面單獨出過一篇文章來講解。
6.第六個DMA引擎控制模塊
輸入的是用戶時鐘(125M),數據輸入,DMA啟動信號;主要輸出DDR3的寫數據;其核心功能是實現高速數據傳輸,將采集模塊的緩沖區數據搬移到 DDR3。
本模塊的關鍵點主要是突發模式的配置與高速傳輸狀態接收
前面單獨出過一篇文章來講解。
7. 第七個DDR3控制器模塊
輸入的是時鐘ddr3_user_clk(200M),輸出init_calib_complete信號,代表DDR3初始化校準完成就緒;
其功能是控制 DDR3 存儲器的初始化、校準和數據讀寫。
實際上在代碼編寫時,主要是將Xilinx MIG IP 核在程序中例化,進而將DDR3物理層接口出現;
實現了用戶接口和 MIG IP 核之間的信號轉換
在第八個頂層模塊中,實現了對前面模塊的例化,同時創建了系統狀態機用于協調管理各個模塊,見上篇文章!!!