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深度的计算。

经验分享 程序员 微信小程序 职场和发展