国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【正點原子FPGA連載】第三十一章DDR4讀寫測試實驗 摘自【正點原子】DFZU2EG/4EV MPSoC 之FPGA開發(fā)指南V1.0

這篇具有很好參考價值的文章主要介紹了【正點原子FPGA連載】第三十一章DDR4讀寫測試實驗 摘自【正點原子】DFZU2EG/4EV MPSoC 之FPGA開發(fā)指南V1.0。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1)實驗平臺:正點原子MPSoC開發(fā)板
2)平臺購買地址:https://detail.tmall.com/item.htm?id=692450874670
3)全套實驗源碼+手冊+視頻下載地址: http://www.openedv.com/thread-340252-1-1.html

第三十一章DDR4讀寫測試實驗

DDR4 SDRAM(Double-Data-Rate Fourth Generation Synchronous Dynamic Random Access Memory,簡稱為DDR4 SDRAM),是一種高速動態(tài)隨機(jī)存取存儲器,它屬于SDRAM家族的存儲器產(chǎn)品,提供了相較于DDR3 SDRAM更高的運行性能與更低的電壓。
本章包括以下幾個部分:
243131.1MIG簡介
31.2實驗任務(wù)
31.3硬件設(shè)計
31.4程序設(shè)計
31.5下載驗證
31.1MIG簡介
DFZU2EG/4EV MPSoC開發(fā)板板載了五片鎂光的DDR4顆粒,它們的型號是MT40A256M16,這5片DDR4芯片有4片位于PS端,有1片位于PL端,本節(jié)實驗使用的是位于PL端的DDR4芯片。下面我們來簡單了解一下這款板載的DDR4芯片,DDR4內(nèi)部結(jié)構(gòu)圖如下所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.1 DDR4結(jié)構(gòu)圖
從上圖我們可以看到,DFZU2EG/4EV MPSoC開發(fā)板板載的這款DDR4芯片的行地址是15bit位寬,列地址是10bit位寬,而整個存儲區(qū)域分為兩個BANK組,每個BANK組又由4個子BANK組成,所以整片DDR4的容量就是215*210816bit=256M16bit。DDR4相較于DDR3在指令引腳上也發(fā)生了變化,DDR4取消了我們所熟悉的使能WE、行激活RAS和列激活CAS這三個命令引腳,而是將這三個命令引腳和地址線A14、A15以及A16復(fù)用了。除此之外在尋址的時候也不再是直接去尋址BANK,而是先尋址BANK組,然后再找到這個BANK組中的某個子BANK。整個數(shù)據(jù)的吞吐是8倍預(yù)取,因此數(shù)據(jù)在讀寫的時候就是16bit8=128bit的數(shù)據(jù)量進(jìn)行吞吐(注意雖然是8倍預(yù)取,但是每一次IO引腳上的數(shù)據(jù)傳輸依舊是16bit,因為數(shù)據(jù)線就16根,至于為何可以達(dá)到8倍預(yù)取和DDR4內(nèi)部的雙沿采樣,F(xiàn)IFO緩沖,寫數(shù)據(jù)邏輯結(jié)構(gòu)有關(guān))。
關(guān)于DDR4更詳細(xì)的介紹大家可以去參考鎂光的官方數(shù)據(jù)手冊,這里不再贅述。
由于DDR4的時序非常復(fù)雜,如果直接編寫DDR4的控制器代碼,那么工作量是非常大的,且性能難以得到保證。值得一提的是,Vivado軟件自帶了DDR4控制器IP核,用戶可以直接借助IP核來實現(xiàn)對DDR4的讀寫操作,從而大大降低了DDR4的開發(fā)難度。本次實驗將使用Xilinx公司MIG(Memory Interface Generators) IP核來實現(xiàn)DDR4讀寫測試。
MIG IP核是Xilinx公司針對DDR存儲器開發(fā)的IP,里面集成存儲器控制模塊,實現(xiàn)DDR讀寫操作的控制流程,下圖是MIG IP 核結(jié)構(gòu)框圖。MIG IP核對外分出了兩組接口,左側(cè)是用戶接口,就是用戶(FPGA)同MIG 交互的接口,用戶只有充分掌握了這些接口才能操作MIG;右側(cè)為DDR物理芯片接口,負(fù)責(zé)產(chǎn)生具體的操作時序,并直接操作芯片管腳,這一側(cè)用戶只負(fù)責(zé)分配正確的管腳,其他不用關(guān)心。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.2 MIG IP 核結(jié)構(gòu)框圖
使用這個IP 核,用戶將可以進(jìn)行DDR4的讀寫操作,而不必熟悉DDR4具體的讀寫控制時序,當(dāng)然用戶必須掌握用戶接口側(cè)的操作時序,并嚴(yán)格遵照時序來編寫代碼,這樣才能正確實現(xiàn)對DDR4的讀寫操作。在了解具體時序之前,大家有必要先了解相關(guān)的信號定義。下圖給出了MIG IP核用戶接口的信號及其說明。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.3 用戶接口信號定義
MIG IP核用戶側(cè)端口數(shù)量共26個,當(dāng)然用戶并不用去關(guān)心所有的信號,只需要了解本實驗要用到幾組重要信號。下面將對這些信號逐一講解并以表格的形式呈現(xiàn)給大家。為了與官方的文檔保持一致,表中標(biāo)明的信號的方向是以MIG IP核作為參照的,例如表格中的信號方向定義為輸出,那么相對于用戶端(FPGA)來說實際上是輸入。
表 31.1.1 MIG IP 核用戶接口部分信號定義
ddr4 fpga,正點原子,fpga開發(fā)

以上是用戶需要用到的信號,其他信號請大家自行了解。
DDR4的讀或者寫都包含寫命令操作,其中寫操作命令(app_cmd)的值等于0,讀操作app_cmd的值等于1。首先來看寫命令時序,如下圖所示。首先檢查app_rdy,為高則表明此時IP核命令接收處于準(zhǔn)備好狀態(tài),可以接收用戶命令,在當(dāng)前時鐘拉高app_en,同時發(fā)送命令(app_cmd)和地址(app_addr),此時命令和地址被寫入。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.4 寫命令時序
下面來看寫數(shù)據(jù)的時序,如下圖所示。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.5 非背靠背寫時序
如上圖所示,寫數(shù)據(jù)有三種情形均可以正確寫入:
(1)寫數(shù)據(jù)時序和寫命令時序發(fā)生在同一拍;
(2)寫數(shù)據(jù)時序比寫命令時序提前一拍;
(3)寫數(shù)據(jù)時序比寫命令時序至多延遲晚兩拍;
結(jié)合上圖,寫時序總結(jié)如下:首先需要檢查app_wdf_rdy,該信號為高表明此時IP核數(shù)據(jù)接收處于準(zhǔn)備完成狀態(tài),可以接收用戶發(fā)過來的數(shù)據(jù),在當(dāng)前時鐘拉高寫使能(app_wdf_wren),給出寫數(shù)據(jù)(app_wdf_data)。這樣加上發(fā)起的寫命令操作就可以成功向IP核寫數(shù)據(jù)。這里有一個信號app_wdf_mask,它是用來屏蔽寫入數(shù)據(jù)的,該信號為高則屏蔽相應(yīng)的字節(jié),該信號為0默認(rèn)不屏蔽任何字節(jié)。
這里需要指出的是,DDR4的讀或者寫操作都可以分為背靠背和非背靠背兩種情形。背靠背,即讀或者寫每個時鐘都連續(xù)進(jìn)行,中間沒有間隙;非背靠背寫則是非連續(xù)的讀寫。
對于背靠背寫,其實也有三種情形,唯一點不同的是,它沒有最大延遲限制,如下圖所示。

ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.6 背靠背寫時序
接著來看讀數(shù)據(jù),如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.7 讀時序
讀時序比較簡單,發(fā)出讀命令后,用戶只需等待數(shù)據(jù)有效信號(app_rd_data_valid)拉高,為高表明此時數(shù)據(jù)總線上的數(shù)據(jù)是有效的返回數(shù)據(jù)。需要注意的是,在發(fā)出讀命令后,有效讀數(shù)據(jù)要晚若干周期才出現(xiàn)在數(shù)據(jù)總線上。下面是背靠背讀的情況,如下圖所示。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.1.8 背靠背讀時序圖
需要注意的是,在連續(xù)讀的時候,讀到的數(shù)據(jù)順序跟請求的命令/地址是相對應(yīng)的。通常使用DDR4的時候,為了最大限度地提高DDR4效能,充分利用突發(fā)寫的特點,非背靠背很少用,而更多地采用背靠背操作。本章實驗的讀寫操作就是基于背靠背模式操作的。
31.2實驗任務(wù)
本節(jié)的實驗任務(wù)是先向DDR4的存儲器地址0至999分別寫入數(shù)據(jù)0999;寫完之后再讀取存儲器地址0999中的數(shù)據(jù),若讀取的值全部正確則LED燈常亮,否則LED燈閃爍。
31.3硬件設(shè)計
本節(jié)實驗使用的是PL端的DDR4,如果想使用PS端的DDR4,可以參考正點原子的嵌入式Vitis開發(fā)指南教程。PL端DDR4的硬件原理圖如下圖所示。在PCB的設(shè)計上,完全遵照Xilinx的DDR4硬件設(shè)計規(guī)范,嚴(yán)格保證等長設(shè)計和阻抗控制,從而保證高速信號的數(shù)據(jù)傳輸?shù)目煽啃浴?br>ddr4 fpga,正點原子,fpga開發(fā)

圖 31.3.1 DDR4硬件原理圖
接下來我們來看看本節(jié)實驗所用到的管腳,管腳分配可以放在工程的XDC文件中,也可以打開io planning窗口在io ports欄中分配管腳。我們本節(jié)實驗用到的管腳如下表所示(因為管腳太多這里只貼出部分管腳):
表 31.3.1 DDR4讀寫測試實驗部分管腳分配
信號名 方向 管腳 端口說明 電平標(biāo)準(zhǔn)
sys_clk_p input AE5 系統(tǒng)差分輸入時鐘 DIFF_HSTL_I_12
sys_clk_n input AF5 系統(tǒng)差分輸入時鐘 DIFF_HSTL_I_12
sys_rst_n input AH11 系統(tǒng)復(fù)位按鍵,低電平有效 LVCMOS33
led output AE10 讀寫結(jié)果指示燈 LVCMOS33
c0_ddr4_dq[15] inout AC4 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[14] inout AC3 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[13] inout AB4 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[12] inout AB3 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[11] inout AB2 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[10] inout AC2 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[9] inout AB1 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[8] inout AC1 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[7] inout AG3 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[6] inout AH3 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[5] inout AE3 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[4] inout AF3 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[3] inout AH2 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[2] inout AH1 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[1] inout AF1 DDR4數(shù)據(jù) POD12
c0_ddr4_dq[0] inout AG1 DDR4數(shù)據(jù) POD12
c0_ddr4_dqs_t[1]} inout AD2 DDR4數(shù)據(jù)選取脈沖 DIFF_ POD12
c0_ddr4_dqs_c[1]} inout AD1 DDR4數(shù)據(jù)選取脈沖 DIFF_ POD12
c0_ddr4_dqs_t[0]} inout AE2 DDR4數(shù)據(jù)選取脈沖 DIFF_ POD12
c0_ddr4_dqs_c[0]} inout AF2 DDR4數(shù)據(jù)選取脈沖 DIFF_ POD12
c0_ddr4_adr[16] output AB5 DDR4地址線 SSTL12
c0_ddr4_adr[15] output AB7 DDR4地址線 SSTL12
c0_ddr4_adr[14] output AF6 DDR4地址線 SSTL12
c0_ddr4_adr[13] output AD9 DDR4地址線 SSTL12
c0_ddr4_adr[12] output AC6 DDR4地址線 SSTL12
c0_ddr4_adr[11] output AH9 DDR4地址線 SSTL12
c0_ddr4_adr[10] output AE7 DDR4地址線 SSTL12
c0_ddr4_adr[9] output AC9 DDR4地址線 SSTL12
c0_ddr4_adr[8] output AH8 DDR4地址線 SSTL12
c0_ddr4_adr[7] output AE9 DDR4地址線 SSTL12
c0_ddr4_adr[6] output AH7 DDR4地址線 SSTL12
c0_ddr4_adr[5] output AD7 DDR4地址線 SSTL12
c0_ddr4_adr[4] output AF7 DDR4地址線 SSTL12
c0_ddr4_adr[3] output AC8 DDR4地址線 SSTL12
c0_ddr4_adr[2] output AF8 DDR4地址線 SSTL12
c0_ddr4_adr[1] output AB8 DDR4地址線 SSTL12
c0_ddr4_adr[0] output AG8 DDR4地址線 SSTL12
c0_ddr4_ba[1] output AC7 DDR4 Bank地址 SSTL12
c0_ddr4_ba[0] output AH6 DDR4 Bank地址 SSTL12
c0_ddr4_bg output AE8 DDR4 Bank組地址 SSTL12
c0_ddr4_reset_n output AG9 DDR4 復(fù)位信號 LVCMOS12
c0_ddr4_cke output AE4 DDR4 時鐘使能信號 SSTL12
c0_ddr4_cs_n output AB6 DDR4 片選信號 SSTL12
c0_ddr4_dm_dbi_n[1] output AD5 DDR4 數(shù)據(jù)掩碼 POD12
c0_ddr4_dm_dbi_n[0] output AG4 DDR4 數(shù)據(jù)掩碼 POD12
c0_ddr4_odt output E2 DDR4 終端電阻使能 SSTL12
c0_ddr4_ck_t output AG6 DDR4 差分時鐘正 DIFF_ SSTL12
c0_ddr4_ck_c output AG5 DDR4 差分時鐘負(fù) DIFF_ SSTL12

如上表所示,本次實驗用到了五種電平,分別是LVCMOS、SSTL、POD12、DIFF_SSTL以及DIFF_ POD12,下面對于這五種電平我們做一個簡單的介紹。
LVCMOS:全稱Low Voltage Complementary Metal Oxide Semiconductor,低壓互補金屬氧化物半導(dǎo)體;
SSTL:全稱Stub Series Terminated Logic,短截線串聯(lián)端接邏輯;
DIFF_SSTL:全稱Difference Stub Series Terminated Logic,差分短截線串聯(lián)端接邏輯;
POD12:POD12是由VDDQ端提供的電壓,一般用于DDR4,當(dāng)POD12電壓驅(qū)動端的上拉電路導(dǎo)通,電路處于高電平時,回路上沒有電流流過,這樣的設(shè)計較少了功耗;
DIFF_ POD12:與POD12一樣,只不過是差分電壓。
除此之外,LVCMOS的特點是噪聲容限大,速度較SSTL慢;SSTL速度快,通常要匹配合適的端接電阻,常用于高速內(nèi)存接口如DDR4;DIFF_SSTL則是帶有差分功能的SSTL。POD和SSTL的最大區(qū)別在于接收端的終端電壓(POD為VDDQ,SSTL為VDDQ/2)。POD可以降低寄生引腳電容和I/O終端功耗,并且即使在VDD電壓降低的情況下也能穩(wěn)定工作。
DDR4的管腳使用的是SSTL、POD12、DIFF_SSTL以及DIFF_ POD12,這里要注意一下DDR4復(fù)位信號c0_DDR4_reset_n,它并沒有使用SSTL,原因是SSTL的噪聲容限不夠大,容易受干擾造成誤復(fù)位。
本實驗對應(yīng)的XDC約束語句如下所示。注意,在這里僅給出了時鐘、復(fù)位、和LED讀寫指示信號的管腳約束。DDR4部分的管腳約束在文檔中不再給出,大家可以從提供的例程中查看。
set_property -dict {PACKAGE_PIN AE5 IOSTANDARD DIFF_HSTL_I_12} [get_ports c0_sys_clk_p]
set_property -dict {PACKAGE_PIN AF5 IOSTANDARD DIFF_HSTL_I_12} [get_ports c0_sys_clk_n]
set_property -dict {PACKAGE_PIN AH11 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
set_property -dict {PACKAGE_PIN AE10 IOSTANDARD LVCMOS33} [get_ports led]
31.4程序設(shè)計
根據(jù)實驗任務(wù),可以大致規(guī)劃出系統(tǒng)的控制流程:首先FPGA通過調(diào)用MIG IP核向DDR4芯片寫入數(shù)據(jù),寫完之后通過MIG IP核從DDR4芯片讀出所寫入的數(shù)據(jù),并判斷讀出的數(shù)據(jù)與寫入的數(shù)據(jù)是否相同,如果相同則LED燈常亮,否則LED燈閃爍。由此畫出系統(tǒng)的功能框圖如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.1 DDR4 讀寫測試實驗系統(tǒng)框圖
由系統(tǒng)總體框圖可知,F(xiàn)PGA頂層模塊例化了以下兩個模塊,分別是讀寫模塊(ddr4_rw)和MIG IP核模塊。
各模塊端口及信號連接如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.2 頂層模塊原理圖
其中DDR4讀寫模塊的作用是生成DDR4的讀寫數(shù)據(jù)和MIG IP核的驅(qū)動時序,并且在DDR4模塊里比較寫入DDR4的數(shù)據(jù)與讀出的數(shù)據(jù)是否一致,如果讀寫一致,說明DDR4讀寫正確,此時LED指示燈常亮;否則說明DDR4讀寫失敗,LED指示燈處于閃爍狀態(tài)。而MIG IP核內(nèi)部包含了整個DDR4的驅(qū)動,一方面它負(fù)責(zé)驅(qū)動板載的DDR4芯片,另一方面和用戶模塊進(jìn)行數(shù)據(jù)交互,在本節(jié)實驗中用戶模塊就是DDR4讀寫模塊,MIG IP核負(fù)責(zé)和DDR4讀寫模塊進(jìn)行數(shù)據(jù)交互。
需要注意的是,本節(jié)實驗的系統(tǒng)時鐘是一對差分時鐘,頻率為100Mhz(c0_sys_clk_p,c0_sys_clk_n),這對差分時鐘直接連接到MIG IP核,由MIG IP核生成DDR4的驅(qū)動時鐘(c0_DDR4_ck_t,c0_DDR4_ck_c),輸出給外部DDR4(MT40A256M16GE-083E)芯片使用。除此之外,F(xiàn)PGA內(nèi)部的用戶模塊時鐘也是由MIG IP核提供,本節(jié)實驗的用戶模塊時鐘是c0_DDR4_ui_clk,作為DDR4讀寫模塊的操作時鐘。
接下來我們介紹下如何對MIG IP核進(jìn)行配置。首先在Vivado環(huán)境里新建一個工程,本實驗取名為ddr4_rw_top。再點擊Project Manager界面下的IP Catalog,打開IP Catalog界面。如下圖所示。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.3 “IP Catalog”按鈕
在搜索欄中輸入MIG,此時出現(xiàn)MIG IP核,我們找到DDR4 SDRAM(MIG),如下圖所示。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.4 搜索欄中輸入關(guān)鍵字
雙擊打開DDR4 SDRAM(MIG),出現(xiàn)如下圖所示界面。

ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.5 IP核配置
上圖所示的是MIG IP 核的Basic配置界面,這里我們對幾個重要的配置信息作出說明:
Component Name:MIG IP核的命名,可以保持默認(rèn),也可以自己取一個名字。
Mode and Interface:控制器的模式和接口選項,可以選擇AXI4接口或者普通模式,并生成對應(yīng)的PHY組件(詳情請參考官方文檔pg150)。
Memory Device Interface Speed:板載DDR4芯片的IO總線時鐘頻率,這里可以最大支持938ps(1066MHz),IO總線時鐘頻率等于2倍DDR4芯片核心頻率(533 MHz)。
PHY to controller clock frequency ratio:用戶時鐘分頻系數(shù),這里只能選擇4比1,因此本節(jié)實驗的用戶時鐘頻率等于DDR4芯片核心頻率的四分之一,即133.25MHz。
Reference input Clock Speed:參考時鐘,本節(jié)實驗選擇10006ps(參考時鐘頻率和系統(tǒng)時鐘頻率保持一致即100MHz)。
Controller Options:控制器配置欄,如果使用MIG IP核內(nèi)部默認(rèn)的DDR4芯片,則只需要在Memory Part欄選中對應(yīng)的DDR4芯片型號即可,例如我們板載的DDR4芯片型號為MT40A256M16GE-083E(如果多片DDR4聯(lián)用注意修改數(shù)據(jù)位寬)。如果使用的DDR4芯片型號不在MIG IP和的默認(rèn)配置中就需要手動定義DDR4芯片的參數(shù)文件,這個時候就需要使能定制型號(Enable Custom Parts Data File),然后加載配置文件(Custom Parts Data File)。
Memory Options:配置突發(fā)長度和CAS延遲的,這里保持默認(rèn)即可(如果需要修改請參考DDR4芯片數(shù)據(jù)手冊)。
接下來我們選擇MIG IP核配置界面的Advanced Clocking界面,如下所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.6 IP核配置界面
Advanced Clocking界面只需要關(guān)注一下Additional Clock Outputs配置,這里可以額外輸出四路時鐘,如果有需求這里可以生成,我們本節(jié)實驗不需要用到額外時鐘,所以全部“None”即可。
接下來切換至Advanced Options界面,如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.7 IP核配置界面
Advanced Options界面的配置信息如下:
Debug Signals for controller:在Xilinx示例設(shè)計中,啟用此功能會把狀態(tài)信號連接到ChipScope ILA核中。
Microblaze MCS ECC option:Microblaze的配置選項,選中它Microblaze的MCS ECC尺寸會增加。
Simulation Options:此選項僅對仿真有效。在選擇BFM選項時,為XiPhy庫使用行為模型,以加快模擬運行時間。選擇Unisim則對XiPhy原語使用Unisim庫。
Example Design Options:示例工程仿真文件的選擇。
Advance Memory Options:提高運行性能的選項,可以選擇自刷新和校準(zhǔn)功能,并將這些信息保存在XSDB BRAM中,也可以把XSDB BRAM中的信息存儲在外部存儲器中 。
Migration Options:引腳兼容選項,如果想兼容UlitraScale和UltraScale+ fpga,就把這個選項選中。
最后我們再來看看IO Planning and Design Checklist界面,如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.8 IP核配置界面
IO Planning and Design Checklist界面提示我們DDR4 IO引腳分配的方式發(fā)生改變,不再像之前DDR3那樣,需要在MIG IP核中就分配好管腳,DDR4可以在IO Planning窗口分配管腳(或者直接編寫XDC文件)。
當(dāng)所有的配置信息全部修改完成后,點擊“OK”按鈕,彈出的界面如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.9 生成IP核
點擊Generate按鈕生成IP核,IP核生成完成后,開始編寫DDR4讀寫實驗的代碼。
頂層模塊的代碼,如下所示:

1   module ddr4_rw_top(
2       output                             c0_ddr4_act_n   ,
3       output [16:0]                      c0_ddr4_adr     ,
4       output [1:0]                       c0_ddr4_ba      ,
5       output [0:0]                       c0_ddr4_bg      ,
6       output [0:0]                       c0_ddr4_cke     ,
7       output [0:0]                       c0_ddr4_odt     ,
8       output [0:0]                       c0_ddr4_cs_n    ,
9       output [0:0]                       c0_ddr4_ck_t    ,
10      output [0:0]                       c0_ddr4_ck_c    ,
11      output                             c0_ddr4_reset_n ,
12      inout  [1:0]                       c0_ddr4_dm_dbi_n,
13      inout  [15:0]                      c0_ddr4_dq      ,
14      inout  [1:0]                       c0_ddr4_dqs_c   ,
15      inout  [1:0]                       c0_ddr4_dqs_t   ,               
16      
17      //Differential system clocks
18      input                              c0_sys_clk_p,
19      input                              c0_sys_clk_n,
20      output[1:0]                        led,
21      input                              sys_rst_n
22      );                
23                      
24  //wire define  
25  
26  wire                 error_flag;
27  
28  wire c0_ddr4_ui_clk                ;
29  wire c0_ddr4_ui_clk_sync_rst       ;
30  wire c0_ddr4_app_en                ;
31  wire c0_ddr4_app_hi_pri            ;
32  wire c0_ddr4_app_wdf_end           ;
33  wire c0_ddr4_app_wdf_wren          ;
34  wire c0_ddr4_app_rd_data_end       ; 
35  wire c0_ddr4_app_rd_data_valid     ; 
36  wire c0_ddr4_app_rdy               ; 
37  wire c0_ddr4_app_wdf_rdy           ; 
38  wire [27 : 0] c0_ddr4_app_addr     ;
39  wire [2 : 0] c0_ddr4_app_cmd       ;
40  wire [127 : 0] c0_ddr4_app_wdf_data;
41  wire [15 : 0] c0_ddr4_app_wdf_mask ;
42  wire [127 : 0] c0_ddr4_app_rd_data ;
43  
44  
45  
46  wire                  locked;              //鎖相環(huán)頻率穩(wěn)定標(biāo)志
47  wire                  clk_ref_i;           //DDR4參考時鐘
48  wire                  sys_clk_i;           //MIG IP核輸入時鐘
49  wire                  clk_200;             //200M時鐘
50  wire                  ui_clk_sync_rst;     //用戶復(fù)位信號
51  wire                  init_calib_complete; //校準(zhǔn)完成信號
52  wire [20:0]           rd_cnt;              //實際讀地址計數(shù)
53  wire [1 :0]           state;               //狀態(tài)計數(shù)器
54  wire [23:0]           rd_addr_cnt;         //用戶讀地址計數(shù)器
55  wire [23:0]           wr_addr_cnt;         //用戶寫地址計數(shù)器
56  
57  //*****************************************************
58  //**                    main code
59  //*****************************************************
60  
61  //讀寫模塊
62  ddr4_rw u_ddr4_rw(
63      .ui_clk               (c0_ddr4_ui_clk),                
64      .ui_clk_sync_rst      (c0_ddr4_ui_clk_sync_rst),       
65      .init_calib_complete  (c0_init_calib_complete),
66      .app_rdy              (c0_ddr4_app_rdy),
67      .app_wdf_rdy          (c0_ddr4_app_wdf_rdy),
68      .app_rd_data_valid    (c0_ddr4_app_rd_data_valid),
69      .app_rd_data          (c0_ddr4_app_rd_data),
70      
71      .app_addr             (c0_ddr4_app_addr),
72      .app_en               (c0_ddr4_app_en),
73      .app_wdf_wren         (c0_ddr4_app_wdf_wren),
74      .app_wdf_end          (c0_ddr4_app_wdf_end),
75      .app_cmd              (c0_ddr4_app_cmd),
76      .app_wdf_data         (c0_ddr4_app_wdf_data),
77      .state                (state),
78      .rd_addr_cnt          (rd_addr_cnt),
79      .wr_addr_cnt          (wr_addr_cnt),
80      .rd_cnt               (rd_cnt),
81      
82      .error_flag           (error_flag),
83      .led                  (led)
84      );
85  ddr4_0 u_ddr4_0 (
86  .c0_init_calib_complete(c0_init_calib_complete),//初始化完成信號       
87  .dbg_clk(),                          
88  .c0_sys_clk_p(c0_sys_clk_p),          // 系統(tǒng)差分時鐘p
89  .c0_sys_clk_n(c0_sys_clk_n),          // 系統(tǒng)差分時鐘n
90  .dbg_bus(),                           
91  .c0_ddr4_adr(c0_ddr4_adr),            // 行列地址
92  .c0_ddr4_ba(c0_ddr4_ba),              // bank地址
93  .c0_ddr4_cke(c0_ddr4_cke),            // 時鐘使能
94  .c0_ddr4_cs_n(c0_ddr4_cs_n),          // 片選信號
95  .c0_ddr4_dm_dbi_n(c0_ddr4_dm_dbi_n),  // 數(shù)據(jù)掩碼
96  .c0_ddr4_dq(c0_ddr4_dq),              // 數(shù)據(jù)線
97  .c0_ddr4_dqs_c(c0_ddr4_dqs_c),        // 數(shù)據(jù)選通信號
98  .c0_ddr4_dqs_t(c0_ddr4_dqs_t),        // 數(shù)據(jù)選通信號
99  .c0_ddr4_odt(c0_ddr4_odt),            // 終端電阻
100 .c0_ddr4_bg(c0_ddr4_bg),              // bank組地址
101 .c0_ddr4_reset_n(c0_ddr4_reset_n),    // 復(fù)位信號
102 .c0_ddr4_act_n(c0_ddr4_act_n),        // 激活指令引腳
103 .c0_ddr4_ck_c(c0_ddr4_ck_c),          //時鐘信號
104 .c0_ddr4_ck_t(c0_ddr4_ck_t),          // 時鐘信號
105 //user interface
106 .c0_ddr4_ui_clk(c0_ddr4_ui_clk),       // 用戶時鐘
107 .c0_ddr4_ui_clk_sync_rst(c0_ddr4_ui_clk_sync_rst), // 用戶復(fù)位
108 .c0_ddr4_app_en(c0_ddr4_app_en),                  // 指令寫入使能
109 .c0_ddr4_app_hi_pri(1'b0),                        
110 .c0_ddr4_app_wdf_end(c0_ddr4_app_wdf_end),        // 寫數(shù)據(jù)最后一個時鐘
111 .c0_ddr4_app_wdf_wren(c0_ddr4_app_wdf_wren),      // 寫數(shù)據(jù)使能
112 .c0_ddr4_app_rd_data_end(c0_ddr4_app_rd_data_end),// 讀數(shù)據(jù)最后一個數(shù)據(jù)
113 .c0_ddr4_app_rd_data_valid(c0_ddr4_app_rd_data_valid), // 讀數(shù)據(jù)有效                 
114 .c0_ddr4_app_rdy(c0_ddr4_app_rdy),           // 指令接收準(zhǔn)備完成,可以開始接收指令
115 .c0_ddr4_app_wdf_rdy(c0_ddr4_app_wdf_rdy),   // 數(shù)據(jù)接收準(zhǔn)備完成,可以開始接收數(shù)據(jù)
116 .c0_ddr4_app_addr(c0_ddr4_app_addr),         // 用戶地址
117 .c0_ddr4_app_cmd(c0_ddr4_app_cmd),           // 讀寫控制命令
118 .c0_ddr4_app_wdf_data(c0_ddr4_app_wdf_data), // 寫數(shù)據(jù)
119 .c0_ddr4_app_wdf_mask(16'b0),                // input wire [15 : 0] c0_ddr4_app_wdf_mask
120 .c0_ddr4_app_rd_data(c0_ddr4_app_rd_data),   // 讀數(shù)據(jù)
121 .sys_rst(~sys_rst_n)                           //系統(tǒng)復(fù)位
122 );    
123 
124 endmodule

頂層模塊的代碼共例化了兩個子模塊,分別是DDR4讀寫模塊(ddr4_rw)和MIG IP核模塊(ddr4_0),主要實現(xiàn)各模塊的數(shù)據(jù)交互。
DDR4讀寫模塊的代碼如下:

1   module ddr4_rw (          
2       input                    ui_clk,                //用戶時鐘
3       input                    ui_clk_sync_rst,       //復(fù)位,高有效
4       input                    init_calib_complete,   //DDR4初始化完成
5       input                    app_rdy,               //MIG 命令接收準(zhǔn)備好標(biāo)致
6       input                    app_wdf_rdy,           //MIG數(shù)據(jù)接收準(zhǔn)備好
7       input                    app_rd_data_valid,     //讀數(shù)據(jù)有效
8       input          [127:0]   app_rd_data,           //用戶讀數(shù)據(jù)
9       output reg     [27:0]    app_addr,              //DDR4地址                      
10      output                   app_en,                //MIG IP發(fā)送命令使能
11      output                   app_wdf_wren,          //用戶寫數(shù)據(jù)使能
12      output                   app_wdf_end,           //突發(fā)寫當(dāng)前時鐘最后一個數(shù)據(jù) 
13      output         [2:0]     app_cmd,               //MIG IP核操作命令,讀或者寫
14      output reg     [127:0]   app_wdf_data,          //用戶寫數(shù)據(jù)
15      output reg     [1 :0]    state,                 //讀寫狀態(tài)
16      output reg     [23:0]    rd_addr_cnt,           //用戶讀地址計數(shù)
17      output reg     [23:0]    wr_addr_cnt,           //用戶寫地址計數(shù)
18      output reg     [20:0]    rd_cnt,                //實際讀地址標(biāo)記
19      output reg               error_flag,            //讀寫錯誤標(biāo)志
20      output reg               led                    //讀寫測試結(jié)果指示燈
21      );
22  
23  //parameter define
24  parameter  TEST_LENGTH = 10;
25  parameter  L_TIME = 25'd25_000_000;
26  parameter  IDLE        = 2'd0;            //空閑狀態(tài)
27  parameter  WRITE       = 2'd1;            //寫狀態(tài)
28  parameter  WAIT        = 2'd2;            //讀到寫過度等待
29  parameter  READ        = 2'd3;            //讀狀態(tài)
30  
31  //reg define
32  reg  [24:0]  led_cnt;    //led計數(shù)
33  
34  //wire define
35  wire         error;     //讀寫錯誤標(biāo)記
36  wire         rst_n;     //復(fù)位,低有效

代碼第2行到第20行是模塊的接口定義,大部分是MIG IP核中要操作的用戶接口信號,這些信號在本章簡介部分中已經(jīng)以表格的形式詳細(xì)呈現(xiàn)給大家,有不清楚的地方可以回去查看。
代碼第24行和第29行是參數(shù)定義,首先定義了TEST_LENGTH(測試長度),注意這里的測試長度是相對于用戶端來說的,一個測試長度對應(yīng)到DDR芯片需要訪問是8個地址,即8個16Byte(共128位)。接下來定義了L_TIME(閃爍間隔),該參數(shù)用來控制LED閃爍頻率。最后定義了讀寫測試的四個狀態(tài),IDLE(空閑)、WRITE(寫)、WAIT(等待)和READ(讀)。

37  
38   //*****************************************************
39  //**                    main code
40  //***************************************************** 
41  
42  assign rst_n = ~ui_clk_sync_rst;
43  //讀信號有效,且讀出的數(shù)不是寫入的數(shù)時,將錯誤標(biāo)志位拉高
44  assign error = (app_rd_data_valid && (rd_cnt! = app_rd_data));
45  
46  //在寫狀態(tài)MIG IP 命令接收和數(shù)據(jù)接收都準(zhǔn)備好,或者在讀狀態(tài)命令接收準(zhǔn)備好,此時拉高使能信號,
47  assign app_en = ((state == WRITE && (app_rdy && app_wdf_rdy))
48                  ||(state == READ && app_rdy)) ? 1'b1:1'b0;
49                  
50  //在寫狀態(tài),命令接收和數(shù)據(jù)接收都準(zhǔn)備好,此時拉高寫使能
51  assign app_wdf_wren = (state == WRITE && (app_rdy && app_wdf_rdy)) ? 1'b1:1'b0;
52  
53  //由于DDR4芯片時鐘和用戶時鐘的分頻選擇4:1,突發(fā)長度為8,故兩個信號相同
54  assign app_wdf_end = app_wdf_wren; 
55  
56  //處于讀的時候命令值為1,其他時候命令值為0
57  assign app_cmd = (state == READ) ? 3'd1 :3'd0;  
58      

代碼第42行,信號ui_clk_sync_rst是MIG IP核產(chǎn)生,用于復(fù)位用戶邏輯,其高電平有效。在代碼中將ui_clk_sync_rst信號取反,是為了轉(zhuǎn)換成代碼中習(xí)慣使用的復(fù)位低電平有效。
代碼第44行,是錯誤標(biāo)志的邏輯判斷。讀數(shù)據(jù)有效信號(app_rd_data_valid)為高時去比較app_rd_data和rd_cnt的值,不相等則讀寫錯誤。關(guān)于rd_cnt的含義將會在下文詳細(xì)介紹。
代碼第47行到48行,首先產(chǎn)生了MIG IP核命令發(fā)送使能信號,這里可以看出,讀或者寫狀態(tài)都要拉高該信號。需要特別指出的是,在寫的時候,app_en拉高的條件是:app_rdy(MIG命令接收準(zhǔn)備好標(biāo)志)和app_wdf_rdy(MIG數(shù)據(jù)接收準(zhǔn)備好標(biāo)致)同時為高,根據(jù)數(shù)據(jù)手冊,用戶可以只判斷app_rdy信號。當(dāng)app_rdy信號為高電平時,可以拉高使能app_en,此處之所以同時判斷app_rdy和app_wdf_rdy,是因為本實驗只考慮DDR4寫狀態(tài)命令發(fā)送和數(shù)據(jù)發(fā)送同拍的情形,這樣的做法基本上不會對DDR4讀寫操作效率造成很大影響,但是卻能大大簡化代碼編寫難度。
代碼第51行,產(chǎn)生寫使能,如上所述,本實驗只考慮寫命令和寫數(shù)據(jù)同時發(fā)起的情形,當(dāng)檢測到命令接收和數(shù)據(jù)接收標(biāo)志同時拉高的時候,寫操作也在同一時間被發(fā)起,即拉高app_wdf_wren(寫數(shù)據(jù)使能)。
這里要解釋一下代碼第54行。上文說過app_wdf_end表明當(dāng)前時鐘是突發(fā)寫過程的最后一個時鐘周期,由于本實驗采用的是4:1模式,每一個用戶時鐘周期實際上都完成了一個寫突發(fā)操作,所以在突發(fā)寫有效時,即app_wdf_wren拉高,每個時鐘,app_wdf_end也跟著拉高,所以在4:1模式信號app_wdf_end和app_wdf_wren是同步變化的。

59  //DDR4讀寫邏輯實現(xiàn)
60  always @(posedge ui_clk or negedge rst_n) begin
61      if((~rst_n)||(error_flag)) begin 
62          state    <= IDLE;          
63          app_wdf_data <= 128'd0;     
64          wr_addr_cnt  <= 24'd0;      
65          rd_addr_cnt  <= 24'd0;       
66          app_addr     <= 28'd0;          
67      end
68      else if(init_calib_complete)begin               //MIG IP核初始化完成
69          case(state)
70              IDLE:begin
71                  state    <= WRITE;
72                  app_wdf_data <= 128'd0;   
73                  wr_addr_cnt  <= 24'd0;     
74                  rd_addr_cnt  <= 24'd0;       
75                  app_addr     <= 28'd0;        
76               end
77              WRITE:begin
78                  if(wr_addr_cnt == TEST_LENGTH - 1 &&(app_rdy && app_wdf_rdy))
79                      state    <= WAIT;                  //寫到設(shè)定的長度跳到等待狀態(tài)
80                  else if(app_rdy && app_wdf_rdy)begin   //寫條件滿足
81                      app_wdf_data <= app_wdf_data + 1;  //寫數(shù)據(jù)自加
82                      wr_addr_cnt  <= wr_addr_cnt + 1;   //寫地址自加
83                      app_addr     <= app_addr + 8;      //DDR4 地址加8
84                  end
85                  else begin                             //寫條件不滿足,保持當(dāng)前值
86                      app_wdf_data <= app_wdf_data;      
87                      wr_addr_cnt  <= wr_addr_cnt;
88                      app_addr     <= app_addr; 
89                  end
90                end
91              WAIT:begin                                                  
92                  state   <= READ;                     //下一個時鐘,跳到讀狀態(tài)
93                  rd_addr_cnt <= 24'd0;                //讀地址復(fù)位
94                  app_addr    <= 28'd0;                //DDR4讀從地址0開始
95                end
96              READ:begin                               //讀到設(shè)定的地址長度    
97                  if(rd_addr_cnt == TEST_LENGTH - 1 && app_rdy)
98                      state   <= IDLE;                   //則跳到空閑狀態(tài) 
99                  else if(app_rdy)begin                  //若MIG已經(jīng)準(zhǔn)備好,則開始讀
100                     rd_addr_cnt <= rd_addr_cnt + 1'd1; //用戶地址每次加一
101                     app_addr    <= app_addr + 8;       //DDR4地址加8
102                 end
103                 else begin                             //若MIG沒準(zhǔn)備好,則保持原值
104                     rd_addr_cnt <= rd_addr_cnt;
105                     app_addr    <= app_addr; 
106                 end
107               end
108             default:begin
109                 state    <= IDLE;
110                 app_wdf_data <= 128'd0;
111                 wr_addr_cnt  <= 24'd0;
112                 rd_addr_cnt  <= 24'd0;
113                 app_addr     <= 28'd0;
114             end
115         endcase
116     end
117 end   
118                         
119 //對DDR4實際讀數(shù)據(jù)個數(shù)編號計數(shù)
120 always @(posedge ui_clk or negedge rst_n) begin
121     if(~rst_n) 
122         rd_cnt  <= 0;              //若計數(shù)到讀寫長度,且讀有效,地址計數(shù)器則置0                                    
123     else if(app_rd_data_valid && rd_cnt == TEST_LENGTH - 1)
124          rd_cnt <= 0;              //其他條件只要讀有效,每個時鐘自增1
125     else if (app_rd_data_valid )
126         rd_cnt <= rd_cnt + 1;
127 end
128 
129 //寄存狀態(tài)標(biāo)志位
130 always @(posedge ui_clk or negedge rst_n) begin
131     if(~rst_n) 
132         error_flag <= 0;
133     else if(error)
134         error_flag <= 1;
135  end
136  
137 //led指示效果控制
138 always @(posedge ui_clk or negedge rst_n) begin
139      if((~rst_n) || (~init_calib_complete )) begin
140         led_cnt <= 25'd0;
141         led <= 1'b0;
142     end
143     else begin
144         if(~error_flag)                        //讀寫測試正確         
145             led <= 1'b1;                       //led燈常亮
146          else begin                            //讀寫測試錯誤
147             led_cnt <= led_cnt + 25'd1;
148             if(led_cnt == L_TIME - 1'b1) begin
149             led_cnt <= 25'd0;
150             led <= ~led;                      //led燈閃爍
151             end                    
152          end
153       end
154 end
155 
156 endmodule

代碼60行起的always模塊是DDR4讀寫邏輯的實現(xiàn)。采用了一段式狀態(tài)機(jī)來編寫整個讀寫測試邏輯,如下圖所示,一共分為四個狀態(tài)。描述如下:上電一開始處于IDLE(空閑)狀態(tài),初始化完成后跳到WRITE(DDR4寫),寫到測試長度跳到WAIT(等待)狀態(tài),在此消耗一個實在周期后無條件跳到READ(DDR4讀),讀到測試長度跳回空閑狀態(tài)。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.10 讀寫測試狀態(tài)跳轉(zhuǎn)圖
下面來講解具體的各狀態(tài),主要是寫和讀狀態(tài)。
首先來看看寫過程,為了便于理解,下面給出了ILA中采集到的DDR4寫的波形,同時為了方便觀察完整的寫過程,把本次實驗的一次讀寫長度設(shè)為10。如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.11 DDR4寫時序
寫狀態(tài)首先判斷MIG IP核發(fā)送過來的信號app_rdy和app_wdf_rdy,當(dāng)這兩個信號同時為高時,拉高app_en和app_wdf_wren,同時時給寫出命令,即app_cmd為0,此刻正式進(jìn)行DDR4寫過程。寫的過程中,寫數(shù)據(jù)app_wdf_data和地址計數(shù)wr_addr_cnt在每個時鐘自加1。另外大家注意到app_addr每次自加8,前面其實提到,用戶端在每一個用戶時鐘進(jìn)行一個128bit的數(shù)據(jù)的傳輸,在DDR4物理芯片端需要分8次傳輸,每次傳輸一個地址位寬16bit,8次就需要8個地址。通過寫時序圖和ILA圖進(jìn)行對比,可以發(fā)現(xiàn)兩者是一致的,即說明本次實驗是成功的
代碼第96到107行是DDR4讀過程,在讀狀態(tài),判斷MIG IP核發(fā)送過來的信號app_rdy,當(dāng)這個信號為高時,拉高app_en,同時給出讀命令,即app_cmd為1,此時開始進(jìn)行讀操作。在進(jìn)行讀操作的時候,app_addr同樣每次自加8。下面還是給出ILA上觀察到的讀信號波形,方便大家理解查看。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.12 DDR4讀時序
讀操作結(jié)束又跳回空閑狀態(tài),如代碼第98行所示。
代碼第120行到127行的always模塊,產(chǎn)生rd_cnt,實現(xiàn)了對讀出的地址數(shù)據(jù)的編號。為什么會有這樣的處理,根本原因在于讀數(shù)據(jù)的返回和讀操作并不是在同一拍出現(xiàn)的,會晚若干周期出現(xiàn)。這樣意味著不能用讀數(shù)據(jù)直接和當(dāng)前的讀地址去比較,所以本次實驗單獨構(gòu)造了rd_cnt這個信號,它代表一次讀操作真正返回的有效的讀數(shù)據(jù)個數(shù)。
代碼第130行到135行的always模塊,實現(xiàn)了錯誤標(biāo)識的寄存。代碼第138行到154行的always模塊實現(xiàn)讀寫測試LED燈的顯示邏輯。錯誤則閃爍,正確則常亮。
最后通過采集到的波形來看讀寫測試結(jié)果,在讀數(shù)據(jù)有效信號app_rd_data_valid為高時,數(shù)據(jù)總線上的app_rd_data分別和地址編號rd_cnt相等。按照本次實驗的設(shè)計,寫進(jìn)DDR4的數(shù)值是它的地址編號,也即等于數(shù)據(jù)編號,說明是正確的讀寫結(jié)果。當(dāng)然大家可以看到錯誤指示信號error_flag始終為0,即沒有出現(xiàn)讀寫錯誤。
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.4.13 DDR4讀結(jié)果
31.5下載驗證
將下載器一端連接電腦,另一端與開發(fā)板上的JTAG下載口連接,接下來連接電源線后撥動開關(guān)按鍵給開發(fā)板上電。
點擊Vivado左側(cè)“Flow Navigator”窗口最下面的“Open Hardware Manager”,此時Vivado軟件識別到下載器,點擊“Hardware”窗口中“Progam Device”下載程序,在彈出的界面中選擇“Program”下載程序。
程序下載完成后,開發(fā)板上的PL_LED1在短暫延時之后,始終處于常亮的狀態(tài),如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.5.1 DDR4板子測試結(jié)果
此時說明DDR4讀寫測試成功。
在這里再額外補充一點,將帶有DDR4 MIG IP核的工程下載進(jìn)開發(fā)板時,會出現(xiàn)一個MIG自帶的狀態(tài)檢測核,如下圖所示:
ddr4 fpga,正點原子,fpga開發(fā)

圖 31.5.2 DDR4狀態(tài)
從上圖中可以看到MIG運行的一些狀態(tài)信息,如果運行正常會顯示“PASS”。到這里DDR4讀寫實驗就給大家全部講解完了。文章來源地址http://www.zghlxwxcb.cn/news/detail-792474.html

到了這里,關(guān)于【正點原子FPGA連載】第三十一章DDR4讀寫測試實驗 摘自【正點原子】DFZU2EG/4EV MPSoC 之FPGA開發(fā)指南V1.0的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包