异步FIFO的跨时钟域同步问题,求大神讲解
时间:10-02
整理:3721RD
点击:
我自己写了一个FIFO,但是我总是不理解Paper中讲的要把读写指针同步,如果我将两个不同时钟产生的读写地址直接比较,产生读写,请问这个亚稳态是怎么产生的,不要复制网上的那些东西,我都看了买就是不太懂,才问的,下面是我的代码
//asysfifo 8*8bit
module asys_fifo(
w_clk,r_clk,w_en,r_en,rst,din,dout,empty,full);
input w_clk,r_clk;
input w_en,r_en;//high valid
input rst; //low valid
input [7:0] din;
output [7:0] dout;
output empty,full;//empty,full flag bit,high valid
reg empty,full;
reg [7:0] dout;
//internal signal defenition
reg [7:0] asys_fifo[7:0]; //asys_fifo ram
reg [2:0] w_addr; //write address
reg [2:0] r_addr; //read address
//MSB defenition
reg w_msb;
reg r_msb;
//write data read data
always @(posedge w_clk)
if(w_en&&!full)
asys_fifo[w_addr]<=din;
always @(posedge r_clk)
if(r_en&&!empty)
dout<=asys_fifo[r_addr];
else
dout<=8'dz;
//write address read address and w_msb r_msb generation
always @(posedge w_clk,negedge rst)
if(!rst)
begin
w_addr<=3'b000;
w_msb<=0;
end
else if(w_en&&!full)
begin
if(w_addr==3'b111)
begin
w_addr<=3'b000;
w_msb<=!w_msb; //MSB qu fan
end
else
begin
w_addr<=w_addr+3'd1;
w_msb<=w_msb;
end
end
else
begin
w_addr<=w_addr;
w_msb<=w_msb;
end
always @(posedge r_clk,negedge rst)
if(!rst)
begin
r_addr<=3'b000;
r_msb<=0;
end
else if(r_en&&!empty)
begin
if(r_addr==3'b111)
begin
r_msb<=!r_msb;
r_addr<=3'b000;
end
else
begin
r_msb<=r_msb;
r_addr<=r_addr+3'd1;
end
end
else
begin
r_msb<=r_msb;
r_addr<=r_addr;
end
//empty,full flag generation
//empty flag generation
always @(*)
if(!rst)
empty<=1;
else if({r_msb,r_addr}=={w_msb,w_addr})
empty<=1;
else
empty<=0;
//full flag generation
always @(*)
if(!rst)
full<=0;
else if((r_msb!=w_msb)&&(r_addr==w_addr))
full<=1;
else
full<=0;
endmodule
//asysfifo 8*8bit
module asys_fifo(
w_clk,r_clk,w_en,r_en,rst,din,dout,empty,full);
input w_clk,r_clk;
input w_en,r_en;//high valid
input rst; //low valid
input [7:0] din;
output [7:0] dout;
output empty,full;//empty,full flag bit,high valid
reg empty,full;
reg [7:0] dout;
//internal signal defenition
reg [7:0] asys_fifo[7:0]; //asys_fifo ram
reg [2:0] w_addr; //write address
reg [2:0] r_addr; //read address
//MSB defenition
reg w_msb;
reg r_msb;
//write data read data
always @(posedge w_clk)
if(w_en&&!full)
asys_fifo[w_addr]<=din;
always @(posedge r_clk)
if(r_en&&!empty)
dout<=asys_fifo[r_addr];
else
dout<=8'dz;
//write address read address and w_msb r_msb generation
always @(posedge w_clk,negedge rst)
if(!rst)
begin
w_addr<=3'b000;
w_msb<=0;
end
else if(w_en&&!full)
begin
if(w_addr==3'b111)
begin
w_addr<=3'b000;
w_msb<=!w_msb; //MSB qu fan
end
else
begin
w_addr<=w_addr+3'd1;
w_msb<=w_msb;
end
end
else
begin
w_addr<=w_addr;
w_msb<=w_msb;
end
always @(posedge r_clk,negedge rst)
if(!rst)
begin
r_addr<=3'b000;
r_msb<=0;
end
else if(r_en&&!empty)
begin
if(r_addr==3'b111)
begin
r_msb<=!r_msb;
r_addr<=3'b000;
end
else
begin
r_msb<=r_msb;
r_addr<=r_addr+3'd1;
end
end
else
begin
r_msb<=r_msb;
r_addr<=r_addr;
end
//empty,full flag generation
//empty flag generation
always @(*)
if(!rst)
empty<=1;
else if({r_msb,r_addr}=={w_msb,w_addr})
empty<=1;
else
empty<=0;
//full flag generation
always @(*)
if(!rst)
full<=0;
else if((r_msb!=w_msb)&&(r_addr==w_addr))
full<=1;
else
full<=0;
endmodule
自己顶起来,不敢沉底
时钟相位不同步,可能踩不到正确数据