新闻  |   论坛  |   博客  |   在线研讨会
IP核从端口寄存器模块设计指南
0750long | 2010-03-10 21:17:34    阅读:1779   发布文章

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

 

 

寄存器设计包括:1.偏移地址,2.寄存器名称,3.各个位的功能,4.读写权限(只读、读写都可以,写后清零)

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

举例如下:

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);

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客