FIFO

发布时间 2023-10-21 12:21:57作者: lwzhang

1 module Write_Data #(
2 parameter DEEP_WIDTH = 4 ,
3 parameter FIFO_DEEP = 5'd16 ,
4 parameter GAP_WIDTH = 3
5 )(
6 output wfull , //几乎满信号
7 output reg wfull_almost , //几乎空信号
8 output [ DEEP_WIDTH-1:0] waddr , //输出给RAM的地址
9 output reg [ DEEP_WIDTH:0] wptr , //格雷码地址指针
10 output wclken , //写RAM信号
11 input [ DEEP_WIDTH:0] wq2_rptr , //同步过来的读格雷码指针
12 input winc , //外部输入的使能信号
13 input wclk , //写时钟
14 input wrst_n //写复位
15
16 );
17 reg [ DEEP_WIDTH:0] waddr_reg ;//地址寄存器,5位
18 reg [ DEEP_WIDTH:0] wq2_rptr_bin ;//读指针同步到写时钟域后,从格雷码转换成二进制
19 reg [ DEEP_WIDTH:0] wgap_reg ;//寄存间隔的距离
20
21 //第一部分,写RAM使能信号的生成
22 assign wclken = winc &&(~ wfull );
23
24 //--------------------------------------//
25
26 //第二部分,产生RAM的地址和格雷码
27 always @(posedge wclk or negedge wrst_n)
28 if(wrst_n == 1'b0) begin
29 waddr_reg <= 5'd0;
30 end
31 else if( wclken )begin //地址自增一
32 waddr_reg <= waddr_reg + 5'd1 ;
33 end
34
35 //生成RAM地址
36 assign waddr = waddr_reg[ DEEP_WIDTH-1:0];
37
38 //生成格雷码
39 always @(posedge wclk or negedge wrst_n)
40 if(wrst_n == 1'b0) begin
41 wptr <= 5'd0;
42 end
43 else begin
44 wptr <= waddr_reg ^( waddr_reg >> 1'b1); //其实也就是位错之后的异或
45 //移位操作不代表移位寄存器
46 end
47
48 //-----------------------------------//
49
50 //第三部分
51
52 //将格雷码转换成二进制编码
53 always @( * )begin
54 wq2_rptr_bin[4] = wq2_rptr[4] ;
55 wq2_rptr_bin[3] = wq2_rptr[4] ^ wq2_rptr[3] ;
56 wq2_rptr_bin[2] = wq2_rptr[4] ^ wq2_rptr[3] ^ wq2_rptr[2] ;
57 wq2_rptr_bin[1] = wq2_rptr[4] ^ wq2_rptr[3] ^ wq2_rptr[2] ^ wq2_rptr[1] ;
58 wq2_rptr_bin[0] = wq2_rptr[4] ^ wq2_rptr[3] ^ wq2_rptr[2] ^ wq2_rptr[1] ^ wq2_rptr[0] ;
59 end
60
61 //产生满的间隔
62 always @(*)begin
63 if( waddr_reg[4] ^ wq2_rptr_bin[4] ) //最高位不相等的时候,也就是有一个是回卷了
64 wgap_reg = wq2_rptr_bin[3:0] - waddr_reg[3:0] ;
65 else //最高位相等的时候,也就是没有回卷,那么间隔就是FIFO_DEEP-( waddr_reg - wq2_rptr_bin)
66 wgap_reg = FIFO_DEEP + wq2_rptr_bin - waddr_reg ;
67 end
68
69 //根据间隔产生几乎满信号
70 always @(posedge wclk or negedge wrst_n)
71 if(wrst_n == 1'b0) begin
72 wfull_almost <= 1'b0 ;
73 end
74 else if( wgap_reg < GAP_WIDTH)begin
75 wfull_almost <= 1'b1 ;
76 end
77 else
78 wfull_almost <= 1'b0 ;
79
80 //产生满信号
81 assign wfull = (~(|wgap_reg ))||(( wgap_reg == 1)&&( winc ));//间隔为0的时候为满,间隔是1的时候还要写,也为满
82
83 endmodule