ZYNQ_PL與PS的DDR交互詳解
掃描二維碼
隨時隨地手機(jī)看文章
ZYNQ7000系列中PS端與PL端的通信都是通過AXI總線進(jìn)行連接的,利用好AXI協(xié)議是PS與PL交互的基礎(chǔ),因此設(shè)計這個實(shí)驗(yàn)來進(jìn)一步了解兩者間的通信。
1.實(shí)驗(yàn)?zāi)康?
PL端通過AXI協(xié)議訪問PS端的DDR內(nèi)存,其中包括往DDR寫數(shù)據(jù),以及讀取DDR內(nèi)部的數(shù)據(jù)。
2.如何實(shí)現(xiàn)
看起來實(shí)驗(yàn)?zāi)康暮芎唵危菍τ谙裎疫@樣的初學(xué)者而言那還是有很多的問題的。例如:
1.芯片內(nèi)部硬件怎么連接(好比兩個人打電話,總得知道電話號碼才能交流)
2.誰是主機(jī)誰是從機(jī)(好比兩個人打電話,誰打給誰)
3.什么時候發(fā)數(shù)據(jù),什么時候讀數(shù)據(jù),總不能在別人還沒存好數(shù)據(jù)的時候讀吧(比如兩個人打電話,一個人在睡覺,怎么都打不通吧)
3.設(shè)計思路
針對上述3個問題,來設(shè)計總的思路,這樣能有條理的實(shí)現(xiàn)總體的功能。
4.芯片內(nèi)部硬件連接
ZYNQ中有9個AXI總線(如圖 1),其中包含4個General-Purpose Ports(AXI_GP),主要是一些常用的通信,位寬為32位,4個High-Performance Ports,高速的通信,位寬為64位,還有一個AXI_AXP這個我不太了解,不過位寬也是64位。
從圖 2中可以看出訪問DDR3的接口有三條①、②、③條接口,其中PL的訪問有兩條,分別為①和③,為了簡單我們選個③,如果有興趣可以使用③來寫,①來讀的操作,這樣能更好的理解兩者間的交互。
5.從機(jī)與主機(jī)
這個簡單的理解就是圖 2中的箭頭,箭頭連接的一段為從機(jī),沒有連接的一段為主。例如AXI_HP接口,主機(jī)就是PL,而箭頭連接的一段是PS,那么PS就是從機(jī)。
6.讀寫時序的控制
主要的問題集中于PL什么時候?qū)憯?shù)據(jù);PL什么時候讀數(shù)據(jù)。簡單的一種控制就是PL自己控制,例如先寫5個數(shù)據(jù),在讀5個數(shù)據(jù),為了增加點(diǎn)難度,我們可以這樣設(shè)計,用PS來通知PL什么時候?qū)?,什么時候讀。那么又涉及到了兩者的通信,而這種通信就比較普通,不是內(nèi)存的控制,具有普適化的意義,這里使用AXI_GP來進(jìn)行通信,以PS為主機(jī)。
注:PS發(fā)數(shù)據(jù)是走紅色的路還是藍(lán)色的路是由其地址決定的

圖 3 PS發(fā)命令的端口
7.總結(jié)
最后我們使用AXI_GP接口來控制讀寫,其中PS為主機(jī);用AXI_HP接口來進(jìn)行DDR3數(shù)據(jù)的輸入與輸出,這時PL為主機(jī)。
8.程序設(shè)計流程圖
流程圖包含PS部分和PL部分。
9.PS部分流程設(shè)計
PS端的程序,我們采用輪訓(xùn)的方式進(jìn)行讀寫命令完成的獲取,也就是PS端不停地讀取PL端是否寫完,以及是否讀完的命令。后續(xù)可以拓展為采用中斷的方式進(jìn)行讀寫控制。
圖 4 PS端流程圖
10.PL部分流程設(shè)計
PL端AXI_HP的流程如圖 4所示,一個簡單的狀態(tài)機(jī)來完成數(shù)據(jù)的讀寫,此時PL為主機(jī)。
圖 5 PL端AXI_HP的狀態(tài)機(jī)
PL端AXI_GP的流程圖如所示,也是一個簡單的狀態(tài)機(jī),但是此時PL是從機(jī),PS是主機(jī),PS發(fā)出讀?。ㄊ欠駥懲昊蛘呤欠褡x?。┑臓顟B(tài),PL將此時的狀態(tài)返回給PS端,讓PS來進(jìn)行判斷是否需要進(jìn)行下一步操作。
圖 6 PL端AXI_GP的狀態(tài)機(jī)
11.程序設(shè)計
首先,設(shè)計FPGA端的程序。有幾個注意點(diǎn):
-
PL端的邏輯一般都是先仿真,然后進(jìn)行板級調(diào)試,如果仿真沒過,那么下載到板子上肯定不過(仿真很重要)。
-
ZYNQ-7000的AXI協(xié)議不是和ARM一樣嚴(yán)格遵守的,有些端口是沒有用到的如圖 7,但是響應(yīng)這些一定要按協(xié)議來。
這里可以簡單的想一下,PS端的DDR怎么能用PL來仿真呢?我能想到的解決方法有2個(歡迎提供更多的方法):
-
在PL端利用ddr的ip核選擇AXI模式進(jìn)行仿真,操作比較麻煩,同時仿真時間長,但是參考價值高
-
就在PL端用一個帶AXI4總線的bram進(jìn)行仿真,比較簡單,但是參考價值低
為了偷懶,我這邊就用方法2來仿真。這個IP中有些端口也是沒有用到的
圖 7 axi_bram s_axi_awlock端口
根據(jù)4.2中的流程圖,以及5中的分析,自己編寫axi協(xié)議后,得到仿真圖如圖 8 AXI_HP的仿真,采用AXI INCR突發(fā)模式,突發(fā)大小為8個字節(jié),突發(fā)長度為2。突發(fā)的地址是根據(jù)ZYNQ中的硬件地址來的如圖 9,采用32’h0008_0000為起始地址(仿真的起始地址是0)。
圖 8 PL端的AXI_HP仿真圖
那么往ddr3寫數(shù)據(jù)的地址應(yīng)該怎么確定呢?圖 9中可以看到AXI_HP可以用的地址,我用的起始地址是32’h0008_0000。
圖 9 PS的地址映射
這里有個問題可以想一下,PS端的程序也是跑在DDR3里面的,那么怎么才能使得PL端訪問的地址與程序跑的地址不沖突呢?(這個可以在評論中給點(diǎn)意見)
我這里的解決方案有兩個:
-
簡單的就是寫的地址與程序的地址不一樣就好了
-
就是在PS端分配好內(nèi)存用來寫ddr,然后將這個地址的起始地址發(fā)給PL,這樣肯定不會有沖突(也許xilinx dma那個ip核就是這么干的吧)
同樣為了偷懶,我采用第一個方法,那么怎么知道程序跑的地址呢?
在SDK的工程里面有個lscript.ld里面有許多地址的信息如圖 10,圖 11。可以看到這邊的地址是從100000開始的,所以我用的地址不在這里。
圖 10
圖 11
12.程序驗(yàn)證結(jié)果
因?yàn)槭煜ち艘稽c(diǎn)AXI協(xié)議,就自己寫了個AXI通信的模塊,然后實(shí)現(xiàn)了PL與ddr的通信,以及PL與PS的通信。
本來用黑金zynq7020的板子驗(yàn)證的,結(jié)果電源模塊壞了,找客服修說過保了,就不能修了,哎,好可惜。。。。。。。。。。。應(yīng)該是二極管擊穿導(dǎo)致的。
于是接了個ZCU102的開發(fā)板來測試這個程序,不過原理都是一樣,只是代碼上的地址可能要改一下。
寫數(shù)據(jù)結(jié)果如圖 12
讀數(shù)據(jù)結(jié)果如圖 13
圖 13 讀數(shù)據(jù)
上述讀寫的結(jié)果一致,完成了本次實(shí)驗(yàn),這次實(shí)驗(yàn)中最重要的部分就是對AXI協(xié)議的理解。
參考資料
-
xilinx.com/support/docu ug585 zynq7000的說明書
-
xilinx.com/support/answ 解決時鐘分配報錯
-
china.xilinx.com/suppor xilinx axi協(xié)議
-
static.docs.arm.com/ihi arm axi協(xié)議
附錄
Block Design如圖 14 這個是ZCU102的,如果是zynq-7000.只要把中間的換了就好。
圖 14 Block Design





