1.同步fifo的功能點
當fifo寫滿的時候结耀,輸出滿標志.
當fifo讀空的時候抑党,輸出空標志.
寫滿之后不能繼續(xù)寫,即有滿標志撬碟,禁止向ram寫入數(shù)據(jù)诞挨,防止數(shù)據(jù)混亂.
讀空之后不能繼續(xù)讀,讀完所有數(shù)據(jù)呢蛤,禁止重復讀.
對于空滿標志的判斷惶傻,設計的思想是,當讀指針等于寫指針加1其障,且同時有一個寫使能银室,這樣,就認為fifo已滿励翼,這是滿的臨界條件蜈敢,近乎滿∑В空標志也是同樣的原理抓狭。
2.設計代碼
module sync_fifo
(
clk ,
reset ,
fifo_wr ,
fifo_rd ,
wr_data ,
rd_data ,
full ,
empty
) ;
//*****************************parameter define*********************
//******************************************************************
parameter WH=8 ;//ram width
parameter DH=16 ;//ram deepth
parameter AD=4 ;//ram addr
//*****************************signal define*********************
//******************************************************************
input clk ;
input reset ;
input fifo_wr ;
input fifo_rd ;
input [WH-1:0] wr_data ;
output full ;
output empty ;
output [WH-1:0] rd_data ;
reg [AD-1:0] wr_pts ;
reg [AD-1:0] rd_pts ;
reg [WH-1:0] fifo_ram [DH-1:0] ;
wire valid_wr ;
wire valid_rd ;
reg [WH-1:0] rd_data ;
reg full ;
reg empty ;
reg [AD-1:0] wp ;//wr_pts gray code
reg [AD-1:0] wp_s ;//wr_pts+1 gray code
reg [AD-1:0] rp ;//rd_pts gray code
reg [AD-1:0] rp_s ;//rd_pts+1 gray code
wire [AD-1:0] wr_pts_s0 ;//wr_pts interal signal
wire [AD-1:0] wr_pts_s1 ;//wr_pts+1 interal signal
wire [AD-1:0] rp_pts_s0 ;//rd_pts interal signal
wire [AD-1:0] rp_pts_s1 ;//rd_pts+1 interal signal
integer i ;
//*****************************code brgin*********************
//*****************************part1:ram************************
always@(posedge clk or negedge reset)
if(!reset)
rd_data<={WH{1'd0}};
else if(valid_rd)
rd_data<=fifo_ram[rd_pts];
else
rd_data<={WH{1'd0}};
always@(posedge clk or negedge reset)
if(!reset)
begin
for(i=0;i<DH;i=i+1)
fifo_ram[i]<=0;
end
else if (valid_wr)
fifo_ram[wr_pts]<=wr_data;
else
fifo_ram[wr_pts]<=fifo_ram[wr_pts];
//*****************************part2:full/empty*********************
//*******************************************************************
always@(posedge clk or negedge reset)
if(!reset)
full<=1'd0;
else if(fifo_wr&&(rp==wp_s))
full<=1'd1;
else
full<=full;
always@(posedge clk or negedge reset)
if(!reset)
empty<=1'd1;
else if(fifo_rd&&(wp==rp_s))
empty<=1'd1;
else
empty<=empty;
//*****************************part3:wr/rd*********************
//*******************************************************************
assign valid_wr=fifo_wr&&(~full);
assign valid_rd=fifo_rd&&(~empty);
//******************************part4:wr/rd_pts pro**********************
//**********************************************************************
always@(posedge clk or negedge reset)
if(!reset)
wr_pts<={AD{1'd0}};
else if(valid_wr)
wr_pts<=wr_pts+1;
else if(wr_pts==15)
wr_pts<={AD{1'd0}} ;
else
wr_pts<=wr_pts ;
always@(posedge clk or negedge reset)
if(!reset)
rd_pts<={AD{1'd0}};
else if(valid_rd)
rd_pts<=rd_pts+1;
else if(rd_pts==15)
rd_pts<={AD{1'd0}} ;
else
rd_pts<=rd_pts ;
//*********************************part5:b-to-g************************
//*************************************************************************
assign wr_pts_s0=wr_pts;
assign wr_pts_s1=wr_pts+1;
assign rp_pts_s0=rd_pts;
assign rp_pts_s1=rd_pts+1;
always@(*)
begin
wp[3]=wr_pts_s0[3];
wp[2]=wr_pts_s0[3]^wr_pts_s0[2];
wp[1]=wr_pts_s0[2]^wr_pts_s0[1];
wp[0]=wr_pts_s0[1]^wr_pts_s0[0];
end
always@(*)
begin
wp_s[3]=wr_pts_s1[3];
wp_s[2]=wr_pts_s1[3]^wr_pts_s1[2];
wp_s[1]=wr_pts_s1[2]^wr_pts_s1[1];
wp_s[0]=wr_pts_s1[1]^wr_pts_s1[0];
end
always@(*)
begin
rp[3]=rp_pts_s0[3];
rp[2]=rp_pts_s0[3]^rp_pts_s0[2];
rp[1]=rp_pts_s0[2]^rp_pts_s0[1];
rp[0]=rp_pts_s0[1]^rp_pts_s0[0];
end
always@(*)
begin
rp_s[3]=rp_pts_s1[3];
rp_s[2]=rp_pts_s1[3]^rp_pts_s1[2];
rp_s[1]=rp_pts_s1[2]^rp_pts_s1[1];
rp_s[0]=rp_pts_s1[1]^rp_pts_s1[0];
end
endmodule
難點在于空滿標志的判斷,代碼里對空滿標志的判斷是一個近乎滿造烁,近乎空的狀態(tài).
3.測試波形
fifo設計要保證寫指針追不上讀指針 否过,讀指針追不上寫指針午笛;
在fifo將寫0,將讀1的時候苗桂,下一拍拉高full药磺,告訴user,fifo已滿(近乎滿的臨界狀態(tài),不要在發(fā)送寫指令了)
如果user繼續(xù)發(fā)送寫指令誉察,則繼續(xù)輸出full標志与涡,同時寫指針不再自加,有效的寫命令不會生成持偏,user發(fā)送過來的數(shù)據(jù)不會被寫入到ram里.
直到有讀指針把full拉低驼卖。才可以繼續(xù)寫入數(shù)據(jù).