|
0111 1000
格雷码可保证每次一次跳变,降低了毛刺产生的概率,如果用次地址去判断空满标志,极大的提高了标志的准确性
格雷码的空满标志判断
0 110 1110
0 101 1101
full=wr_addr[3:0] == {~rd_addr[3:2],rd_addr[1:0]};
当写地址和读地址的最高位和此高位不同,其余位相同的时候则可判断FIFO满
empty= wr_addr[3:0] == rd_addr[3:0];
当写地址和读地址的最高位和此高位相同,其余位相同的时候则可判断FIFO满
module fifo
(
input rst_n,
input rd_clk,
input rd_en,
output [7:0]dout,
input wr_clk,
input wr_en,
input [7:0]din,
output full,
empty
);
//定义FIFO深度为8
reg [7:0]fifo_rem[7:0];//数组的定义
reg [3:0] wr_addr,rd_addr;
//FIFO的写
always @(posedge wr_clk or negedge rst_n)
if(~rst_n)
wr_addr <=4’d0;
else if(wr_en&&(~full))begin
if(wr_addr==4’b1111)
wr_addr <=4’d0;
else
wr_addr <= wr_addr +1’b1;
fifo_rem[wr_addr[2:0]]<= din;
end
//fifo读操作
assign dout= fifo_rem [rd_addr[2:0]];
always @(posedge rd_clk or negedge rst_n)
if(~rst_n)
rd_addr<=4’d0;
else if(rd_en&&(~empty))begin
if(rd_addr==4’b1111)
rd_addr<=4’d0;
else
rd_addr<= rd_addr+1’b1;
end
//****************************************************************************、、//空满标志判断
wire [3:0] rd_addr_g, wr_addr_g;
assign wr_addr_g= wr_addr ^{1’b0, wr_addr [3:1]};//写地址格雷码转换
assign rd_addr_g= rd_addr ^{1’b0, rd_addr [3:1]};//读地址格雷码转换
//地址同步
reg [3:0] rd_addr_g_r1, rd_addr_g_r2;//读地址同步
alwqays @(posedge wr_clk)begin
rd_addr_g_r1<= rd_addr_g;
rd_addr_g_r2<= rd_addr_g_r1;
end
reg [3:0] wr_addr_g_r1, wr_addr_g_r2;//写地址同步
alwqays @(posedge rd_clk)begin
wr_addr_g_r1<= wr_addr_g;
wr_addr_g_r2<= wr_addr_g_r1;
end
assign full= (wr_addr_g== {~rd_addr_g_r2[3:2], rd_addr_g_r2[1;0]}?1’b1:1’b0;
assing empty=( rd_addr_g== wr_addr_g_r2)?1’b1:1’b0;
endmodule
|
|