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