原创 IP核从端口寄存器模块设计指南

2010-3-7 09:46 3112 3 5 分类: FPGA/CPLD

寄存器设计包括1.偏移地址,2.寄存器名称,3.各个位的功能,4.读写权限(只读、读写都可以,写后清零)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


一般都有以下寄存器:状态寄存器、控制寄存器,其他寄存器就根据功能而定。


举例如下:


Offset    Name                   Access                               Bits


                                                        31 ... 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0


0            Status                  R/C                                             Busy | Done


4            Read Address     R/W  Read Address (byte address, 32 bits,


8            N/A                                                                         N/A


12          Length                 R/W                              Length (bytes, 32 bits)


16          N/A                                                                         N/A              


20          N/A                                                                         N/A


24          Control                R/W                    RCON | 0 | 0 | 0 | I_EN | Go | 0 | Inv | Clr


28          Checksum           R      Zeros(16) |               Checksum result (16 bits)


从端口寄存器包括的模块:


1.       读寄存器模块 


2.       写寄存器编写  


3.       状态寄存器编写  


4.       控制寄存器编写  


5.       中断信号编写


6.       模块输出信号


读寄存器模块编写:


临时变量通过一个多路数据选择器获得状态寄存器值,选择条件是从端口地址,然后同步时钟下临时变量赋值给寄存器,最后寄存器赋值给读数据端口。


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)


                 begin


                      control_readdata_temp_d1 <= control_readdata_temp;/


                 end


           end


      end


      assign slave_readdata = control_readdata_temp_d1;


写寄存器编写:根据寄存器偏移地址和写信号两个条件,外加字节使能信号。最终把寄存器信号值赋值给wire型变量。


always @ (posedge clk or posedge reset)


      begin


           if (reset)


           begin


                 XX_register <= 0;


           end


           else


           begin


                 if ((slave_address == 3'b011) & (slave_write == 1))


                 begin


                      if (slave_byteenable[0] == 1)


                      begin


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


                      end


                      if (slave_byteenable[1] == 1)


                      begin


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


                      end


                      if (slave_byteenable[2] == 1)


                      begin


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


                      end


                      if (slave_byteenable[3] == 1)


                      begin


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


                      end          


                 end


           end


      end


     


      assign control_read_XX = XX_register;


 


状态寄存器编写:


根据输入状态信号和输出状态信号编写对应的状态寄存器位,状态寄存器一般都是进行读操作,也可以加入写清零操作。


always @ (posedge clk or posedge reset)


      begin


           if (reset)


                 status_register <= 0;


           else


           begin


                 if (done_strobe == 1)


                      status_register <= 32'h1;  // busy and done


                 else if (control_go == 1)


                      status_register <= 32'h2;  // not busy and not done


                 else if ((slave_address == 3'b000) & (slave_write == 1))


                 begin


                      status_register <= 0;  // clear on write


                 end


           end


      end


 


控制寄存器编写:


和一般寄存器一样有写操作部分,最后再根据控制寄存器某一位的状态,确定输出信号。


always @ (posedge clk or posedge reset)


      begin


           if (reset)


           begin


                 control_register <= 0;


           end


           else


           begin


                 if ((slave_address == 3'b110) & (slave_write == 1))


                 begin


                      if (slave_byteenable[0] == 1)


                      begin


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


                      end


                      if (slave_byteenable[1] == 1)


                      begin


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


                      end


                      if (slave_byteenable[2] == 1)


                      begin


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


                      end


                      if (slave_byteenable[3] == 1)


                      begin


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


                      end          


                 end


           end


      end


assign control_fixed_read_address = control_register[8];


assign control_invert = control_register[1];


 


中断信号编写(中断信号一般在从端口模块中)


中断信号就是多个来自不同寄存器(尤其是状态寄存器和控制寄存器)位信号的组合逻辑值,注意中断信号要可以清空


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


 


Avalon总线信号:要通过同步时钟锁存到寄存器中。


always @ (posedge clk or posedge reset)


      begin


           if (reset)


           begin


                 slave_write_d1 <= 0;


                 slave_address_d1 <= 0;


                 slave_byteenable_d1 <= 0;


           end


           else


           begin


                 slave_write_d1 <= slave_write;


                 slave_address_d1 <= slave_address;


                 slave_byteenable_d1 <= slave_byteenable;


           end


      end


 


模块输出信号:


模块输出信号根据内部寄存器(总线信号寄存器、总线地址寄存器、总线字节使能寄存器、控制寄存器等)确定输出。


assign control_go = (slave_write_d1 == 1) & (slave_address_d1 == 3'b110) & (control_register[3] == 1) & (slave_byteenable_d1[0] == 1); 


assign control_clear = (slave_write_d1 == 1) & (slave_address_d1 == 3'b110) & (control_register[0] == 1) & (slave_byteenable_d1[0] == 1);


 


 应网友要求将整理的pdf上传,供学习下载。https://static.assets-stash.eet-china.com/album/old-resources/2010/3/7/6bd3d095-3550-41f4-9864-1753cd09639e.rar

 

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户180508 2010-3-7 11:03

pdf已经上传。

用户142112 2010-3-6 19:31

楼主这篇文章的出处在哪里啊?在帖子里看比较费劲,LZ能整理成PDF档吗?
相关推荐阅读
用户180508 2011-08-08 22:29
运算放大器指标
1.输入失调电压VIO(input offset voltage) :输入电压为零时,将输出电压除以电压增益,再加上负号,即为折算到输入端的失调电压。亦即使输出电压为零时在输入端所加的补偿电压。VIO...
用户180508 2011-02-18 22:21
UDE(u盘超级加密2008)失效解决
UDE伪装成唐诗三百首的加密软件,在忘记密码资料还没有丢失,操作系统改变时加密文件没有显示在加密区内。此时文件也没有丢失。 采用R-Studio(注册后)可以探测到隐藏的文件,并恢复。 本人遇到的隐藏...
用户180508 2011-02-01 12:35
Altea公司FPGA开发软件安装指南与注意
Quartus II安装点击Setup,和安装其他应用程序一样。可以根据自己的需要决定安装的大小。比如可以选择是否安装某种型号的器件 QuartusII8.0 破解补丁1将sys_cpt.dll覆盖掉...
用户180508 2011-02-01 12:02
Altea公司FPGA开发软件安装指南与注意
Quartus II安装点击Setup,和安装其他应用程序一样。可以根据自己的需要决定安装的大小。比如可以选择是否安装某种型号的器件QuartusII8.0 破解补丁1将sys_cpt.dll覆盖掉安...
用户180508 2011-02-01 12:01
Altea公司FPGA开发软件安装指南与注意
Quartus II安装点击Setup,和安装其他应用程序一样。可以根据自己的需要决定安装的大小。比如可以选择是否安装某种型号的器件QuartusII8.0 破解补丁1将sys_cpt.dll覆盖掉安...
用户180508 2010-12-30 10:18
VC安装错误解决
安装VC++6.0时候总是说我的安装程序无法创建一个DCOM用户来注册? 右击我的电脑-》管理-》本地用户和组-》用户-》删除VSA Sever Account项 再安装,成功!...
EE直播间
更多
我要评论
2
3
关闭 站长推荐上一条 /3 下一条