fifo_ctrl

模块描述

读/写地址控制逻辑,用于产生读/写指针和读空/写满信号,分别实例化了一组读地址控制逻辑和一组写地址控制逻辑,并进行了地址的跨时钟域同步

参数说明

parameters of fifo_ctrl
parameter                           FIFO_ADDR_WD    =   3   ;
  • FIFO_ADDR_WD : FIFO地址位所需的最大位宽(与深度相对应)

I/O端口及变量说明

ports & variables of fifo_ctrl
input                               rd_clk          ;
input                               rd_rstn         ;
input                               rd_en_i         ;
output                              rd_empty_o      ;
output [FIFO_ADDR_WD    -1:0]       rd_ptr_o        ;
input                               wr_clk          ;
input                               wr_rstn         ;
input                               wr_en_i         ;
output                              wr_full_o       ;
output [FIFO_ADDR_WD    -1:0]       wr_ptr_o        ;

wire   [FIFO_ADDR_WD    -1:0]       rd_ptr_sync_r   ;
wire   [FIFO_ADDR_WD    -1:0]       wr_ptr_sync_r   ;

reg    [FIFO_ADDR_WD    -1:0]       rd_ptr_1_r      ;
reg    [FIFO_ADDR_WD    -1:0]       rd_ptr_2_r      ;
reg    [FIFO_ADDR_WD    -1:0]       wr_ptr_1_r      ;
reg    [FIFO_ADDR_WD    -1:0]       wr_ptr_2_r      ;

端口名称

端口类型

描述

具体说明

rd_clk

输入

读时钟

-

rd_rstn

输入

读时钟域的异步复位信号

-

rd_en_i

输入

读使能信号(与读时钟同步)

其有效且未读空时,从FIFO中读出数据到rd_dat_o并令读地址+1

rd_empty_o

输出

读空标志信号

由读指针和同步到读时钟域的写指针决定,若读指针追上写指针,则表示读空,在有新数据被写入前不允许继续读取数据

rd_ptr_o

输出

读指针

指向FIFO中下一个待读取的数据,编码方式为格雷码

wr_clk

输入

写时钟

-

wr_rstn

输入

写时钟域的异步复位信号

-

wr_en_i

输入

写使能信号(与写时钟同步)

其有效且未写满时,向FIFO中写入待写入数据并令写地址+1

wr_full_o

输出

写满标志信号

由写指针和同步到写时钟域的读指针决定,若写指针追上读指针,则表示写满,在有数据被读出前不允许继续写入新数据

wr_ptr_o

输出

写指针

指向FIFO中下一个待写入数据的位置,编码方式为格雷码

变量名称

变量类型

描述

具体说明

rd_ptr_sync_r

wire

同步到写时钟域的读指针

-

wr_ptr_sync_r

wire

同步到读时钟域的写指针

-

rd_ptr_1_r

reg

在写时钟域进行一拍寄存后的读指针

-

rd_ptr_2_r

reg

在写时钟域进行两拍寄存后的读指针

同rd_ptr_sync_r

wr_ptr_1_r

reg

在读时钟域进行一拍寄存后的写指针

-

wr_ptr_2_r

reg

在读时钟域进行两拍寄存后的写指针

同wr_ptr_sync_r

工作时序

  • 上电,读时钟域和写时钟域分别完成读/写指针复位操作

  • 写时钟域

    • 当写使能信号wr_en_i有效且写满标志位wr_full_o无效(未写满)时,将写指针+1(指向下一个待写入位置)

    • 在完成一次写入(写指针发生变化)或者同步过来的读指针rd_ptr_sync_r发生变化后,比较当前写指针+1后的地址与同步过来的读指针的地址

      • 若二者相等,意味着写指针已经再次追上读指针(滞后的),此时不可继续写入,写满标志位置1(写满有效)

      • 若二者不相等,意味着写指针未再次追上读指针(滞后的),允许写入,写满标志位置0(写满无效)

  • 读时钟域

    • 当读使能信号rd_en_i有效且读空标志位rd_empty_o无效(未读空)时,将读指针+1(指向下一个待读出位置)

    • 在完成一次读出(读指针发生变化)或者同步过来的写指针wr_ptr_sync_r发生变化后,比较当前读指针的地址与同步过来的写指针的地址

      • 若二者相等,意味着读指针已经追上写指针(滞后的),此时不可继续读FIFO数据,读空标志位置1(读空有效)

      • 若二者不相等,意味着读指针未追上写指针(滞后的),允许读出FIFO数据,读空标志位置0(读空无效)

  • 在读/写指针变化的同时(之前),FIFO存储器会根据指针完成相应数据的读出/写入

RTL代码

fifo_ctrl.v
 1module fifo_ctrl(
 2   rd_clk          ,
 3   rd_rstn         ,
 4   rd_en_i         ,
 5   rd_empty_o      ,
 6   rd_ptr_o        ,
 7   wr_clk          ,
 8   wr_rstn         ,
 9   wr_en_i         ,
10   wr_full_o       ,
11   wr_ptr_o
12);
13
14   parameter                           FIFO_ADDR_WD    =   3   ;
15
16   input                               rd_clk          ;
17   input                               rd_rstn         ;
18   input                               rd_en_i         ;
19   output                              rd_empty_o      ;
20   output [FIFO_ADDR_WD    -1:0]       rd_ptr_o        ;
21   input                               wr_clk          ;
22   input                               wr_rstn         ;
23   input                               wr_en_i         ;
24   output                              wr_full_o       ;
25   output [FIFO_ADDR_WD    -1:0]       wr_ptr_o        ;
26
27   wire   [FIFO_ADDR_WD    -1:0]       rd_ptr_sync_r   ;
28   wire   [FIFO_ADDR_WD    -1:0]       wr_ptr_sync_r   ;
29
30   reg    [FIFO_ADDR_WD    -1:0]       rd_ptr_1_r      ;
31   reg    [FIFO_ADDR_WD    -1:0]       rd_ptr_2_r      ;
32   reg    [FIFO_ADDR_WD    -1:0]       wr_ptr_1_r      ;
33   reg    [FIFO_ADDR_WD    -1:0]       wr_ptr_2_r      ;
34
35   assign  rd_ptr_sync_r = rd_ptr_2_r;
36   assign  wr_ptr_sync_r = wr_ptr_2_r;
37
38   always@(posedge rd_clk or negedge rd_rstn) begin
39      if(~rd_rstn) begin
40            wr_ptr_1_r <= 3'b000;
41            wr_ptr_2_r <= 3'b000;
42      end
43      else begin
44            {wr_ptr_2_r,wr_ptr_1_r} <= {wr_ptr_1_r,wr_ptr_o};
45      end
46   end
47
48   always@(posedge wr_clk or negedge wr_rstn) begin
49      if(~wr_rstn) begin
50            rd_ptr_1_r <= 3'b000;
51            rd_ptr_2_r <= 3'b000;
52      end
53      else begin
54            {rd_ptr_2_r,rd_ptr_1_r} <= {rd_ptr_1_r,rd_ptr_o};
55      end
56   end
57
58   fifo_rd_ctrl #(.FIFO_ADDR_WD(FIFO_ADDR_WD)) fifo_rd_ctrl(
59      .rd_clk         (   rd_clk          ),
60      .rd_rstn        (   rd_rstn         ),
61      .rd_en_i        (   rd_en_i         ),
62      .rd_empty_o     (   rd_empty_o      ),
63      .rd_ptr_o       (   rd_ptr_o        ),
64      .wr_ptr_sync_i  (   wr_ptr_sync_r   )
65   );
66
67   fifo_wr_ctrl #(.FIFO_ADDR_WD(FIFO_ADDR_WD)) fifo_wr_ctrl(
68      .wr_clk         (   wr_clk          ),
69      .wr_rstn        (   wr_rstn         ),
70      .wr_en_i        (   wr_en_i         ),
71      .wr_full_o      (   wr_full_o       ),
72      .wr_ptr_o       (   wr_ptr_o        ),
73      .rd_ptr_sync_i  (   rd_ptr_sync_r   )
74   );
75
76endmodule

链接到

子模块

父模块