同步FIFO

  • FIFO是( first input first output)一般用作不同时钟域的缓冲器,顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加一完成,根据读和写的时钟是否为同一时钟分为同步FIFO和异步FIFO。
  • FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的情况下,不 能进行写操作。在空的状态下不能进行读操作。
  • 典型的同步FIFO由三部分组成:
  1. FIFO写控制逻辑:用于产生FIFO写地址、写有效信号,同时产生FIFO写满、写错等状态信号。
  2. FIFO读控制逻辑:用于产生FIFO读地址、读有效信号,同时产生FIFO读空、读错等状态信号。
  3. FIFO存储实体(memory、reg)

结构图如下:
在这里插入图片描述
设计主要分为以下两部分:

  • 读写过程的地址控制
  1. 定义reg来存储FIFO写数据,读数据。
  2. FIFO写操作:写地址加一。
  3. FIFO读操作:读地址加一。
  • 空满状态的产生
    引入计数器,count计数器存储FIFO数据的的个数。
  1. 写操作:count+1。
  2. 读操作 :count-1。
  3. 写满:count=fifo深度,写满为full。
  4. 读空:count=0,读空为empty。

设计代码如下:

module syn_fifo
(
	input		clk;
	input		rst_n;

	input		wr_cs;
	input		wr_en;
	input  [7:0]wr_data;	
	output	reg	full;

	input		rd_cs;
	input		dr_en;
	output  [7:0]rd_data;	
	output	reg	empty;
);
	reg		[7:0]	wr_addr;
	reg		[7:0]	rd_addr;
	reg		[8:0]	count;
	reg		[7:0]	fifo_ram   [255:0];
	integer	i;
		
//写数据
always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			begin
				for(i = 0; i < 128;i = i + 1)
					fifo_ram[i] <= {8{1'b0}};
			end
		else
			if(wr_en&&(!full))
				fifo_ram[wr_addr] <= wr_data;
	end

//读数据
always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			rd_data <= {8{1'b0}};
		else if(rd_en&&(!empty))
			rd_data <= fifo_ram[rd_addr];
	end

//读写控制
always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			wr_addr <= {8{1'b0}};
		else if(wr_en&&(!full))
			wr_addr <= wr_addr +1'b1;
	end
always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			rd_addr <= {8{1'b0}};
		else if(rd_en&&(!empty))
			rd_addr <= rd_addr +1'b1;
	end

//数据计数器  读一次减1,写一次加1
always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			count <= 9'b0;
		else if(wr_en&&(!full))
			count <= count + 1;
		else if(rd_en&&(!empty))
			count <= count - 1;
	end
//空满判断
assign	full = (count == {8{1'b1} + 1});
assign	empty = (count == 0);
endmodule