同步FIFO与异步FIFO的Verilog实现

Posted pure-z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同步FIFO与异步FIFO的Verilog实现相关的知识,希望对你有一定的参考价值。

技术图片
 1 module sync_fifo(
 2     input sys_clk,
 3     input sys_rst_n,
 4     input [7:0] wr_data,
 5     input wr_en,
 6     input rd_en,
 7 
 8     output reg [7:0] rd_data,
 9     output reg empty,
10     output reg full 
11 );
12 
13 parameter WIDTH = 8 ;
14 parameter ADDRSIZE = 3;
15 parameter DEPTH = 1 << ADDRSIZE ;
16 
17 reg [ADDRSIZE-1:0] wr_addr ;
18 reg [ADDRSIZE-1:0] rd_addr ;
19 reg [WIDTH-1:0] mem [DEPTH-1:0];
20 reg [DEPTH-1:0] count;
21 
22 //read
23 always @(posedge sys_clk or negedge sys_rst_n) begin
24     if (!sys_rst_n)
25         rd_data <= 0;
26     else if(rd_en && empty==0)
27         rd_data <= mem[rd_addr];
28 end
29 
30 //write
31 always @(posedge sys_clk ) begin
32     if(wr_en && full==0)
33     mem[wr_addr] <= wr_data;
34 end
35 
36 //更新读地址
37 always @(posedge sys_clk or negedge sys_rst_n) begin
38     if(!sys_rst_n)
39         rd_addr <= 0;
40     else if (rd_en && empty == 0)
41         rd_addr <= rd_addr + 1 ;
42 end
43 
44 //更新写地址
45 always@ (posedge sys_clk or negedge sys_rst_n) begin
46     if(!sys_rst_n)
47         wr_addr <= 0;
48     else if (wr_en && full == 0)
49         wr_addr <= wr_addr + 1 ;
50 end
51 
52 //更新标志位
53 always @(posedge sys_clk or negedge sys_rst_n) begin
54     if(!sys_rst_n)
55         count <= 0;
56     else begin
57         case({wr_en,rd_en})
58             2b00:count <= count;
59             2b01:
60                 if (count != 0)
61                 count <= count -1;
62             2b10:
63                 if (count != (DEPTH-1))
64                 count <= count +1;
65             2b11:count <= count;
66         endcase
67     end
68 end
69 
70 always@(count) begin
71     if (count == 0)
72         empty <= 1;
73     else
74         empty = 0;
75 end
76 
77 always@(count) begin
78     if (count == (DEPTH -1))
79         full <= 1;
80     else
81         full = 0;
82 end
83 
84 endmodule
sync_fifo
技术图片
  1 module  async_fifo
  2 #(
  3 parameter WIDTH = 8,   //数据位宽为8
  4 parameter ADDRSIZE = 8 //地址位宽为8,则FIFO深度为2^8
  5 )
  6 (
  7     input I_rst_n, //复位信号,低电平有效
  8     input I_w_clk, //写时钟
  9     input I_w_en,  //写使能    
 10     input I_r_clk, //读时钟
 11     input I_r_en,  //读使能
 12     input [WIDTH-1 : 0]I_data,//位宽为8的并行数据输入
 13     output [WIDTH-1 : 0]O_data,//并行数据输出
 14     output reg O_r_empty,//读空信号
 15     output reg O_w_full  //写满信号
 16 );
 17 
 18 (*KEEP = "TRUE"*)wire [ADDRSIZE-1 : 0] waddr,raddr;//读写地址
 19 reg [ADDRSIZE : 0] w_ptr,r_ptr;//读指针,写指针,格雷码(位宽为9,最高两位用来比较是否写了一圈)
 20 reg [ADDRSIZE : 0] wp_to_rp1,wp_to_rp2;//写指针同步至读时钟域,格雷码,1与2指的是经过两级D触发器,消除亚稳态
 21 reg [ADDRSIZE : 0] rp_to_wp1,rp_to_wp2;//读指针同步至写时钟域,格雷码,1与2指的是经过两级D触发器,消除亚稳态
 22 
 23 //RAM模块-----------------------------------------------------------------------------------------
 24 localparam RAM_DEPTH = 1 << ADDRSIZE; //RAM深度=2^ADDRSIZE, 深度=256
 25 reg [WIDTH-1 : 0] mem[RAM_DEPTH-1 : 0]; //声明一个位宽为8,深度为256的RAM
 26 
 27 always @(posedge I_w_clk)
 28 begin
 29     if(I_w_en)
 30         mem[waddr] <= I_data;
 31 end
 32 assign O_data = mem[raddr];
 33 
 34 //同步模块,将读指针同步至写时钟域-----------------------------------------------------------------------
 35 always @(posedge I_w_clk or negedge I_rst_n)
 36 begin
 37     if(!I_rst_n)
 38     begin
 39         rp_to_wp1 <= 0;
 40         rp_to_wp2 <= 0;
 41     end
 42     else
 43     begin
 44         rp_to_wp1 <= r_ptr;
 45         rp_to_wp2 <= rp_to_wp1;
 46     end
 47 end
 48 
 49 //同步模块,将写指针同步至读时钟域--------------------------------------------------
 50 always @(posedge I_r_clk or negedge I_rst_n)
 51 begin
 52     if(!I_rst_n)
 53     begin
 54         wp_to_rp1 <= 0;
 55         wp_to_rp2 <= 0;
 56     end
 57     else
 58     begin
 59         wp_to_rp1 <= w_ptr;
 60         wp_to_rp2 <= wp_to_rp1;
 61     end
 62 end
 63         
 64 //读空信号的产生------------------------------------------------------------------
 65 (*KEEP = "TRUE"*)reg  [ADDRSIZE : 0] raddr_cnt;
 66 (*KEEP = "TRUE"*)wire [ADDRSIZE : 0]raddr_cnt_next;
 67 (*KEEP = "TRUE"*)wire [ADDRSIZE : 0] r_ptr_next;
 68 (*KEEP = "TRUE"*)wire empty_val;
 69 always @(posedge I_r_clk or negedge I_rst_n)
 70 begin
 71     if(!I_rst_n)
 72     begin
 73         raddr_cnt <= 0;
 74         r_ptr <= 0;
 75     end
 76     else
 77     begin
 78         raddr_cnt <= raddr_cnt_next;
 79         r_ptr <= r_ptr_next;
 80     end
 81 end
 82 
 83 assign raddr_cnt_next = raddr_cnt + (I_r_en & ~O_r_empty);//读地址不断+1
 84 assign r_ptr_next = (raddr_cnt_next >> 1) ^ raddr_cnt_next; //地址计数(二进制)=>地址指针(格雷码)
 85 assign raddr = raddr_cnt[ADDRSIZE-1 : 0]; //实际地址比地址计数器少一位,最高位用来比较是否写了一圈
 86 assign empty_val = (r_ptr_next == wp_to_rp2);//若读指针与同步过来的写指针相等,则读空信号产生
 87 
 88 always @(posedge I_r_clk or negedge I_rst_n)
 89 begin
 90     if(!I_rst_n)
 91     O_r_empty <= 1b1;
 92     else
 93     O_r_empty <= empty_val;
 94 end
 95 
 96 
 97 //写满信号的产生------------------------------------------------------------------
 98 (*KEEP = "TRUE"*)reg  [ADDRSIZE : 0] waddr_cnt;
 99 (*KEEP = "TRUE"*)wire [ADDRSIZE : 0]waddr_cnt_next;
100 wire [ADDRSIZE : 0]w_ptr_next;
101 wire full_val;
102 
103 always @(posedge I_w_clk or negedge I_rst_n)
104 begin
105     if (!I_rst_n)
106     begin
107         waddr_cnt <= 0;
108         w_ptr <= 0;
109     end
110     else
111     begin
112         waddr_cnt <= waddr_cnt_next;
113         w_ptr <= w_ptr_next;
114     end
115 end
116 
117 assign waddr_cnt_next = waddr_cnt + (I_w_en & ~O_w_full);//写地址不断+1
118 assign w_ptr_next = (waddr_cnt_next >> 1) ^ waddr_cnt_next;
119 assign waddr = waddr_cnt[ADDRSIZE-1 : 0];//实际地址比地址计数器少一位,最高位用来比较是否写了一圈
120 assign full_val = (w_ptr_next == {~rp_to_wp2[ADDRSIZE : ADDRSIZE-1],rp_to_wp2[ADDRSIZE-2 : 0]});//若写指针与同步过来的读指针最高两位不同,其他位都相等,则写满信号产生
121 
122 always @(posedge I_w_clk or negedge I_rst_n)
123 begin
124     if(!I_rst_n)
125     O_w_full <= 1b0;
126     else
127     O_w_full <= full_val;
128 end
129 
130 endmodule
async_fifo

 

以上是关于同步FIFO与异步FIFO的Verilog实现的主要内容,如果未能解决你的问题,请参考以下文章

异步fifo的Verilog实现

verilog实现之同步FIFO

Verilog设计之异步fifo设计

Verilog设计之异步fifo设计

Verilog设计之异步fifo设计

Verilog实现同步FIFO