最近在調試這個讀的過程,現將調試過程中的問題記錄一下。
1.測試目標:通過NIOS直接操作內存,然后在verilog中讀取數據流,保證讀取和寫的一致。
通過上述c程序對內存賦值,然后通過該IP讀取內存中的數據,假設從內存的一半開始讀取,這里為了方便計算以及對比,我將數據從1開始賦值。
地址定義如下:
在NIOS中,需要將最高位置1,從而避免訪問cache,二來需要注意的是,操作時地址是:內存的大小/2 + 內存分配的基地址。
2.在qsys中調用該IP,然后頂層例化如下:
這里我用的1G bit的ddr2,相當於128M * 8bit,所以地址是64M起始,即地址 = 67108864,這里通過該IP訪問內存時,並不像NIOS中,需要加基地址。
其次由於不是burst傳輸的,因此control_fixed_location 設置為0;下面的control_read_length設置為(實際自己設置):4096*2 = 8192 BYTE,而數據線寬度我設置的是32Bit,也就是4字節,因此8192/4 = 2048(words),十六進制0x800,因此讀取2048次即可。
3.signal tap 波形分析:
由於之前分析過,輸出是在user_read_buffer有效時,且在next clk才輸出數據,因此我這里在user發出control_go信號之后,人為的產生一個clk的user_read_buffer信號,這樣我之后操作vld和data就對齊了。如下圖所示,之后user_read_buffer和data是對齊的:
接下來看下最后一個數據讀出,下圖中最后一個數字是0x800,對應10進制2048,每次讀取4字節,因此和我們在參數例化時設置的一致:
4.control_done 和 early_done 信號分析
如上圖所示,當數據為0x70F時,control_done為1,上次分析該信號是指示最后一個數據的,但是我沒有發現在0x800出現,二十在0x70f出現的,而fifo的深度我設置的是256,故我猜測該信號是表示最后一個數據已經寫入到FIFO中,然后該信號拉高(感覺不好用),control_early_done超前control_done,在此不做分析。
5.總結
該ip可以從Avalon MM Slave中讀取一定長度的數據,然后通過流的方式輸出,這在流處理過程中會有很大的應用,比如通過NIOS配置ccd/cmos傳感器,之后通過相應的接口將數據寫入到緩存中(可用Avalon-MM Master Templates-Write,下次分析),之后再通過讀端口將數據讀出,這樣會大大的簡化user 的操作,且user可以把輸出的數據進行打包,若加上sop和eop等信號,則可以直接傳送到千兆網模塊,當然還需要計算數據流的大小。
除了上述的應用,還可以共享內存做圖像顯示,在NIOS中給內存賦值,然后讀取內存中的數據到相應的顯示設備顯示即可,我想如果加上GUI會更加強大,且省成本,該方案可作為一種廉價的嵌入式解決方案。