FPGA是否具有高速通信接口和高速內(nèi)存接口已經(jīng)是高端FPGA和低端FPGA的分水嶺了。低端FPGA一般只提供低速通用IO,速度最高的就是LVDS了。但是LVDS只提供了PHY層的邏輯,即串轉(zhuǎn)并,還需要自己實現(xiàn)數(shù)據(jù)鏈路層和應(yīng)用層的邏輯。
高速FPGA的高速接口非常的豐富,一般包括用于高速通信的Serdes,PCIe硬核;用于高速存儲接口的DDR3、DDR4接口。另一方面,同樣的接口,不同廠家實現(xiàn)的方案也不同,比如Xilinx提供的DDR接口是用FPGA邏輯實現(xiàn)的軟核,而PCIe是直接硬核的資源;而PGL22G這款FPGA的DDR接口是使用硬核的HMEMC。
DDR內(nèi)存控制器是非常復雜的一個IP,在實現(xiàn)的過程中會使用了非常多的資源,直接使用FPGA資源實現(xiàn)DDR控制器的缺點就是占用資源,但是優(yōu)點是實現(xiàn)靈活,根據(jù)引腳分配規(guī)則可以分布在各個BANK上,這對于引腳分配和PCB布局布線是非常方便的,尤其在使用多個顆?;駾IMM實現(xiàn)32位或者64位總線內(nèi)存的時候。而使用硬核的DDR控制器剛好相反,占用邏輯資源少,但是只能在固定位置。比如PGL22G包含兩個硬核HMEMC,分別在BANK L1/L2和BANK R1/R2,可以看到HMEMC的位置靠近器件封裝的兩側(cè),可以直接和引腳相鄰,這樣的布局應(yīng)該是方便布線和時序。
圖1.HMEMC在PGL22G中的位置
根據(jù)PANGO官方的數(shù)據(jù)手冊,HMEMC是可以bypass,從而使用軟核實現(xiàn),個人感覺有這個需求的應(yīng)該是很少的吧?
圖2.HMEMCdatasheet描述
這里可以看出DDR控制器的組成有兩個主要部分:DDRC和DDRPHY,如圖3圖4所示。這個看綜合后RTL視圖也可以看到,例化了DDR控制器之后,會在ipcore目錄下生成相應(yīng)的RTL代碼。主要是對DDR控制器硬核資源進行配置和例化,而一些復位控制,鏈路訓練等是通過邏輯資源實現(xiàn)的。有興趣的可以直接看源代碼,只不過可讀性差了點。
圖3.HMEMC硬核DDRC
圖4.HMEMC硬核DDRPHY
再來看HMEMC的使用方法,可以通過IP_Compiler例化DDR控制器,最多支持3組AXI,1個128bit,2個64bit。在配置IP的時候可以選擇使用哪組,或者全部都用。支持多組AXI總線是有必要的,因為項目中經(jīng)常有多個模塊需要訪問DDR,支持多個端口可以減少使用外部的Crossbar做多端口的仲裁和互聯(lián)。DDR控制器輸入的時鐘不需要硬件上額外提供,直接使用系統(tǒng)時鐘即可,在內(nèi)部使用PLL倍頻到DDR速率。這里我有一點困惑,因為系統(tǒng)時鐘是50Mhz,但是DDR控制器最高速率支持1066Mhz,也就是PLL的輸出頻率是533Mhz,并不是整數(shù)倍分頻的。這里PGL22G的PLL真的可以做到這一點,還是工具有問題?(Xilinx的FPGA中只有MMCM才能實現(xiàn)分數(shù)倍頻率綜合)
DDR3帶寬測試
帶寬測試的基本方法是:向DDR里寫入數(shù)據(jù)(可以是遞增的數(shù)或偽隨機數(shù)),然后讀出進行比對,如果出錯則立即停止,否則對整個地址空間進行讀寫,然后記錄所用的時間,即可計算出帶寬。
首選對DDR控制器進行配置和例化,選擇一組128bit的AXI總線,DDR速率配置為800Mhz。頂層主要包括兩個模塊,ipsl_hmemc_top和ddr_wr_ctrl,ddr_wr_ctrl使用DDRIP輸出的100Mhz時鐘ui_clk作為時鐘。通過狀態(tài)機,首先對整個DDR空間進行寫入測試,然后再讀出整個空間進行比對,寫入的數(shù)據(jù)為遞增的數(shù)據(jù)。對整個寫入和讀出過程進行計時,計時精度1us。
圖5.DDR讀寫測試工程RTL視圖
計時值的讀出是通過debug_core讀出的,這樣可以不使用其他通信接口而簡化設(shè)計。這里需要注意如果計時值在頂層沒有輸出連接的話,會被綜合器優(yōu)化掉,在添加調(diào)試信號的時候會搜索不到這個網(wǎng)絡(luò)。這里有兩種方法可以避免未連接的端口被優(yōu)化掉:一種是使用Synplify的綜合Directive如“Syn_keep”、“ syn_preserve”告訴綜合器不要優(yōu)化;另外一種是直接將計數(shù)值通過組合邏輯連接到IO上。這里使用第二種方法,通過組合邏輯連接到LED上。計數(shù)值直接通過debug_core讀出,測試的開始觸發(fā)是通過檢測按鍵的邊沿。
// LED active low
assign led = {clk_led, pll_lock&ddrphy_rst_done&ddr_init_done,(|test_time), err_flag};
DDR工作在800Mhz,物理位寬16bit,理論物理帶寬為800Mhz*16bit = 12.8Gbps;
AXI總線頻率100Mhz,總線位寬128bit,理論帶寬為100Mhz*128bit = 12.8Gbps;
二者帶寬是匹配的,即通過AXI總線可以測出DDR的最大帶寬。
ddr_band_width = 128MB / test_time
在操作DDR控制器AXI接口的時候有幾個地方一定要注意,特別是對AXI4協(xié)議不太熟悉的朋友。axi_awsize指的是AXI的總線的有效位寬,這里需要和總線的實際進行區(qū)別,比如128bit的總線是可以傳輸64bit/32bit/16bit/8bit的數(shù)據(jù),稱為Narrow Burst。所以axi_awsize才決定了實際傳輸有效數(shù)據(jù)的位寬,這里設(shè)為4,即2^4=16Byte。axi_awburst指定了地址的增長模式,這里設(shè)為2’b01,即地址遞增。
assign axi_awid = 4'h0 ;
assign axi_awlen = 8'hFF ;
assign axi_awsize = 3'b100; // 128b = 16B = 2^4
assign axi_awburst = 2'b01 ; // incremental burst
通過布局布線的結(jié)果,我們可以很直觀的看到,使用硬核資源,只占用了非常少的邏輯資源。
圖6.HMEMC布局布線結(jié)果