原创 【原创】SOPC自定义从接口编写实例

2008-12-10 22:56 6153 8 11 分类: FPGA/CPLD

Nios II嵌入式系统驱动设计(三)


SOPC中自定义元件的端口设置解析 中讲述了各种Avalon自定义接口的端口设置,在SOPC自定义元件的添加及运行中介绍了如何将已编写好代码的元件集成到SOPC Builder中,在本文中将介绍如何编写能够挂载到Avalon上的Slave接口的端口代码编写方法。







Slave interface(接口)代码编写:


Slave interface包含如下端口:

Signal TypeDirectionv7.1 and Earlier Interfacev7.2 and Later Interface
clkInputGlobalClock Input (1)
resetInputGlobalClock Input (1)
addressInputAvalon SlaveAvalon Slave
readInputAvalon SlaveAvalon Slave
readdataOutputAvalon SlaveAvalon Slave
writeInputAvalon SlaveAvalon Slave
writedataInputAvalon SlaveAvalon Slave
waitrequestOutputAvalon SlaveAvalon Slave
irqOutputAvalon SlaveInterrupt Sender
my_export_signalsInput, Output, or BidirGlobalConduit

8.0版本中,Slave接口中去掉了chipselect端口,也增加了上面表格中没有的byteenable端口,slave inteface代码编写实例如下:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


module slave (


       // these connect to the clock port


       clk,


       reset,


       // these connect to the slave port


       slave_address,


       slave_read,


       slave_readdata,


       slave_write,


       slave_writedata,


       slave_byteenable,


       // this connects to the irq sender port


       control_irq


// Conduit port


Out<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2In,


In2Out,


);



       input clk;


       input reset;



       input [2:0] slave_address;


       input slave_read;


       output wire [31:0] slave_readdata;


       input slave_write;


       input [31:0] slave_writedata;


       input [3:0] slave_byteenable;



       output control_irq;



input Out2In;


output In2Out;


/****************************************************************************/


// definition register in Slave


       reg [31:0] status_register;


       reg [31:0] read_address_register;


       reg [31:0] length_register;


       reg [31:0] control_register;


       wire [31:0] control_readdata_temp;


       reg [31:0] control_readdata_temp_d1; 


       wire [31:0] checksum_register;


/****************************************************************************/


//write length register


always @ (posedge clk or posedge reset)


       begin


              if (reset)


              begin


                     length_register <= 0;


              end


              else


              begin


                     if ((slave_address == 3'b011) & (slave_write == 1))//assert to write length register


                     begin


                            if (slave_byteenable[0] == 1)


                            begin


                                   length_register[7:0] <= slave_writedata[7:0];


                            end


                            if (slave_byteenable[1] == 1)


                            begin


                                   length_register[15:8] <= slave_writedata[15:8];


                            end


                            if (slave_byteenable[2] == 1)


                            begin


                                   length_register[23:16] <= slave_writedata[23:16];


                            end


                            if (slave_byteenable[3] == 1)


                            begin


                                   length_register[31:24] <= slave_writedata[31:24];


                            end        


                     end


              end


       end


//you can write other register like this.


/**********************************************************************/


//read register


assign control_readdata_temp = (slave_address == 3'b000)? status_register :


                                                   (slave_address == 3'b001)? read_address_register :


                                                   (slave_address == 3'b011)? length_register :


                                                   (slave_address == 3'b110)? control_register :


                                                   (slave_address == 3'b111)? checksum_register : 0;


                                                


       always @ (posedge clk or posedge reset)


       begin


              if (reset)


              begin


                     control_readdata_temp_d1 <= 0;


              end


              else


              begin


                     if (slave_read == 1)//assert to read register


                     begin


                            control_readdata_temp_d1 <= control_readdata_temp;//the content is according to the slave_address


                     end


              end


       end


       assign slave_readdata = control_readdata_temp_d1;//assign the register data to the slave_readdata.


/*****************************************************************************/


//interrupt sender


assign control_irq = status_register[0] & control_register[4];


/*****************************************************************************/


//do some algorithm, receive Out2In from outside SOPC system, export In2Out to outside SOPC system


XXX <= Out2In;


………………….


In2Out <= YYY;


/*****************************************************************************/


 






 


register map文件 component_reg.h文件中定义了这些寄存器的地址,以便驱动文件读写这些寄存器。


下面为status寄存器的地址映射代码,其他寄存器也类似,只是偏移地址根据程序中设定的地址具体再指定。


#define CHECKSUM_ACCELERATOR_STATUS_REGISTER_OFFSET    0


#define  IOADDR_CHECKSUM_ACCELERATOR_STATUS(base)


__IO_CALC_ADDRESS_NATIVE(base,CHECKSUM_ACCELERATOR_STATUS_REGISTER_OFFSET)


#define  IORD_CHECKSUM_ACCELERATOR_STATUS(base)


IORD_32DIRECT(base,CHECKSUM_ACCELERATOR_STATUS_REGISTER_OFFSET)


#define IOWR_CHECKSUM_ACCELERATOR_STATUS(base, data)


IOWR_32DIRECT(base, CHECKSUM_ACCELERATOR_STATUS_REGISTER_OFFSET, data)


 





 


编写完register map文件后,并可以在HAL API文件中编写API函数,在函数中根据register map文件中的IORDIOWR宏读写寄存器的值,比如:


alt_u32 read_status_of_checksum(alt_u32 base)


{


  return IORD_CHECKSUM_ACCELERATOR_STATUS(base+CHECKSUM_ACCELERATOR_STATUS_REGISTER_OFFSET);


}



上层的软件工程只需要调用API函数及可以操作硬件,而不用直接读写硬件的寄存器,这


也是驱动的主要作用。


 

文章评论3条评论)

登录后参与讨论

用户1690430 2012-8-3 19:03

问下版主 你的IP中的IRQ是在什么事件下发生啊?

用户504141 2009-3-19 17:34

请问版主,component.mk文件怎样编写?我是个新手不太会,谢谢!

用户1332143 2009-1-6 09:46

slave_byteenable的信号在主端口生成时的逻辑中根据你的设置应该会自动产生
相关推荐阅读
用户1332143 2009-08-16 21:47
时序电路亚稳态分析
这篇文章是我对电子设计中,亚稳态问题的一种分析和总结。文章通过对数字电路中器件的工作机制的介绍,引出亚稳态问题的发生机制。并通过对亚稳态问题发生机制的探讨,用以得到一种能够清楚地,有的放矢地解决亚稳态...
用户1332143 2009-08-16 10:52
【推荐】ADF4350配置软件下载
p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">  随着现代半导体工艺的不断发展, 几十纳米级的CMOS工艺给数字电路带来了很大的恩惠, 但对模拟...
用户1332143 2009-08-14 12:47
【原创】基于NiosII及FT245BM的USB接口设计
以前做的一个项目,FPGA接收AD采集数据后,通过串口发送回PC机,由于串口传输速率较低,对于实时性要求较高的场合不太适用,因此站长选用FT245BM芯片来实现USB接口传输,本文主要讲解FT245B...
用户1332143 2009-08-13 14:56
【原创】MAXII:UFM中晶振的使用
MAXII系列CPLD中带有UFM模块,本文主要讲解UFM中晶振的使用,具体内容请点击下面链接MAXII:UFM中晶振的使用...
用户1332143 2009-03-01 21:53
【原创】如何使用FPGA进行信号调制
       最近要做一个通信收发系统项目,以前对收发器的射频前段关注的比较多,而对基带部分的信号处理一直没有仔细研究。因此,正好借这个项目,熟悉整个基带部分的信号处理流程。       基带部分主要...
用户1332143 2009-02-27 21:56
寒假回来——FPGA市场评论
寒假在家里电脑不能上网,好久没来更新自己的博客了,首先感谢大家对我博客的支持。回来后马上开始了一个863项目,一直没有时间来写博客,今天总算有时间,上来看看。回来这段时间关注了下FPGA的相关新闻,发...
EE直播间
更多
我要评论
3
8
关闭 站长推荐上一条 /3 下一条