verilog实现FIFO(2)

高位扩展法

module sync_fifo_ptr #(
	parameter DEPTH = 16,
	parameter WIDTH = 8
)(
	input wire 				clk,
	input wire 				rst_n,
	
	input wire 				i_wen,
	input wire [WIDTH-1:0] 	i_wdata,
	
	input wire 				i_ren,
	output reg [WIDTH-1:0]	o_rdata,
	
	output 	wire			o_empty,
	output 	wire			o_full
	
);

reg [$clog2(DEPTH):0] w_addr;
reg [$clog2(DEPTH):0] r_addr;

wire [$clog2(DEPTH)-1:0] w_addr_true;
wire [$clog2(DEPTH)-1:0] r_addr_true;

wire w_addr_ptr;
wire r_addr_ptr;


assign {w_addr_ptr,w_addr_true} = w_addr;
assign {r_addr_ptr,r_addr_true} = r_addr;



reg [WIDTH-1:0] fifo_buffer[DEPTH-1:0]; //鐢ㄤ簩缁存暟缁勫疄鐜癛AM
//counter


//write
always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		begin
			w_addr <= 'd0;
		end
	else if(i_wen && !o_full)
			begin
			w_addr <= w_addr + 1'b1;
			fifo_buffer[w_addr_true] <= i_wdata;
			end
end


//read
always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		begin
			r_addr <= 'd0;
		end
	else if(i_ren && !o_empty)
		  begin
              o_rdata <= fifo_buffer[r_addr_true];
		      r_addr  <= r_addr+1'b1;
		  end
end


assign o_empty = (w_addr == r_addr)?1'b1:1'b0;
assign o_full  = ((w_addr_true == r_addr_true) && (w_addr_ptr != r_addr_ptr))?1'b1:1'b0;

endmodule

测试

`timescale 1ns/1ns	//时间单位/精度
 
//------------<模块及端口声明>----------------------------------------
module tb_sync_fifo_ptr();
 
parameter   WIDTH = 8  ;		//FIFO位宽
parameter   DEPTH = 16 ;		//FIFO深度
 
reg									clk		;
reg									rst_n	;
reg		[WIDTH-1:0]			data_in	;
reg									rd_en	;
reg									wr_en	;
						
wire	[WIDTH-1:0]			data_out;	
wire								empty	;	
wire								full	;
 
 
//------------<例化被测试模块>----------------------------------------
sync_fifo_ptr
#(
	.WIDTH	(WIDTH),			//FIFO位宽
    .DEPTH	(DEPTH)			//FIFO深度
)
sync_fifo_ptr_inst(
	.clk		(clk		),
	.rst_n		(rst_n		),
	.i_wdata	(data_in	),
	.i_ren		(rd_en		),
	.i_wen		(wr_en		),
                 
	.o_rdata	(data_out	),	
	.o_empty		(empty		),	
	.o_full		(full		)
);
 
//------------<设置初始测试条件>----------------------------------------
initial begin
	clk = 1'b0;					//初始时钟为0
	rst_n <= 1'b0;				//初始复位
	data_in <= 'd0;
	wr_en <= 1'b0;
	rd_en <= 1'b0;
//重复8次写操作,让FIFO写满 	
	repeat(8) begin
		@(negedge clk)begin
			rst_n <= 1'b1;		
			wr_en <= 1'b1;
			data_in <= $random;	//生成8位随机数
		end
	end
//重复8次读操作,让FIFO读空 	
	repeat(8) begin
		@(negedge clk)begin		
			wr_en <= 1'b0;
			rd_en <= 1'd1;
		end
	end
//重复4次写操作,写入4个随机数据	
	repeat(4) begin
		@(negedge clk)begin		
			wr_en <= 1'b1;
			data_in <= $random;	//生成8位随机数
			rd_en <= 1'b0;
		end
	end
//持续同时对FIFO读写,写入数据为随机数据	
	forever begin
		@(negedge clk)begin		
			wr_en <= 1'b1;
			data_in <= $random;	//生成8位随机数
			rd_en <= 1'b1;
		end
	end
end
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk;			//系统时钟周期20ns
endmodule
posted @ 2025-02-21 14:56  心随鸥鹭齐舒羽  阅读(48)  评论(0)    收藏  举报