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

【正點(diǎn)原子FPGA連載】第二十章AXI4接口之DDR讀寫實(shí)驗(yàn) 摘自【正點(diǎn)原子】DFZU2EG_4EV MPSoC之嵌入式Vitis開發(fā)指南

這篇具有很好參考價(jià)值的文章主要介紹了【正點(diǎn)原子FPGA連載】第二十章AXI4接口之DDR讀寫實(shí)驗(yàn) 摘自【正點(diǎn)原子】DFZU2EG_4EV MPSoC之嵌入式Vitis開發(fā)指南。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

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

第二十章AXI4接口之DDR讀寫實(shí)驗(yàn)

Xilinx從Spartan-6和Virtex-6系列開始使用AXI協(xié)議來連接IP核。在ZYNQ MPSOC器件中,Xilinx在IP核中繼續(xù)使用AXI協(xié)議。本章我們對AXI協(xié)議作一個(gè)簡單介紹,并在Vivado中實(shí)現(xiàn)一個(gè)AXI4接口的IP核,用于對MPSOC PS端的DDR4進(jìn)行讀寫測試。
本章包括以下幾個(gè)部分:
2020.1簡介
20.2實(shí)驗(yàn)任務(wù)
20.3硬件設(shè)計(jì)
20.4軟件設(shè)計(jì)
20.5下載驗(yàn)證

20.1簡介

MPSOC將高性能ARM Cotex-A系列處理器與高性能FPGA在單芯片內(nèi)緊密結(jié)合,為設(shè)計(jì)帶來了如減小體積和功耗、降低設(shè)計(jì)風(fēng)險(xiǎn),增加設(shè)計(jì)靈活性等諸多優(yōu)點(diǎn)。在將不同工藝特征的處理器與FPGA融合在一個(gè)芯片上之后,片內(nèi)處理器與FPGA之間的互聯(lián)通路就成了MPSOC芯片設(shè)計(jì)的重中之重。如果Cotex-A53與FPGA之間的數(shù)據(jù)交互成為瓶頸,那么處理器與FPGA結(jié)合的性能優(yōu)勢就不能發(fā)揮出來。
我們在前面的實(shí)驗(yàn)中介紹了一些MPSOC PS與PL交互所使用的接口,比如《EMIO按鍵控制LED實(shí)驗(yàn)》中的EMIO,以及《AXI GPIO按鍵控制LED實(shí)驗(yàn)》中的AXI4-Lite接口等。其中AXI4-Lite接口屬于AXI4總線協(xié)議,接下來我們將對該協(xié)議作一個(gè)更具體的介紹。
AXI的英文全稱是Advanced eXtensible Interface,即高級可擴(kuò)展接口,它是ARM公司所提出的AMBA(Advanced Microcontroller Bus Architecture)協(xié)議的一部分。在介紹AXI協(xié)議之前,我們首先要對通信協(xié)議有一個(gè)基本的概念。
簡單來說,通信協(xié)議就是指雙方進(jìn)行信息傳遞所遵循的規(guī)則和約定。其實(shí)在我們的生活當(dāng)中,比如在打電話的時(shí)候,就遵循著一些基本的“通信協(xié)議”。為了更形象的說明這一概念,我們首先來看一個(gè)通話記錄:
《少林寺的通話記錄》
老方丈:下午張三豐和滅絕師太要來參觀,你去機(jī)場接一下,我把他倆手機(jī)號給你 //主機(jī)發(fā)送控制信號
小和尚:好的,稍等,我找張紙記一下。
老方丈:嗯。 //主機(jī)等待
小和尚:我準(zhǔn)備好了,您說吧。 //從機(jī)返回Ready信號
老方丈:張三豐的是“123-321-34567”,滅絕師太的是“123-456-56789”。 //主機(jī)突發(fā)傳輸數(shù)據(jù)
小和尚:記下來了。 //從機(jī)返回響應(yīng)信號
上面的通話記錄是一次完整的通信過程,傳輸?shù)男畔⑹莾蓚€(gè)手機(jī)號。我們把“老方丈”當(dāng)成主機(jī),“小和尚”當(dāng)成從機(jī),那么這一通信過程由主機(jī)發(fā)起,最終向從機(jī)寫入兩組數(shù)據(jù)(手機(jī)號)。我們需要注意的是整個(gè)過程中二者的協(xié)調(diào)配合:為了確保數(shù)據(jù)傳輸無誤,主機(jī)需要等從機(jī)準(zhǔn)備好之后才能發(fā)送數(shù)據(jù);另外從機(jī)在接收數(shù)據(jù)完成后,會發(fā)送響應(yīng)信號,表示傳輸完成。
然后再來看另外一個(gè)通話記錄:
《武當(dāng)山的通話記錄》
張三豐:下午我要去趟少林寺,你把方丈的手機(jī)號找給我 //主機(jī)發(fā)送控制信號
小道士:找到了,188-666…… //從機(jī)返回有效數(shù)據(jù)
張三豐:等一下,我找支筆。好了,你說吧 //主機(jī)發(fā)送Ready信號
小道士:188-666-66666,念完了 //從機(jī)返回有效數(shù)據(jù),以及響應(yīng)信號
張三豐:好的。
在武當(dāng)山的通話記錄中,張三豐是主機(jī),小道士是從機(jī)。通信過程同樣是由主機(jī)發(fā)起,向從機(jī)請求數(shù)據(jù)。主機(jī)準(zhǔn)備好之后發(fā)送Ready信號,接下來從機(jī)開始發(fā)送數(shù)據(jù)。從機(jī)在數(shù)據(jù)發(fā)送完成后給出響應(yīng)信號,表明本次傳輸結(jié)束。
對比上述兩個(gè)通話記錄可以發(fā)現(xiàn),少林寺的通話是一次主機(jī)向從機(jī)寫數(shù)據(jù)的過程,而武當(dāng)山的通話則是主機(jī)向從機(jī)讀數(shù)據(jù)的過程。在通信過程中,主從之間會進(jìn)行協(xié)調(diào),只有等接收方準(zhǔn)備好之后,才能開始數(shù)據(jù)傳輸,這種機(jī)制我們稱之為“握手”。
在打電話的時(shí)候,通話雙方能夠理解彼此的語言,進(jìn)而從中篩選有效信息。而在數(shù)字電路中,通信雙方就沒有那么智能了,主設(shè)備和從設(shè)備需要按照約定好的數(shù)據(jù)傳輸方式來發(fā)送和接收數(shù)據(jù)。AXI協(xié)議就是描述了主設(shè)備和從設(shè)備之間的數(shù)據(jù)傳輸方式,在該協(xié)議中,主設(shè)備和從設(shè)備之間通過握手信號建立連接。
AXI協(xié)議是一種高性能、高帶寬、低延遲的片內(nèi)總線,具有如下特點(diǎn):
1、總線的地址/控制和數(shù)據(jù)通道是分離的;
2、支持不對齊的數(shù)據(jù)傳輸;
3、支持突發(fā)傳輸,突發(fā)傳輸過程中只需要首地址;
4、具有分離的讀/寫數(shù)據(jù)通道;
5、支持顯著傳輸訪問和亂序訪問;
6、更加容易進(jìn)行時(shí)序收斂。
在數(shù)字電路中只能傳輸二進(jìn)制數(shù)0和1,因此可能需要一組信號才能高效地傳輸信息,這一組信號就組成了接口。AXI4協(xié)議支持以下三種類型的接口:
1、AXI4:高性能存儲映射接口。
2、AXI4-Lite:簡化版的AXI4接口,用于較少數(shù)據(jù)量的存儲映射通信。
3、AXI4-Stream:用于高速數(shù)據(jù)流傳輸,非存儲映射接口。
在這里我們首先解釋一下存儲映射(Meamory Map)這一概念。如果一個(gè)協(xié)議是存儲映射的,那么主機(jī)所發(fā)出的會話(無論讀或?qū)懀┚蜁?biāo)明一個(gè)地址。這個(gè)地址對應(yīng)于系統(tǒng)存儲空間中的一個(gè)地址,表明是針對該存儲空間的讀寫操作。
AXI4協(xié)議支持突發(fā)傳輸,主要用于處理器訪問存儲器等需要指定地址的高速數(shù)據(jù)傳輸場景。AXI-Lite為外設(shè)提供單個(gè)數(shù)據(jù)傳輸,主要用于訪問一些低速外設(shè)中的寄存器。而AXI-Stream接口則像FIFO一樣,數(shù)據(jù)傳輸時(shí)不需要地址,在主從設(shè)備之間直接連續(xù)讀寫數(shù)據(jù),主要用于如視頻、高速AD、PCIe、DMA接口等需要高速數(shù)據(jù)傳輸?shù)膱龊稀?br> 在本章我們重點(diǎn)介紹AXI4接口,它由五個(gè)獨(dú)立的通道構(gòu)成:
1、讀地址
2、讀數(shù)據(jù)
3、寫地址
4、寫數(shù)據(jù)
5、寫響應(yīng)
下面是使用讀地址和讀數(shù)據(jù)通道實(shí)現(xiàn)讀傳輸過程的示意圖:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.1.1 讀傳輸過程示意圖
從圖 20.1.1中可以看到,在一個(gè)讀傳輸過程中,主機(jī)首先在讀地址通道給出讀地址和控制信號,然后從機(jī)由讀數(shù)據(jù)通道返回讀出的數(shù)據(jù)。另外我們需要注意的是,這是一次突發(fā)讀操作,主機(jī)只給出一個(gè)地址,從該地址連續(xù)突發(fā)讀出四個(gè)數(shù)據(jù)。
寫傳輸過程如圖 20.1.2所示,它用到了寫地址、寫數(shù)據(jù)和寫響應(yīng)三個(gè)通道。主機(jī)在寫地址通道給出寫地址和控制信號,然后在寫數(shù)據(jù)通道連續(xù)突發(fā)寫四個(gè)數(shù)據(jù)。從機(jī)在接收數(shù)據(jù)之后,在寫響應(yīng)通道給出響應(yīng)信號。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.1.2 寫傳輸過程示意圖
AXI總線中的每個(gè)通道都包含了一組信息信號,還有一個(gè)VALID和一個(gè)READY信號。VALID信號由源端(source)產(chǎn)生,表示當(dāng)前地址或者數(shù)據(jù)線上的信息是有效的;而READY信號由目的端(destination)產(chǎn)生,則表示已經(jīng)準(zhǔn)備好接收地址、數(shù)據(jù)以及控制信息。VALID和READY信號提供了AXI總線中的握手機(jī)制,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.1.3 VALID和READY握手機(jī)制
在圖 20.1.3中,ACLK為時(shí)鐘信號,在AXI協(xié)議中,所有的輸入信號都是在ACLK的上升沿采樣,所有的輸出信號必須在ACLK的上升沿之后才能改變。在T1之后,源端將VALID拉高,表明INFORMATION信號線上傳輸?shù)氖怯行У牡刂贰?shù)據(jù)或者控制信息。目的端在T2之后將READY拉高,表明它已經(jīng)準(zhǔn)備好接收數(shù)據(jù),此時(shí)源端必須保持INFORMATION數(shù)據(jù)穩(wěn)定不變,直到T3時(shí)刻進(jìn)行數(shù)據(jù)傳輸。
需要注意的是,源端不允許等目的端的READY信號拉高之后,才將VALID信號置為有效狀態(tài)。而且,一旦VALID拉高,源端必須保持其處于有效狀態(tài),直至成功握手(在時(shí)鐘上升沿檢測到VALID和READY同時(shí)為有效狀態(tài))。
AXI協(xié)議的五個(gè)通道都有各自的VALID/READY握手信號對,每個(gè)通道握手信號對的名稱如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.1.4 各通道握手信號名稱
到這里,我們已經(jīng)簡單介紹了AXI4協(xié)議的讀寫過程,以及握手協(xié)議。關(guān)于如何實(shí)現(xiàn)AXI4通信協(xié)議,以及如何在設(shè)計(jì)中使用該協(xié)議進(jìn)行通信,我們將在硬件設(shè)計(jì)部分進(jìn)行講解。

20.2實(shí)驗(yàn)任務(wù)

本章的實(shí)驗(yàn)任務(wù)是通過自定義一個(gè)AXI4接口的IP核,通過AXI_HP接口對PS端DDR4進(jìn)行讀寫測試。

20.3硬件設(shè)計(jì)

根據(jù)實(shí)驗(yàn)任務(wù)我們可以畫出本次實(shí)驗(yàn)的系統(tǒng)框圖,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.1 系統(tǒng)框圖
在圖 20.3.1中,DDR Test是我們自定義的IP核,具有AXI4 Master端口,該端口通過AXI Smartconnect模塊,最終連接到PS端的Slave AXI_HP端口。輸入的按鍵控制DDR Test模塊對PS的DDR4進(jìn)行讀寫測試,并在讀寫測試結(jié)束后,通過兩個(gè)PL LED燈分別指示讀寫完成和讀寫錯誤。需要說明的是,DDR Test模塊通過輸入信號的上升沿作為對DDR4讀寫測試的觸發(fā)信號,需要對輸入的按鍵信號進(jìn)行消抖,否則會導(dǎo)致讀寫錯誤。
首先創(chuàng)建Vivado工程,工程名為“axi4_ddr_rw”,然后創(chuàng)建Block Design設(shè)計(jì)(design_1.bd)并添加Zynq UltraScale+ MPSOC模塊。接下來按照《“Hello World”實(shí)驗(yàn)》中的步驟2-7、2-8分別配置PS的UART和DDR控制器。需要特別注意的是,我們在《“Hello World”實(shí)驗(yàn)》的步驟2-10中,移除了PS中與PL端交互的接口信號,在我們本次實(shí)驗(yàn)中要保留時(shí)鐘“PL Fabric Clocks”和復(fù)位“Fabric Reset Enable”信號。
由于本次實(shí)驗(yàn)用到了PS端的HP接口,因此在Zynq UltraScale+ MPSOC模塊的配置界面左側(cè)點(diǎn)擊“PS-PL Configuration”標(biāo)簽,然后依次展開右側(cè)界面中PS-PL Interfaces-> Slave Interface->AXI HP,勾選“AXI HP0 FPD”,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.2 PS-PL接口配置
最后點(diǎn)擊右下角的“OK”,本次實(shí)驗(yàn)Zynq UltraScale+ MPSOC模塊就配置完成了。
Zynq UltraScale+ MPSOC模塊配置完成后其接口如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.3 Zynq UltraScale+ MPSOC模塊接口
在圖 20.3.3中,S_AXI_HP0_FPD是PS端的AXI高性能接口,它是一個(gè)從接口,連接到PS內(nèi)的存儲器互聯(lián),用于PL訪問PS內(nèi)的存儲設(shè)備,包括OCM和DDR。
在本次實(shí)驗(yàn)中,PS內(nèi)的數(shù)據(jù)通路如圖 20.3.4所示。我們在PL內(nèi)自定義的DDR Test IP核作為主設(shè)備,通過PS Slave AXI_HP0接口,與DDR控制器進(jìn)行通信,最終對DDR4存儲器進(jìn)行讀寫操作。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.4 PS內(nèi)的數(shù)據(jù)通路
接下來我們要在Block Design中添加PL端的自定義IP核。
在添加該IP之前,我們需要先自定義一個(gè)帶有AXI4 Master端口的IP核,并將其添加到工程的IP庫中。我們在《自定義IP核-呼吸燈實(shí)驗(yàn)》中介紹了如何定義一個(gè)帶有AXI-Lite Slave接口的IP核,在本次實(shí)驗(yàn)中定義IP的方法與之相同,只是這次我們要選擇AXI4 Master接口。
在菜單欄中點(diǎn)擊“Tools”,然后在下拉列表中選擇“Create and Package New IP”,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.5 創(chuàng)建IP
在彈出的對話框中直接點(diǎn)擊“Next”,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.6 創(chuàng)建和封裝IP
在下圖所示的界面中選擇“Create a new AXI4 peripheral”,點(diǎn)擊“Next”:

接下來設(shè)置IP核的名稱為“axi4_rw_test”,并將IP的路徑修改為當(dāng)前工程路徑下的“ip_repo”文件夾,最后點(diǎn)擊“Next”,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.7 設(shè)置IP名稱和路徑
在“Add Interfaces”界面中修改接口名稱為“M_AXI”,選擇接口類型為“Full”,接口模式為“Master”,數(shù)據(jù)位寬為“32”。如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.8 自定義IP核接口配置
圖 20.3.8中對IP核接口的配置與《自定義IP核——呼吸燈實(shí)驗(yàn)》不同,在這里我們新建的IP核作為主機(jī)(Master),除此之外我們使用的接口類型變成了AXI-Full,而不再是AXI-Lite。
設(shè)置完成后點(diǎn)擊上圖中右下角的“Next”。
接下來在圖 20.3.9中選擇“Edit IP”,最后點(diǎn)擊“Finish”,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.9 創(chuàng)建外設(shè)
在上圖中點(diǎn)擊“Finish”后會自動打開一個(gè)新的Vivado工程,工程名為“edit_ axi4_rw_test_v1_0”,如圖 20.3.10所示。我們可以在這個(gè)工程中對創(chuàng)建的IP核——AXI4_RW_TEST進(jìn)行編輯。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.10 Edit IP工程
AXI4接口共有五個(gè)獨(dú)立的通道,每個(gè)通道又有少則幾個(gè),多則十幾個(gè)信號,如果讓我們自己來實(shí)現(xiàn)這樣一個(gè)接口還是比較復(fù)雜的。不過大家不用擔(dān)心,我們在圖 20.3.8中創(chuàng)建AXI4接口的IP時(shí),Vivado提供的IP封裝工具已經(jīng)自動幫我們實(shí)現(xiàn)了這樣一個(gè)接口,并提供了一個(gè)示例程序。
在圖 20.3.10中,箭頭所指示的文件實(shí)現(xiàn)了AXI4協(xié)議下的讀寫測試模塊,我們甚至都不用對代碼作任何修改,即可實(shí)現(xiàn)對DDR的讀寫測試功能。雖然該模塊的代碼看上去比較長(900多行),但是大多是一些注釋,非常詳盡。大家可以通過閱讀代碼及注釋,來學(xué)習(xí)AXI4協(xié)議主機(jī)的實(shí)現(xiàn)方式。
在這里我們只貼出部分代碼:

735       //implement master command interface state machine                                                        
736                                                                                                                 
737       always @ ( posedge M_AXI_ACLK)                                                                            
738       begin                                                                                                     
739         if (M_AXI_ARESETN == 1'b0 )                                                                             
740           begin                                                                                                 
741             // reset condition                                                                                  
742             // All the signals are assigned default values under reset condition                                
743             mst_exec_state      <= IDLE;                                                                
744             start_single_burst_write <= 1'b0;                                                                   
745             start_single_burst_read  <= 1'b0;                                                                   
746             compare_done      <= 1'b0;                                                                          
747             ERROR <= 1'b0;   
748           end                                                                                                   
749         else                                                                                                    
750           begin                                                                                                 
751                                                                                                                 
752             // state transition                                                                                 
753             case (mst_exec_state)                                                                               
754                                                                                                                 
755               IDLE:                                                                                     
756                 // This state is responsible to wait for user defined C_M_START_COUNT                           
757                 // number of clock cycles.                                                                      
758                 if ( init_txn_pulse == 1'b1)                                                      
759                   begin                                                                                         
760                     mst_exec_state  <= INIT_WRITE;                                                              
761                     ERROR <= 1'b0;
762                     compare_done <= 1'b0;
763                   end                                                                                           
764                 else                                                                                            
765                   begin                                                                                         
766                     mst_exec_state  <= IDLE;                                                            
767                   end                                                                                           
768                                                                                                                 
769               INIT_WRITE:                                                                                       
770                 // This state is responsible to issue start_single_write pulse to                               
771                 // initiate a write transaction. Write transactions will be                                     
772                 // issued until burst_write_active signal is asserted.                                          
773                 // write controller                                                                             
774                 if (writes_done)                                                                                
775                   begin                                                                                         
776                     mst_exec_state <= INIT_READ;                                                              
777                   end                                                                                           
778                 else                                                                                            
779                   begin                                                                                         
780                     mst_exec_state  <= INIT_WRITE;                                                              
781                                                                                                                 
782                     if (~axi_awvalid && ~start_single_burst_write && ~burst_write_active)                       
783                       begin                                                                                     
784                         start_single_burst_write <= 1'b1;                                                       
785                       end                                                                                       
786                     else                                                                                        
787                       begin                                                                                     
788                         start_single_burst_write <= 1'b0; //Negate to generate a pulse                          
789                       end                                                                                       
790                   end                                                                                           
791                                                                                                                 
792               INIT_READ:                                                                                        
793                 // This state is responsible to issue start_single_read pulse to                                
794                 // initiate a read transaction. Read transactions will be                                       
795                 // issued until burst_read_active signal is asserted.                                           
796                 // read controller                                                                              
797                 if (reads_done)                                                                                 
798                   begin                                                                                         
799                     mst_exec_state <= INIT_COMPARE;                                                             
800                   end                                                                                           
801                 else                                                                                            
802                   begin                                                                                         
803                     mst_exec_state  <= INIT_READ;                                                               
804                                                                                                                 
805                     if (~axi_arvalid && ~burst_read_active && ~start_single_burst_read)                         
806                       begin                                                                                     
807                         start_single_burst_read <= 1'b1;                                                        
808                       end                                                                                       
809                    else                                                                                         
810                      begin                                                                                      
811                        start_single_burst_read <= 1'b0; //Negate to generate a pulse                            
812                      end                                                                                        
813                   end                                                                                           
814                                                                                                                 
815               INIT_COMPARE:                                                                                     
816                 // This state is responsible to issue the state of comparison                                   
817                 // of written data with the read data. If no error flags are set,                               
818                 // compare_done signal will be asseted to indicate success.                                     
819                 //if (~error_reg)                                                                               
820                 begin                                                                                           
821                   ERROR <= error_reg;
822                   mst_exec_state <= IDLE;                                                               
823                   compare_done <= 1'b1;                                                                         
824                 end                                                                                             
825               default :                                                                                         
826                 begin                                                                                           
827                   mst_exec_state  <= IDLE;                                                              
828                 end                                                                                             
829             endcase                                                                                             
830           end                                                                                                   
831       end //MASTER_EXECUTION_PROC

上面的代碼實(shí)現(xiàn)了一個(gè)狀態(tài)機(jī),其狀態(tài)轉(zhuǎn)換圖如下所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.11 狀態(tài)轉(zhuǎn)換圖
系統(tǒng)復(fù)位后,狀態(tài)機(jī)處于初始狀態(tài),在該狀態(tài)下等待外部輸入的啟動傳輸脈沖init_txn_pulse。一旦檢測到init_txn_pulse為高電平,狀態(tài)機(jī)跳轉(zhuǎn)到INIT_WRITE狀態(tài)。
在INIT_WRITE狀態(tài)下,狀態(tài)機(jī)拉高start_single_burst_write信號,來不斷地啟動AXI4 Master接口對Slave端大小為4KB的存儲空間進(jìn)行突發(fā)寫操作。寫操作完成后,write_done信號會拉高,狀態(tài)機(jī)進(jìn)入INIT_READ狀態(tài)。
在INIT_READ狀態(tài)下,狀態(tài)機(jī)拉高start_single_burst_read信號,不斷地啟動AXI4 Master接口對Slave端同一存儲空間進(jìn)行突發(fā)讀操作,同時(shí)將讀出的數(shù)據(jù)與寫入的數(shù)據(jù)進(jìn)行對比。讀操作完成后,read_done信號拉高,狀態(tài)機(jī)進(jìn)入INIT_COMPARE狀態(tài)。
在INIT_COMPARE狀態(tài)下,判斷AXI4接口在讀寫過程中的是否發(fā)生錯誤,并將錯誤狀態(tài)賦值給ERROR信號,然后將compare_done信號拉高,表示一次讀寫測試完成。最后跳轉(zhuǎn)到IDLE狀態(tài),等待下一次讀寫操作的啟動信號。
我們在查看了圖 20.3.10中箭頭所指示的IP核源碼后,不需要再對IP作任何修改,直接關(guān)閉名為edit_AXI4_RW_TEST_v1_0的工程。最終我們創(chuàng)建的IP核將通過AXI4 Master端口向Slave端指定的4K存儲空間中連續(xù)寫入1024個(gè)數(shù)據(jù),寫入的數(shù)值從1累加到1024,每個(gè)數(shù)據(jù)占32bit。
IP核創(chuàng)建完成后,我們在工程目錄下的ip_repo文件夾中可以找到IP相關(guān)的文件,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.12 IP核相關(guān)的文件
需要注意的是,在圖 20.3.12中我們只需要保留紅色方框中的文件夾即可,其余文件及文件夾是用于對IP進(jìn)行編輯的工程文件,我們可以直接刪除。
回到axi4_ddr_rw工程界面,在左側(cè)“Flow Navigator”一欄點(diǎn)擊“IP Catalog”,然后在右側(cè)的IP目錄中可以看到我們前面所創(chuàng)建的IP核——AXI4_RW_TEST,該IP已經(jīng)自動添加到了當(dāng)前工程的IP庫中。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.13 IP目錄
接下來在Diagram窗口中給設(shè)計(jì)添加自定義的IP核AXI4_RW_TEST,添加完成后如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.14 添加AXI4_RW_TEST IP核
在圖 20.3.14中,M_AXI是AXI-Full類型的主機(jī)接口,我們將通過這個(gè)接口對PS端的DDR4進(jìn)行讀寫操作。AXI4_RW_TEST IP核在檢測到m_axi_init_axi_txn端口的上升沿后會啟動讀寫過程,并將讀出的數(shù)據(jù)與寫入的數(shù)據(jù)作比較,比較完成后m_axi_txn_done輸出高電平。另外,在比較完成后,m_axi_error信號會指示整個(gè)過程是否出錯。如果在讀寫過程中出錯,或者在比較的過程中發(fā)現(xiàn)讀出的數(shù)據(jù)與寫入的數(shù)據(jù)不一致,那么m_axi_error將會拉高。
添加完自定義IP核之后,雙擊該IP核對其進(jìn)行配置,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.15 配置AXI4_RW_TEST IP核
在圖 20.3.15中,我們將變量C M AXI TARGET SLAVE BASE ADDR的值修改為0x1000_0000,它位于DDR4存儲器的地址空間,是AXI4_RW_TEST IP核進(jìn)行讀寫操作的起始地址。我們將該地址之前的存儲空間預(yù)留下來,用于運(yùn)行PS中的軟件程序。
接下來,我們還要添加Utility Vector Logic IP核。然后將其配置成非門,位寬為1,作為反向器使用,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.16 Utility Vector Logic IP核設(shè)置
這是因?yàn)槲覀冃枰褂肞L端的按鍵來作為AXI4_RW_TEST IP核的啟動信號,MPSOC開發(fā)板上的按鍵在按下的時(shí)候?yàn)榈碗娖?,因此我們通過添加一個(gè)反向器,將其修改為按下時(shí)輸出高電平。
接下來為按鍵添加消抖模塊,用于消除按鍵的抖動。添加的方法是先將《MPSOC之FPGA開發(fā)指南》中“按鍵控制蜂鳴器”里的按鍵消抖模塊(key_debounce.v)添加至工程,然后再添加至框圖設(shè)計(jì)中即可。下面開始具體操作,我們在工程目錄.\axi4_ddr_rw\axi4_ddr_rw.srcs\sources_1下創(chuàng)建一個(gè)文件夾new,將key_debounce.v拷貝至new文件夾下,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.17 key_debounce路徑
接下來將key_debounce.v模塊添加至工程中,右擊Design Sources下的design_1(design_1.bd),選擇“Add Sources…”,如下圖所示。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.18 添加源文件
在彈出的頁面中選擇第二個(gè)“Add or create design sources”,點(diǎn)擊“NEXT”。
然后點(diǎn)擊頁面中的“Add Files”,在彈出的頁面中選擇“key_debounce.v”,如下圖所示。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.19 添加“key_debounce.v”
最后點(diǎn)擊“Finish”完成代碼的添加,如下圖所示。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.20 點(diǎn)擊“Finish”
此時(shí)在Design Sources界面下,可以看到剛剛添加的文件,如下圖所示。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.21 添加完成界面
接下來在Diagram界面空白處右擊,選擇“Add Module…”,如下圖所示。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.22 點(diǎn)擊“Add Module”
此時(shí)會彈出工程中添加的.v文件,將key_debounce.v添加進(jìn)來,如下圖所示。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.23 添加“key_debounce.v”至BD中
需要說明的是,如果上圖的界面中,沒有出現(xiàn)按鍵消抖模塊,可能是軟件界面還沒有更新剛剛添加的設(shè)計(jì)文件,可以稍作等待后再添加,添加完成后如下圖所示。
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.24 消抖模塊成功添加至BD界面中
IP核添加完成后,使用工具的自動連接功能,對設(shè)計(jì)進(jìn)行連線,連線后如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.25 自動連接
以上是使用Vivado軟件的自動連線,接下來還需要手動進(jìn)行消抖模塊、反向器、AXI4_RW_TEST IP核之間的連接。連接完成后,在Diagram窗口空白處右擊,然后選擇“Regenerate Layout”對設(shè)計(jì)進(jìn)行重新布局,布局后的界面如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.3.26 重新布局后的設(shè)計(jì)界面
從上圖中可以看到,在執(zhí)行了自動連接之后,工具自動添加了兩個(gè)IP核,分別是AXI智能互聯(lián)(AXI Smartconnect)和處理器系統(tǒng)復(fù)位(Processor System Reseet)。接下來需要將消抖模塊key端口引出,用于連接開發(fā)板PL端按鍵,并重命名為key_int,命名方法參考AXI GPIO按鍵LED實(shí)驗(yàn);還需要將AXI4讀寫測試模塊的m_axi_txn_done和m_axi_error兩個(gè)端口引出,用于連接PL端LED燈,并分別重命名為compare_done和error_flag,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖20.3.27 引出管腳
圖20.3.27中橙色的連線標(biāo)注出了本設(shè)計(jì)中AXI4總線的連接,其中AXI4_RW_TEST IP核的M_AXI作為主機(jī)接口,Zynq UltraScale+ MPSOC的S_AXI_HP0_FPD為從機(jī)接口,中間經(jīng)過了AXI Smartconnect。AXI Smartconnect的功能與AXI Interconnect IP核類似,都是用于將AXI存儲器映射的主器件連接到存儲器映射的從器件。
到這里我們的Block Design就設(shè)計(jì)完成了,在Diagram窗口空白處右擊,然后選擇“Validate Design”驗(yàn)證設(shè)計(jì)。驗(yàn)證完成后彈出對話框提示“Validation Successful”表明設(shè)計(jì)無誤,點(diǎn)擊“OK”確認(rèn)。最后按快捷鍵“Ctrl + S”保存設(shè)計(jì)。
接下來在Source窗口中右鍵點(diǎn)擊Block Design設(shè)計(jì)文件“design_1.bd”,然后依次執(zhí)行“Generate Output Products”和“Create HDL Wrapper”。
在左側(cè)Flow Navigator導(dǎo)航欄中找到RTL ANALYSIS,點(diǎn)擊該選項(xiàng)中的“Open Elaborated Design”,在彈出的窗口中點(diǎn)擊“OK”?;蛘咴诓藛螜谥悬c(diǎn)擊 Layout,在下拉列表中選擇I/O Planning以打開I/O Ports窗口。我們將在 I/O Ports 窗口中對key_init等接口進(jìn)行管腳分配,如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖20.3.28 管腳分配
在圖20.3.28中,我們將key_init分配到了AD11引腳上,該引腳最終與MPSOC開發(fā)板上的按鍵PL_KEY0相連接;compare_done和error_flag分別連接到開發(fā)板上的LED:PL_LED0和PL_LED1。管腳分配完成后按快捷鍵Ctrl+S保存管腳約束,并在彈出的保存約束窗口中輸入文件名“axi4_ddr_rw”。
最后在左側(cè)Flow Navigator導(dǎo)航欄中找到PROGRAM AND DEBUG,點(diǎn)擊該選項(xiàng)中的“Generate Bitstream”,對設(shè)計(jì)進(jìn)行綜合、實(shí)現(xiàn)、并生成Bitstream文件。
在生成Bitstream之后,在菜單欄中選擇 File > Export > Export hardware導(dǎo)出硬件,并在彈出的對話框中,勾選“Include bitstream”。將導(dǎo)出的“design_1_wrapper.xsa”文件放到vitis文件夾,然后在菜單欄選擇File > Launch Vitis,啟動VITIS軟件。
20.4軟件設(shè)計(jì)
在VITIS軟件中新建一個(gè)空的應(yīng)用工程,應(yīng)用工程名為“axi4_ddr_rw”。然后為應(yīng)用工程新建一個(gè)源文件“main.c”,我們在新建的main.c文件中輸入本次實(shí)驗(yàn)的代碼:

1  #include "stdio.h"
2  #include "xil_cache.h"
3  #include "xil_printf.h"
4  #include "xil_io.h"
5  
6  int main()
7  {
8   int i;
9   char c;
10 
11  Xil_DCacheDisable();
12  printf("AXI4 PL DDR TEST!\n\r");
13 
14  while(1)
15  {
16      scanf("%c",&c);
17      if(c == 'c'){
18          printf("start\r\n");
19          for(i=0;i<4096;i=i+4)
20          {
21              printf("%d is %d\n",i,(int)(Xil_In32(0x10000000+i)));
22          }
23      }
24  }
25  return 0;
26 }

可以看出,我們的軟件程序特別簡單。在代碼的第14行至24行,通過一個(gè)while(1)死循環(huán),連續(xù)判斷用戶輸入的字符。當(dāng)輸入字符“c”時(shí),程序通過一個(gè)for循環(huán)開始從地址0x1000_0000讀取DDR存儲器中的數(shù)據(jù),讀取的存儲空間大小為4KB。需要注意的是,變量i每次累加4,這是因?yàn)槲覀冋{(diào)用了函數(shù)Xil_In32( )來讀取內(nèi)存數(shù)據(jù),每次讀取32bit。而內(nèi)存地址是以字節(jié)(1字節(jié)==8bit)為單位的,那么操作完成后地址應(yīng)該累加4。
可以看出,我們在軟件中讀取的內(nèi)存地址與硬件設(shè)計(jì)過程中DDR Test IP核所寫入的地址是一致的。我們將軟件讀出的數(shù)據(jù)通過串口打印出來,與DDR Test IP核寫入的數(shù)據(jù)進(jìn)行對比,即可驗(yàn)證我們通過AXI4接口對DDR進(jìn)行的讀寫操作是否成功。
另外,在代碼的第11行,我們通過調(diào)用函數(shù)Xil_DCacheDisable( )來關(guān)閉數(shù)據(jù)緩存(Data Cache),以避免從緩存中讀取數(shù)據(jù)。這是因?yàn)樵趯ν坏刂愤M(jìn)行讀操作時(shí),讀出的有可能是Data Cache中緩存的數(shù)據(jù),而不是DDR中真正的數(shù)據(jù)。
20.5下載驗(yàn)證
首先我們將下載器與開發(fā)板上的JTAG接口連接,下載器另外一端與電腦連接。然后使用USB連接線將USB_UART(開發(fā)板PS PORT)接口與電腦連接,用于串口通信。最后連接開發(fā)板的電源,給開發(fā)板上電。
打開Vitis Terminal終端,設(shè)置并連接串口。然后下載本次實(shí)驗(yàn)的程序,下載完成后,在下方的Vitis Terminal中可以看到應(yīng)用程序打印的信息“AXI4 PL DDR TEST!”。
然后在Vitis Terminal窗口中輸入字符“c”,然后按回車鍵發(fā)送。程序會打印從DDR中讀出的數(shù)據(jù),如下圖所示:

mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.5.1 第一次從DDR4中讀出的數(shù)據(jù)
如圖 20.5.1所示,串口打印出了DDR存儲空間中從地址0x1000_0000開始的1024個(gè)數(shù)據(jù),每個(gè)數(shù)據(jù)占4個(gè)字節(jié)。從圖中可以看出,開發(fā)板上電后,在沒對該地址空間進(jìn)行寫操作之前,DDR中的數(shù)據(jù)是隨機(jī)的。
我們按下開發(fā)板上的按鍵PL_KEY1然后釋放,該動作會啟動AXI4_RW_TEST IP核對DDR的讀寫操作。然后開發(fā)板上的PL_LED1會點(diǎn)亮,表示讀寫操作完成。如下圖所示:
mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.5.2 MPSOC開發(fā)板實(shí)物圖
在圖 20.5.2中,如果旁邊的PL_LED2也點(diǎn)亮了,這表明在對DDR進(jìn)行讀寫操作過程中出現(xiàn)了錯誤。但是這個(gè)錯誤指示燈點(diǎn)亮的原因并不唯一,通過分析AXI4_RW_TEST IP核的源碼可以看出,在AXI4通信過程中寫響應(yīng)出錯、讀響應(yīng)出錯、以及讀出與寫入的數(shù)據(jù)不一致均會導(dǎo)致錯誤指示燈點(diǎn)亮。
筆者最早在實(shí)現(xiàn)本次實(shí)驗(yàn)功能的時(shí)候,旁邊的PL_LED2偶爾也會亮,是由于沒有對按鍵進(jìn)行消抖處理所致,添加按鍵消抖模塊后,沒有再出現(xiàn)讀寫錯誤的情況。
在Vitis Terminal窗口中重新輸入字符“c”并發(fā)送,程序會再次打印從DDR中讀出的數(shù)據(jù),如下圖所示:

mpsoc驅(qū)動axilite讀寫,正點(diǎn)原子,fpga開發(fā)

圖 20.5.3 第二次從DDR4中讀出的數(shù)據(jù)
從圖 20.5.3中可以看出,PS端軟件從DDR中指定的4KB存儲空間中讀出的數(shù)據(jù)依次為1到1024,與AXI4_RW_TEST IP核寫入的數(shù)據(jù)一致,說明本次實(shí)驗(yàn)在MPSOC開發(fā)板上面下載驗(yàn)證成功。文章來源地址http://www.zghlxwxcb.cn/news/detail-784531.html

到了這里,關(guān)于【正點(diǎn)原子FPGA連載】第二十章AXI4接口之DDR讀寫實(shí)驗(yàn) 摘自【正點(diǎn)原子】DFZU2EG_4EV MPSoC之嵌入式Vitis開發(fā)指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包