FIFO(原理、框图、代码、深度计算)
//写地址使能
assign wen=wr_en&&(!full);
//写地址二进制到格雷码的转换
always@(posedge wr_clk or negedge wr_reset)
if(wr_reset)
waddr_gray<={(ADDR_WIDTH+1){1b0}};
else waddr_gray<=waddr^{1b0,[waddr[ADDR_WIDTH:1]]};//相当于右移一位后与原来的二进制异或
//读地址格雷码转换为二进制码
always@(*)
begin
raddr_gray2bin={raddr_gray_sync_d[4],
raddr_gray_sync_d[4]^raddr_gray_sync_d[3],
raddr_gray_sync_d[4]^raddr_gray_sync_d[3]^raddr_gray_sync_d[2],
raddr_gray_sync_d[4]^raddr_gray_sync_d[3]^raddr_gray_sync_d[2]^raddr_gray_sync_d[1],
raddr_gray_sync_d[4]^raddr_gray_sync_d[3]^raddr_gray_sync_d[2]^raddr_gray_sync_d[1]^raddr_gray_sync_d[0]
};
End
这个图片可以帮助理解rd_gap和wr_gap计算的原因:
/状态生成/ //写指针与读指针间隔计算,在写时钟域的情况,判断满信号full和将满信号almost full的产生 always@(*)//地址宽度为4bit,扩展一位后为5bit begin if(waddr[4]^raddr_gray2bin[4])//相同为0,相异为1;需要判断还有多少空格,看看啥时候写满 wr_gap=raddr_gray2bin[3:0]-waddr[3:0];//最高位不相同的情况 else wr_gap=FIFO_DEEP+raddr_gray2bin-waddr;//最高位相同的情况 end //almost_full信号的产生 always@(posedge wr_clk or wr_reset) begin if(wr_reset) almost_full<=1b0; else if(wr_gap<ALMOST_FULL_GAP)//空格子比规定的格子少了 almost_full<=1b1; else almost_full<=1b0; end //full信号的产生 always@(posedge wr_clk or wr_reset) begin if(wr_reset) full<=1b0; else if(wr_gap==1&&wen) full<=1b1; else full<=1b0; end //读指针和写指针的间隔,在读时钟域,读空,计算的是还有几个格子不是空的 always@(posedge rd_clk or negedge rd_reset) begin if(rd_reset) ra_gap<=0; else ra_gap<=waddr_gray2bin-raddr; end //almost_empty信号的产生 always@(posedge rd_clk or negedge rd_reset) begin if(rd_reset) almost_empty<=0; else if(ra_gap<ALMOST_EMPTY_GAP)// almost_empty<=1; else almost_empty<=0; end //empty信号的产生 always@(posedge rd_clk or negedge rd_reset) begin if(rd_reset) empty<=0; else if(rd_en&&rd_gap==1) empty<=1; else empty<=0;
4、Fifo深度 Fifo的最小深度是指写入数据的个数减去读出数据后得到的fifo需要暂存的数据个数。 讨论fifo深度有一个隐含的条件:fifo写和读的吞吐量要相同。 每X个时钟读出Y个数据。
FIFO深度可以去看《FPGA深度解析》上面详细有具体例子讲解fifo深度的计算。
