天天看点

数字IC秋招手撕代码(四)同步FIFO实现题目分析代码

数字IC秋招手撕代码(四)同步FIFO实现

  • 题目
  • 分析
  • 代码

题目

用verilog实现一个同步FIFO,深度16,数据位宽8bit

分析

由于同步FIFO的读写两端时钟是同步的,所以不需要异步考虑。同步FIFO中需要设计的部分是读指针,写指针,空满状态,读数据和写数据和ram的数据流通。

代码

modual Syn_fifo
#(
	parameter						DATA_WIDTH	=	8,
	parameter						ADDR_WIDTH	=	4,
	parameter						RAM_DEPTH	=	(1 << ADDR_WIDTH)
)
(
	input							clk,
	input							rstn,
	input	[DATA_WIDTH-1:0]		din,
	input							wr_en,
	input							rd_en,
	output	reg	[DATA_WIDTH-1:0]	dout,
	output							empty,
	output							full
)

reg	[ADDR_WIDTH-1:0]	wr_cnt;
reg	[ADDR_WIDTH-1:0]	rd_cnt;
reg	[ADDR_WIDTH-1:0]	status_cnt;
reg	[DATA_WIDHT-1:0]	ram_data;

assign	empty = status_cnt == (RAM_DEPTH-1) ? 1'b1 : 1'b0;
assign	full  = status_cnt == 0 ? 1'b1 : 1'b0;

reg		rd_en_dly;
always @(posedge clk)begin		//此处为了ram的数据到FIFO输出的一拍延时
	if(!rstn)
		rd_en_dly <= 0;
	else
		rd_en_dly <= rd_en;
end

always @(posedge clk)begin
	if(!rstn)
		wr_cnt <= 0;
	else if(wr_cnt==RAM_DEPTH-1)
		wr_cnt <= 0;
	else if(wr_en)
		wr_cnt <= wr_cnt + 1;
end

always @(posedge clk)begin
	if(!rstn)
		rd_cnt <= 0;
	else if(rd_cnt==RAM_DEPTH-1)
		rd_cnt <= 0;
	else if(rd_en)
		rd_cnt <= rd_cnt + 1;
end

always @(posedge clk)begin
	if(!rstn)
		dout <= 0;
	else if(rd_en_dly)
		dout <= ram_data;
end

always @(posedge clk)begin
	if(!rstn)
		status_cnt <= 0;
	else if(rd_en && !wr_en && (status_cnt != 0))
		status_cnt <= status_cnt - 1;
	else if(!rd_en && wr_en && (status_cnt != RAM_DEPTH-1))
		status_cnt <= status_cnt + 1;
end

integer	i;
reg	[DATA_WIDTH-1:0]	register	[RAM_DEPTH-1:0];
always @(posedge clk)begin
	if(!rstn)begin
		for(i=0;i<RAM_DEPTH;i=i+1)
			register[i] <= 0;
	end
	else if(wr_en)
		register[i] <= din;
end

always @(posedge clk)begin
	if(!rstn)
		data_ram <= 0;
	else if(rd_en)
		data_ram <= register[rd_cnt];
end

endmodule
           

继续阅读