AVALON總線分類
在QSYS下,一個簡單的元件包含了許多接口,它們實作了不同的功能,大緻有下面幾種:
Avalon-MM
Avalon-ST
Avalon Conduit
Avalon-TC
Avalon Interrupt
Avalon Clock.
這些标準是開源的,不需要license就可以開發使用。下圖是一個總線應用的示意圖:
<a href="http://s3.51cto.com/wyfs02/M00/86/15/wKioL1e0Gm3izts1AADLRaaI9b4776.jpg" target="_blank"></a>
2. AVALON MM總線
這裡以AVALON MM為例,設計一個使用者自定義的DPRAM元件,并用DMA方式将DPRAM PORTB中的資料搬移到記憶體SDRAM/DDR2中。下面接口定義是AVALON MM SLAVE總線的信号,具體時序在Avalon Interface Specifications中有較長的描述。
<code>//avalon MM slave</code>
<code>input avs_clk,</code>
<code>input avs_reset_n,</code>
<code>input avs_chipselect_n,</code>
<code>input [7:0] avs_address,</code>
<code>input [3:0] avs_byteenable,</code>
<code>input avs_write,</code>
<code>input [31 :0] avs_writedata,</code>
<code>input avs_read,</code>
<code>output avs_readdatavalid,</code>
<code>output [31 :0] avs_readdata</code>
3. Qsys中添加自定義元件
1) 建立元件
<a href="http://s3.51cto.com/wyfs02/M01/86/15/wKioL1e0HgKxVwZ9AAB_gS4gy2M556.jpg" target="_blank"></a>
2)添加檔案
<a href="http://s4.51cto.com/wyfs02/M01/86/15/wKioL1e0HmrjMx98AACHdhdzvHY121.jpg" target="_blank"></a>
3) 信号設定
<a href="http://s3.51cto.com/wyfs02/M01/86/15/wKiom1e0Hu7iMPy7AAC72yJKk4w782.jpg" target="_blank"></a>
4) 接口時序
<a href="http://s1.51cto.com/wyfs02/M02/86/15/wKioL1e0H2yzN8TvAACgJ_Ytcdw970.jpg" target="_blank"></a>
4. FPGA邏輯代碼
下面是使用者自定義的DPRAM的Verilog代碼:
<code>//file name: vid_dpram.v</code>
<code>//author: shugen.yin</code>
<code>//date: 2016.8.15</code>
<code>//function: user dpram for Qsys</code>
<code>//log: </code>
<code>module vid_dpram(</code>
<code> </code><code>//user port</code>
<code> </code><code>input inclock,</code>
<code> </code><code>input [7:0] data,</code>
<code> </code><code>input data_valid,</code>
<code> </code><code>input vid_vsync,</code>
<code> </code>
<code> </code><code>//avalon MM slave</code>
<code> </code><code>input avs_clk,</code>
<code> </code><code>input avs_reset_n,</code>
<code> </code><code>input avs_chipselect_n,</code>
<code> </code><code>input [7:0] avs_address,</code>
<code> </code><code>input [3:0] avs_byteenable,</code>
<code> </code><code>input avs_write,</code>
<code> </code><code>input [31 :0] avs_writedata,</code>
<code> </code><code>input avs_read,</code>
<code> </code><code>output avs_readdatavalid,</code>
<code> </code><code>output [31 :0] avs_readdata</code>
<code>);</code>
<code>parameter VID_WIDTH = 640;</code>
<code>reg avs_readdatavalid_r0;</code>
<code>reg avs_readdatavalid_r1;</code>
<code>reg [9:0] wraddress_0;</code>
<code>reg [9:0] wraddress_1;</code>
<code>reg rdaddress_high_bit;</code>
<code>reg wraddress_high_bit;</code>
<code>wire [10:0] wraddress;</code>
<code>wire [8:0] rdaddress;</code>
<code>assign rdaddress = (avs_chipselect_n==1</code><code>'b0)?{1'</code><code>b0,avs_address[7:0]}:0;</code>
<code>wire rden;</code>
<code>assign rden = avs_read & ~avs_chipselect_n; </code>
<code>dpram_01 dpram_01_inst (</code>
<code> </code><code>.data ( data ),</code>
<code> </code><code>.wrclock ( inclock ),</code>
<code> </code><code>.rdclock ( avs_clk ),</code>
<code> </code><code>.rden (rden),</code>
<code> </code><code>.rdaddress ( rdaddress ), </code><code>//input [8:0] rdaddress;</code>
<code> </code><code>.wraddress ( wraddress ), </code><code>//input [10:0] wraddress;</code>
<code> </code><code>.wren (1'b0 ),</code>
<code> </code><code>.q ( avs_readdata )</code>
<code> </code><code>);</code>
<code>endmodule</code>
dpram的PORT B端用HEX檔案初始化(511~0循環遞減):
<a href="http://s1.51cto.com/wyfs02/M01/86/15/wKioL1e0I2qxQE2bAABXOWoPIyQ715.jpg" target="_blank"></a>
5. NIOS2 源代碼
<code>#include <stdio.h></code>
<code>#include <sys/unistd.h></code>
<code>#include <string.h></code>
<code>#include <sys/alt_irq.h></code>
<code>#include "system.h"</code>
<code>#include "alt_types.h"</code>
<code>#include "altera_avalon_dma_regs.h"</code>
<code>#include "sys/alt_dma.h"</code>
<code>#include <sys/alt_cache.h></code>
<code>#define DAT_LEN 640</code>
<code>unsigned </code><code>int</code> <code>buffer0[DAT_LEN/4];</code>
<code>unsigned </code><code>int</code> <code>*point=VID_DPRAM_0_BASE;</code>
<code>static</code> <code>void</code> <code>DMA_Init(</code><code>void</code><code>); </code><code>//初始化DMA</code>
<code>unsigned </code><code>int</code> <code>dma_end_flag = 0;</code>
<code>alt_dma_txchan tx;</code>
<code>alt_dma_rxchan rx;</code>
<code>void</code> <code>dma_done()</code>
<code>{</code>
<code> </code><code>dma_end_flag++;</code>
<code>}</code>
<code>static</code> <code>void</code> <code>DMA_Init(</code><code>void</code><code>)</code>
<code> </code><code>tx = alt_dma_txchan_open(</code><code>"/dev/dma_0"</code><code>);</code>
<code> </code><code>if</code><code>(tx != NULL)</code>
<code> </code><code>{</code>
<code> </code><code>printf</code><code>(</code><code>"DMA transition start\n"</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>alt_dma_txchan_ioctl(tx,ALT_DMA_SET_MODE_32,NULL);</code>
<code> </code><code>//point是源位址、傳輸資料塊長度是DAT_LEN</code>
<code> </code><code>alt_dma_txchan_send(tx, point, DAT_LEN, NULL, NULL);</code>
<code> </code><code>rx = alt_dma_rxchan_open(</code><code>"/dev/dma_0"</code><code>);</code>
<code> </code><code>alt_dma_rxchan_ioctl(rx,ALT_DMA_SET_MODE_32,NULL);</code>
<code> </code><code>//buffer0是目标位址、傳輸資料塊長度是DAT_LEN、dma_done()是DMA完成後被調用的回調函數</code>
<code> </code><code>alt_dma_rxchan_prepare(rx, buffer0 , DAT_LEN, dma_done, NULL);</code>
<code>int</code> <code>main()</code>
<code> </code><code>int</code> <code>i;</code>
<code> </code><code>for</code><code>(i=0;i<DAT_LEN/4;i++)</code>
<code> </code><code>buffer0[i] = 0;</code>
<code>// alt_dcache_flush_all(); //if the nios2 core uses the cache</code>
<code> </code><code>DMA_Init();</code>
<code> </code><code>//等待中斷結束,說明傳輸完成</code>
<code> </code><code>while</code><code>(dma_end_flag == 0);</code>
<code> </code><code>alt_dma_txchan_close(tx);</code>
<code> </code><code>alt_dma_rxchan_close(rx);</code>
<code> </code><code>printf</code><code>(</code><code>"\n============start===========\n"</code><code>);</code>
<code> </code><code>//列印接收位址的資料</code>
<code> </code><code>printf</code><code>(</code><code>"buffer0[%d]=%d\t"</code><code>,i,buffer0[i]);</code>
<code> </code><code>printf</code><code>(</code><code>"\n=============end===========\n"</code><code>);</code>
<code> </code><code>return</code> <code>0;</code>
6. 運作結果
<a href="http://s2.51cto.com/wyfs02/M00/86/16/wKiom1e0JHHSssrhAADYzcNDodA880.jpg" target="_blank"></a>
本文轉自 shugenyin 51CTO部落格,原文連結:http://blog.51cto.com/shugenyin/1839613