AVALON总线分类
在QSYS下,一个简单的组件包含了许多接口,它们实现了不同的功能,大致有下面几种:
Avalon-MM
Avalon-ST
Avalon Conduit
Avalon-TC
Avalon Interrupt
Avalon Clock.
这些标准是开源的,不需要license就可以开发使用。下图是一个总线应用的示意图:
2. AVALON MM总线
这里以AVALON MM为例,设计一个用户自定义的DPRAM组件,并用DMA方式将DPRAM PORTB中的数据搬移到内存SDRAM/DDR2中。下面接口定义是AVALON MM SLAVE总线的信号,具体时序在Avalon Interface Specifications中有详细描述。
//avalon MM slave input avs_clk, input avs_reset_n, input avs_chipselect_n, input [7:0] avs_address, input [3:0] avs_byteenable, input avs_write, input [31 :0] avs_writedata, input avs_read, output avs_readdatavalid, output [31 :0] avs_readdata
3. Qsys中添加自定义组件
1) 新建组件
2)添加文件
3) 信号设置
4) 接口时序
4. FPGA逻辑代码
下面是用户自定义的DPRAM的Verilog代码:
//file name: vid_dpram.v //author: shugen.yin //date: 2016.8.15 //function: user dpram for Qsys //log: module vid_dpram( //user port input inclock, input [7:0] data, input data_valid, input vid_vsync, //avalon MM slave input avs_clk, input avs_reset_n, input avs_chipselect_n, input [7:0] avs_address, input [3:0] avs_byteenable, input avs_write, input [31 :0] avs_writedata, input avs_read, output avs_readdatavalid, output [31 :0] avs_readdata ); parameter VID_WIDTH = 640; reg avs_readdatavalid_r0; reg avs_readdatavalid_r1; reg [9:0] wraddress_0; reg [9:0] wraddress_1; reg rdaddress_high_bit; reg wraddress_high_bit; wire [10:0] wraddress; wire [8:0] rdaddress; assign rdaddress = (avs_chipselect_n==1‘b0)?{1‘b0,avs_address[7:0]}:0; wire rden; assign rden = avs_read & ~avs_chipselect_n; dpram_01 dpram_01_inst ( .data ( data ), .wrclock ( inclock ), .rdclock ( avs_clk ), .rden (rden), .rdaddress ( rdaddress ), //input [8:0] rdaddress; .wraddress ( wraddress ), //input [10:0] wraddress; .wren (1‘b0 ), .q ( avs_readdata ) ); endmodule
dpram的PORT B端用HEX文件初始化(511~0循环递减):
5. NIOS2 源代码
#include <stdio.h> #include <sys/unistd.h> #include <string.h> #include <sys/alt_irq.h> #include "system.h" #include "alt_types.h" #include "altera_avalon_dma_regs.h" #include "sys/alt_dma.h" #include <sys/alt_cache.h> #define DAT_LEN 640 unsigned int buffer0[DAT_LEN/4]; unsigned int *point=VID_DPRAM_0_BASE; static void DMA_Init(void); //初始化DMA unsigned int dma_end_flag = 0; alt_dma_txchan tx; alt_dma_rxchan rx; void dma_done() { dma_end_flag++; } static void DMA_Init(void) { tx = alt_dma_txchan_open("/dev/dma_0"); if(tx != NULL) { printf("DMA transition start\n"); } alt_dma_txchan_ioctl(tx,ALT_DMA_SET_MODE_32,NULL); //point是源地址、传输数据块长度是DAT_LEN alt_dma_txchan_send(tx, point, DAT_LEN, NULL, NULL); rx = alt_dma_rxchan_open("/dev/dma_0"); alt_dma_rxchan_ioctl(rx,ALT_DMA_SET_MODE_32,NULL); //buffer0是目标地址、传输数据块长度是DAT_LEN、dma_done()是DMA完成后被调用的回调函数 alt_dma_rxchan_prepare(rx, buffer0 , DAT_LEN, dma_done, NULL); } int main() { int i; for(i=0;i<DAT_LEN/4;i++) buffer0[i] = 0; // alt_dcache_flush_all(); //if the nios2 core uses the cache DMA_Init(); //等待中断结束,说明传输完成 while(dma_end_flag == 0); alt_dma_txchan_close(tx); alt_dma_rxchan_close(rx); printf("\n============start===========\n"); //打印接收地址的数据 for(i=0;i<DAT_LEN/4;i++) { printf("buffer0[%d]=%d\t",i,buffer0[i]); } printf("\n=============end===========\n"); return 0; }
6. 运行结果
本文出自 “shugenyin的博客” 博客,请务必保留此出处http://shugenyin.blog.51cto.com/4259554/1839613
原文:http://shugenyin.blog.51cto.com/4259554/1839613