【IC设计】同步FIFO设计(Verilog源码、参数化设计、面试必备)

设计思想

FIFO也就是先进先出的队列,是一种特殊的RAM,特殊在读写地址默认是自增1,所以FIFO内部管理读写地址,不需要暴露读写地址端口。
同步FIFO指读写使用同一个时钟,异步FIFO则读写使用不同的时钟,同步FIFO相对简单一些,异步FIFO还涉及到亚稳态、格雷码和二进制的转化等问题。

FIFO的难点在于空满的判断,这里同步FIFO的空满判断有两种方式,一是使用计数器,这个很简单,fifo_cnt等于0就为空,等于深度就满,二是使用读写指针进行判断,这里我使用第一种方式。

下面给出了经典同步fifo设计的源码,用来面试手撕,采用了参数化、$clog2函数,代码很规范也很好记。
总结一下博客,重点强调下记忆的方法,方便面试手撕代码,如有错误的地方恳请指正!

端口

分三方面记忆,时钟复位+读+写。注意读写不光有数据,还有使能和空满信号。

代码块

一共可以分为六个代码块:

  • 读数据部分有读指针always块、读操作always块;
  • 写数据部分有写指针always块、写操作always块;
  • 空满判断部分有fifo元素数量always块、空满判断assign块;

寄存器

包括:

  • fifo_buffer存储数据
  • fifo_cnt记录当前fifo元素数量
  • rd_pointer和wr_pointer指针

同步FIFO代码

module syn_fifo
#
(
	parameter DATA_WIDTH = 8,
	parameter DATA_DEPTH = 8,
)
(
	input clk				,
	input rst_n				,
	
	// read
	output [DATA_WIDTH - 10] read_data		,
	input  rd_en								,
	output rd_empty								,
	
	// write
	input [DATA_WIDTH - 10] write_data		,
	input  wr_en								,
	output wr_full								,
);
	
	// Parameters
	parameter DEPTH_WIDTH = $clog2(DATA_DEPTH)  ;

	// Regs
	reg [DATA_WIDTH - 10] fifo_buffer [0 : DATA_DEPTH - 1]  ;
	reg [DATA_DEPTH     : 0] fifo_cnt						   ;
	reg [DATA_DEPTH - 1 : 0] wr_pointer,rd_pointer			   ;

	// read pointer
	always@(posedge clk or negedge rst_n) begin
		if(~rst_n) begin
			read_pointer <= 'b0;
		end
		else begin
			if( rd_en && !rd_empty) begin
				if( rd_pointer == DATA_DEPTH - 1) begin
					rd_pointer <= 'b0;
				end else begin
					rd_pointer <= rd_pointer + 1'b1;
				end
			end
		
		end
	end
	
	// read operation
	always@(posedge clk or negedge rst_n) begin
		if(~rst_n) begin
			read_data <= 'b0;
		end
		else begin
			read_data <= fifo_buffer[rd_pointer];
		end
	end
	
	// write pointer
	always@(posedge clk or negedge rst_n) begin
		if(~rst_n) begin
			wr_pointer <= 'b0;
		end
		else begin
			if( wr_en && !wr_full) begin
				if( wr_pointer == DATA_DEPTH - 1) begin
					wr_pointer <= 'b0;
				end else begin
					wr_pointer <= wr_pointer + 1'b1;
				end
			end
		
		end
	end
	
	// write operation
	always@(posedge clk or negedge rst_n) begin
		if(~rst_n) begin
			fifo_buffer[wr_pointer] <= 'b0;
		end
		else begin
			fifo_buffer[wr_pointer]  <= read_data;
		end
	end
	
	// current fifo_cnt in fifo_buffer
	always@(posedge clk or negedge rst_n) begin
		if(~rst_n) begin
			fifo_cnt <= 'b0;
		end
		else begin
			fifo_cnt <= fifo_cnt + 1'b1;
		end
	end
	
	
	// empty and full
	assign full   = (fifo_cnt == DATA_DEPTH);
	assign empty  = (fifo_cnt == 0	       );


endmodule
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农民真快落

我琢磨着也没人给我打赏呀。。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>