SOPC自定义元件的添加及运行.docx
《SOPC自定义元件的添加及运行.docx》由会员分享,可在线阅读,更多相关《SOPC自定义元件的添加及运行.docx(15页珍藏版)》请在冰点文库上搜索。
SOPC自定义元件的添加及运行
SOPC自定义元件的添加及运行
NiosII嵌入式系统驱动设计
(二)
在SOPC中自定义元件的端口设置解析中讲述了自定义元件的端口设置,在本文中将详细讲述如何将自定义元件嵌入SOPCBuilder中,以及将该元件加入SOPC系统,并通过运行软件测试该元件性能。
新建一个文件夹ip,将CkecksumHardwareAccelerator的源文件checksum_accelerator.v,checksum_transform.v,latency_aware_read_master.v,slave.v复制到该文件夹下。
打开SOPCBuilder,单击左上角的Createnewcomponent…,弹出如下对话框:
Introduction页面是对componenteditor的简单介绍。
● HDLFiles
单击Add…,选择刚才新建的ip文件夹,将该文件夹下的所有.v文件选中加入,componenteditor并会进行分析,主要是对端口的分析,将顶层文件的Top复选框打上勾。
如果文件有改变可以点击ReanalyzeHDLFiles重新分析。
除了导入HDL文件外,componenteditor还提供另一种方法可以将端口export到SOPC系统之外,直接在Signals页面手动加入信号或在Templates中加入已经定义好的端口信号,用户再自己修改。
导入HDL文件后,Templates下拉菜单为灰色,无法加入。
● Signals
这里的信号是componenteditor分析了HDL文件后自动从文件中提取的端口信号,用户需要设置interface,SignalType,Width,Direction以使用户端口信号与Avalon总线信号相对应,如果用户端口信号的命名方式参考SOPC中自定义元件的端口设置解析中的要求,则componenteditor自动识别出相对应的信号设置。
● interfaces
Interfaces的类型在SOPC中自定义元件的端口设置解析中有说明,主要有Master,slave,clockinput等10种,在每种类型下面可以设置该类型interface的属性参数,如时序,流水线传输,interface的同步clock等。
如果显示了除定义以外的interface,则点击RemoveinterfacesWithNoSignals删除。
● ComponentWizard
在ComponentWizard中可以设置元件所属类型名称,元件显示名称,版本号等信息,点击PreviewtheGUI…可以预览,如果在顶层HDL文件中定义了一些Parameters,可以这里加入以便让用户在实例化时可以设置这些参数。
全部设置完后,点击Finish…在ip文件夹下产生checksum_accelerator_hw.tcl文件,该文件并是Componenteditor根据用户设置生成的文件,该文件提供给SOPCBuilder所有需要的信息。
除了硬件文件外,为了能用软件执行给元件,需要添加软件驱动程序。
在ip文件夹下新建HAL文件和inc文件,ip文件结构如下:
其中HAL文件夹下的inc文件夹下包含checksum_accelerator_routines.h为软件API的头文件,HAL文件夹下的src文件夹下包含checksum_accelerator_routines.c为软件API的源文件,以及component.mk,该文件在编译时提供驱动程序源文件信息。
在ip文件夹下的inc文件提供元件的寄存器映射(registermap)文件,该文件提供软件读写元件寄存器的地址。
所有的工作完成后,将ip文件复制到QuaetusII工程目录下,打开该工程的SOPCBuilder,此时在左边栏出现刚才新增的元件。
为了测试新增元件的功能,建立带有该元件的SOPC系统:
同时建立以该硬件为基础的软件工程,将文件test_checksum.c的内容复制到应用工程的源文件中,编译,下载,运行后,console窗口出现如下结果:
软件首先产生64KB的随机数,然后分别用软件cheksum和硬件checksum,输出两次checksum的结果,可以看到硬件checksum比软件checksum快了65倍,硬件加速起到了很大的作用,因此在关键算法上可以采用硬件实现,以提高速度。
基于NiosII的DMA传输总结(附源码)
NiosII中的DMA传输有以下三种形式:
1、 存储器到存储器
这种情况下需要同时打开发送通道和接收通道,而且源地址和目标地址都是自增的。
tx=alt_dma_txchan_open("/dev/dma_0");//打开发送通道
dma_res=alt_dma_txchan_send(tx,tx_buf,32,NULL,NULL);//tx_buf是源地址
rx=alt_dma_rxchan_open("/dev/dma_0");//打开接收通道
dma_res=alt_dma_rxchan_prepare(rx,rx_buf,32,dma_done,NULL);//rx_buf是目标地址,dma_done()是DMA完成后被调用的回调函数。
2、 存储器到外设
这种情况下只要打开发送通道,而且源地址是自增的,目标地址是固定的。
tx=alt_dma_txchan_open("/dev/dma_0");//打开发送通道
alt_dma_txchan_ioctl(tx,ALT_DMA_TX_ONLY_ON,(void*)dst_addr);//dst_addr是目标地址
dma_res=alt_dma_txchan_send(tx,tx_buf,32,dma_done,NULL);//tx_buf是源地址
3、 外设到存储器
这种情况下只要打开接收通道,而且源地址是固定的,目标地址是自增的。
rx=alt_dma_rxchan_open("/dev/dma_0");//打开接收通道
alt_dma_rxchan_ioctl(rx,ALT_DMA_RX_ONLY_ON,(void*)source_addr);//source_addr是源地址
dma_res=alt_dma_rxchan_prepare(rx,rx_buf,32,dma_done,NULL);//rx_buf是目标地址
其中通过alt_dma_txchan_ioctl,alt_dma_rxchan_ioctl还可以设置每次发送和接收的字节数。
下面给出两个实例,说明DMA传输的过程。
1、 存储器到存储器
下面程序为SDRAM到onchip-memory的数据传输。
硬件连接图示:
程序如下:
#include
#include
#include
#include"system.h"
staticvolatileintrx_done=0;
intrc;
alt_dma_txchantxchan;
alt_dma_rxchanrxchan;
staticcharbuff[256];
void*tx_data=(void*)buff;/*源地址*/
void*rx_buffer=(void*)0x01801000;/*目标地址,从上图看到0x01801000为onchip-memory的地址*/
//DMA传输结束回调函数
staticvoiddone_t(void*handle,void*data)
{
rx_done++;
}
intmain(intargc,char*argv[],char*envp[])
{
/*打开发送通道*/
if((txchan=alt_dma_txchan_open("/dev/dma"))==NULL)
{
printf("Failedtoopentransmitchannel\n");
exit
(1);
}
/*打开接收通道*/
if((rxchan=alt_dma_rxchan_open("/dev/dma"))==NULL)
{
printf("Failedtoopenreceivechannel\n");
exit
(1);
}
/*开始发送数据*/
if((rc=alt_dma_txchan_send(txchan,
tx_data,
128,
NULL,
NULL))<0)
{
printf("Failedtoposttransmitrequest,reason=%i\n",rc);
exit
(1);
}
/*开始接收数据*/
if((rc=alt_dma_rxchan_prepare(rxchan,
rx_buffer,
128,
done_t,
NULL))<0)
{
printf("Failedtopostreadrequest,reason=%i\n",rc);
exit
(1);
}
/*等待传输结束*/
while(!
rx_done);
printf("Transfersuccessful!
\n");
return0;
}
程序运行结束后在NiosIDE的console界面中显示:
Transfersuccessful!
表明传输成功。
2、 存储器到UART
下面程序为SDRAM到UART的数据传输
硬件连接图:
程序如下:
#include
#include
#include"sys/alt_dma.h"
#include"altera_avalon_uart_regs.h"
#include"system.h"
#include"alt_types.h"
staticvolatileinttx_done=0;
volatilestaticalt_u8chr[20]={1,2,3,4,6,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20};//待发送的数据
//回调函数
staticvoiddone(void*handle)
{
tx_done++;
}
intmain()
{
intrc;
alt_dma_txchantxchan;
void*source_buff_ptr=(void*)chr;/*源地址*/
void*destination_buff_ptr=(void*)IOADDR_ALTERA_AVALON_UART_TXDATA(UART_BASE);/*目标地址IOADDR_ALTERA_AVALON_UART_TXDATA(UART_BASE)函数读出txdata的地址*/
/*打开发送通道*/
if((txchan=alt_dma_txchan_open("/dev/dma"))==NULL)
{
printf("Failedtoopentransmitchannel\n");
exit
(1);
}
/*设置目标地址固定*/
if((rc=alt_dma_txchan_ioctl(txchan,ALT_DMA_TX_ONLY_ON,destination_buff_ptr))<0)
{
printf("Failedtosetioctl,reason=%i\n",rc);
exit
(1);
}
//设置每次发送一个字节,即8位,因为UART每次只发送8位
if((rc=alt_dma_txchan_ioctl(txchan,ALT_DMA_SET_MODE_8,NULL))<0)
{
printf("Failedtosetmode8\n");
exit
(1);
}
/*开始发送*/
if((rc=alt_dma_txchan_send(txchan,source_buff_ptr,20,done,NULL))<0)
{
printf("Failedtoposttransmitrequest,reason=%i\n",rc);
exit
(1);
}
/*等待发送结束*/
while(!
tx_done);
printf("Transfersuccessful!
\n");
return0;
}
不过该程序执行结束后,在串口调试器中显示Transfersuccessful!
,却没有显示DMA发送的那20个数字。
不知道哪里需要修改,放在这里和大家讨论下。