zedboard如何從PL端控制DDR讀寫(五)


  有了前面的一堆鋪墊。現在終於開始正式准備讀寫DDR了,開發環境:VIVADO2014.2 + SDK。

 

  一、首先要想在PL端通過AXI去控制DDR,我們必須要有一個AXI master,由於是測試,就不自己寫了,直接用package IP生成,方法如下:

  1.選擇package IP工具

  

  2.創建新的AXI外設

  

  3.接口類型選擇Full,模式選擇master,如果你不關心里面的詳細實現過程,那么直接finish就好了。(后面我們會繼續分析里面的過程)

  

  

  二、創建好了IP,自然要加入到IP庫里,如圖,在IP Catalog空白處右鍵,設置,把剛剛生成IP的路徑放進去:

  

 

  三、接下來創建BD塊,把整個硬件系統搭建好:

  

  需要指出的是,由於我們需要用到HP,所以在zynq的配置里面把HP勾選上,任選一個通道就行

  

 

   四、然后校驗正確性,產生輸出文件,創建BD塊頂層,這都是套路,一路走下來就行。如果你想在調試里看到產生的AXI信號,那么需要對AXI標記一下debug

   

 

   五、綜合,set up debug,然后生成比特流,並將其導入到SDK;在SDK里跑個hello world 就行,主要目的是用CPU去把DDR控制器初始化。

 

  到這里整個過程基本就結束了,接下來看仿真波形:

  

   放大一點,可以看到每次地址的步進長度是十進制的64,這是因為我們的突發長度設置的是16,位寬為32bit。

   

  但是問題來了,我們在上一節里面說過,有一部分地址是連到了OCM的,那么這一部分地址是多少呢?UG585里給出了如下說明:

  

  我們是從全0地址開始寫數據的,然而全0的地址剛好分配到了OCM,這TM就很尷尬了。一開始想讓程序運行的時間長一點,這樣地址是不是就可以跑到0x0008_0000了?然而並沒有什么用,因為地址只跑到00001000就停止了,如圖:

  

  還記得前面打包AXI IP時候我們說過要分析其過程嗎?其實那里就已經挖了一個坑了,具體見代碼:

   

  這是AXI的寫數據狀態機,(可以看到,官方也是用一段式狀態機來實現整個時序的,印證了前面三段式狀態機不好實現的說法),從寫狀態到讀狀態的跳變是由writes_done信號來控制的,那么這個writes_done又是怎么產生的呢?繼續看代碼:

  

  writes_done是由write_burst_counter的高位進位來控制的,再繼續找write_burst_counter:

  

  在這個計數器里有一個很關鍵的位C_NO_BURSTS_REQ ,在代碼的低179行,它的定義如下:

localparam integer C_NO_BURSTS_REQ = C_MASTER_LENGTH-clogb2((C_M_AXI_BURST_LEN*C_M_AXI_DATA_WIDTH/8)-1);

  

  C_M_AXI_BURST_LEN我們設置的是16,C_M_AXI_DATA_WIDTH是32,clogb2可以理解為計算以2為底的某個數的對數,那么最后得到的C_NO_BURSTS_REQ = 6;也就是說write_burst_counter的位寬是7為,當最高位為1時,寫數據停止。也就是只會發生64次寫數據,之后計數器和寫地址就會歸零。那么64次寫數據乘以每次突發長度16再乘以位寬4個字節,最后得到的數值是4096,換算成16進制剛好是0x00001000。
  所以要想真正的往DDR里面寫數據,我們還需要對代碼進行修改。
  到這里離成功就已經不遠了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM