fifo_rd_ctrl¶
模块描述¶
读地址控制逻辑,用于产生读指针和读空信号
参数说明¶
parameters of fifo_rd_ctrl¶
parameter FIFO_ADDR_WD = 3 ;
FIFO_ADDR_WD : FIFO地址位所需的最大位宽(与深度相对应)
I/O端口及变量说明¶
I/O ports & variables of fifo_rd_ctrl¶
input rd_clk ;
input rd_rstn ;
input rd_en_i ;
output rd_empty_o ;
output [FIFO_ADDR_WD -1:0] rd_ptr_o ; // read pointer, use gray-code
input [FIFO_ADDR_WD -1:0] wr_ptr_sync_i ; // write pointer (sync), use gray-code
reg rd_empty_o ;
reg [FIFO_ADDR_WD -1:0] rd_ptr_o ;
reg [FIFO_ADDR_WD -1:0] rd_ptr_next ;
端口名称 |
端口类型 |
描述 |
具体说明 |
|---|---|---|---|
rd_clk |
输入 |
读时钟 |
- |
rd_rstn |
输入 |
读时钟域的异步复位信号 |
- |
rd_en_i |
输入 |
读使能信号(与读时钟同步) |
其有效且未读空时,从FIFO中读出数据到rd_dat_o并令读地址+1 |
rd_empty_o |
输出 |
读空标志信号 |
由读指针和同步到读时钟域的写指针决定,若读指针追上写指针,则表示读空,在有新数据被写入前不允许继续读取数据 |
rd_ptr_o |
输出 |
读指针 |
指向FIFO中下一个待读取的数据,编码方式为格雷码 |
wr_ptr_sync_i |
输入 |
同步到读时钟域的写指针 |
- |
变量名称 |
变量类型 |
描述 |
具体说明 |
|---|---|---|---|
rd_empty_o |
reg |
读空标志信号 |
- |
rd_ptr_o |
reg |
读指针 |
- |
rd_ptr_next |
reg |
下一个读指针 |
- |
工作时序¶
上电,完成读指针复位操作
当读使能信号rd_en_i有效且读空标志位rd_empty_o无效(未读空)时,将读指针+1(指向下一个待读出位置)
在完成一次读出(读指针发生变化)或者同步过来的写指针wr_ptr_sync_r发生变化后,比较当前读指针的地址与同步过来的写指针的地址
若二者相等,意味着读指针已经追上写指针(滞后的),此时不可继续读FIFO数据,读空标志位置1(读空有效)
若二者不相等,意味着读指针未追上写指针(滞后的),允许读出FIFO数据,读空标志位置0(读空无效)
RTL代码¶
fifo_rd_ctrl.v¶
1module fifo_rd_ctrl(
2 rd_clk ,
3 rd_rstn ,
4 rd_en_i ,
5 rd_empty_o ,
6 rd_ptr_o ,
7 wr_ptr_sync_i
8);
9
10 parameter FIFO_ADDR_WD = 3 ;
11
12 input rd_clk ;
13 input rd_rstn ;
14 input rd_en_i ;
15 output rd_empty_o ;
16 output [FIFO_ADDR_WD -1:0] rd_ptr_o ; // read pointer, use gray-code
17 input [FIFO_ADDR_WD -1:0] wr_ptr_sync_i ; // write pointer (sync), use gray-code
18
19 reg rd_empty_o ;
20 reg [FIFO_ADDR_WD -1:0] rd_ptr_o ;
21 reg [FIFO_ADDR_WD -1:0] rd_ptr_next ;
22
23 always@(*) begin
24 case(rd_ptr_o)
25 3'b000: rd_ptr_next = 3'b001;
26 3'b001: rd_ptr_next = 3'b011;
27 3'b011: rd_ptr_next = 3'b010;
28 3'b010: rd_ptr_next = 3'b110;
29 3'b110: rd_ptr_next = 3'b111;
30 3'b111: rd_ptr_next = 3'b101;
31 3'b101: rd_ptr_next = 3'b100;
32 3'b100: rd_ptr_next = 3'b000;
33 endcase
34 end
35 always@(*) begin
36 if (rd_ptr_o == wr_ptr_sync_i) begin
37 rd_empty_o <= 1'b1;
38 end
39 else if (rd_ptr_o != wr_ptr_sync_i) begin
40 rd_empty_o <= 1'b0;
41 end
42 end
43
44 always@(posedge rd_clk or negedge rd_rstn) begin
45 if(~rd_rstn) begin
46 rd_ptr_o <= 3'b000;
47 end
48 else begin
49 if((rd_en_i == 1'b1) && (rd_empty_o == 1'b0)) begin
50 rd_ptr_o <= rd_ptr_next;
51 end
52 end
53 end
54
55endmodule