异步FIFO的设计

  1. 基于真双口RAM。可以实现同时在一端写,另一端读的功能,两端的时钟可以不同。
  2. 什么时候读/写?-使能+空满标志的判断
  3. 空满如何判断?
    读地址to格雷码-同步到写时钟域,与写地址比较-产生写满标志
  4. 如何在二进制下比较地址指针,得到空满信号?
    读写指针均增加一位标志信号,当读写指针相等,FIFO为空;写指针领先读指针一圈,此时两者MSB不同,其余各位相同,FIFO为满
  5. 如何在格雷码下比较地址指针,得到空满信号?
    空不变。最高位和次高位不同,其余位相同,代表满
    注意看0-8,1-9,2-10
    在这里插入图片描述

框架图
在这里插入图片描述

module asyn_fifo(
input clkw,clkr,rst_n,
input w_en,r_en,
input [7:0] data_in,
output 					w_full,r_empty,
output reg		[7:0] 	data_out
);

reg [7:0] mem[15:0]; //16x8 RAM
reg [4:0] w_addr,r_addr,w_addr_g,r_addr_g;
reg [4:0] w_addr_gr[1:0];
reg [4:0] r_addr_gw[1:0];

always@(posedge clkw or negedge rst_n) begin
	if(!rst_n) begin
	w_addr <= 0;
	end
	if(w_en==1 && w_full==0) begin
	mem[w_addr[3:0]] <= data_in;
	w_addr <= w_addr + 1;
	end
end
always@(posedge clkr or negedge rst_n) begin
	if(!rst_n) begin
	r_addr <= 0;
	end
	if(r_en==1 && r_empty==0) begin
	data_out <= mem[r_addr[3:0]]
	r_addr <= r_addr + 1;
	end
end

assign w_addr_g = w_addr ^ (w_addr>>1);
assign r_addr_g = r_addr ^ (r_addr>>1);

always@(posedge clkw or negedge rst_n) begin
	if(!rst_n) begin r_addr_gw[0]<=0; r_addr_gw[1]<=0; end
	else begin r_addr_gw[0]<=r_addr_g; r_addr_gw[1]<=r_addr_gw[0]; end
end
always@(posedge clkr or negedge rst_n) begin
	if(!rst_n) begin w_addr_gr[0]<=0; w_addr_gr[1]<=0; end
	else begin w_addr_gr[0]<=w_addr_g; w_addr_gr[1]<=w_addr_gr[0]; end
end

assign r_empty = r_addr_g == w_addr_gr[1];
assign w_full = w_addr_g == {~r_addr_gw[1][4:3],r_addr_gw[1][2:0]};
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值