-
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中有详细描述。
|
1
2
3
4
5
6
7
8
9
10
11
|
//avalon MM slaveinput 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代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
//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 源代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
#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 640unsigned 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 51CTO博客,原文链接:http://blog.51cto.com/shugenyin/1839613