同步FIFO的编写

以一个16x8bit的FIFO为例。

module sync_fifo(
	input clk,
	input rst_n,
	input wr_en,
	input[7:0] wr_data,
	input rd_en,
	output reg[7:0] rd_data,
	output full,
	output empty
);
	reg[3:0] wr_addr, rd_addr;
	reg[7:0] ram[0:15];
	reg full_reg, empty_reg;
	reg[4:0] cnt;
	
	//---------------------- 读写操作 --------------------------
	always@(posedge clk)begin
		if(wr_en == 1'b1)
			ram[wr_addr] <= wr_data;
	end
	always@(posedge clk)begin
		if(rd_en == 1'b1)
			rd_data <= ram[rd_addr];
	end
	
	//--------------------读写RAM地址计数器---------------------
	always@(posedge clk)begin
		if(rst_n == 1'b0)
			wr_addr <= 4'b0000;
		else if(wr_en == 1'b1 && full_reg == 1'b0)
			wr_addr <= wr_addr + 1'b1;
	end
	always@(posedge clk)begin
		if(rst_n == 1'b0)
			rd_addr <= 4'b0000;
		else if(rd_en == 1'b1 && empty_reg == 1'b0)
			rd_addr <= rd_addr + 1'b1;
	end
	
	//----------------------full和empty标志-----------------------------
	always@(posedge clk)begin
		if(rst_n == 1'b0)
			cnt <= 5'b0000;
		else begin 
			case({wr_en,rd_en})
				2'b01: 
					if(cnt != 5'b00000)
						cnt <= cnt - 1'b1;
				2'b10:
					if(cnt != 5'b10000)
						cnt <= cnt + 1'b1;
				default: 
					cnt <= cnt;
			endcase
		end
	end
	
	always@(cnt)begin
		if(rst_n == 1'b0)
			full_reg <= 1'b0;
		else if(cnt == 5'b10000)
			full_reg <= 1'b1;
		else
			full_reg <= 1'b0;
	end
	
	always@(cnt)begin
		if(rst_n == 1'b0)
			empty_reg <= 1'b1;
		else if(cnt == 5'b00000)
			empty_reg <= 1'b1;
		else
			empty_reg <= 1'b0;
	end
	assign full = full_reg;
	assign empty = empty_reg;
	
endmodule

testbench编写:

`timescale 1ns/1ns
`define clock_period 10

module tb_sync_fifo;

	reg clk;
	reg rst_n;
	
	reg rd_en,wr_en;
	wire full,empty;
	reg[7:0] wr_data;
	wire rd_data;
	integer i;
	
	sync_fifo inst1(
		.clk(clk),
		.rst_n(rst_n),
		.wr_en(wr_en),
		.wr_data(wr_data),
		.rd_en(rd_en),
		.rd_data(rd_data),
		.full(full),
		.empty(empty)
	);
	
	initial clk = 1'b0;
	always #(`clock_period/2) clk = ~clk;
	
	initial begin
		rst_n = 1'b0;
		wr_en = 0;
		rd_en = 0;
		wr_data = 8'h00;
		#(`clock_period*10+1);
		rst_n = 1'b1;
		#(`clock_period*10);
		wr_fifo(4'b0000,8'b01100101);
		#(`clock_period*10);
		rd_fifo;
		$stop;
	end
	
	task wr_fifo;
		input[3:0] addr;
		input[7:0] data;
		begin
			for(i = 0; i < 16; i = i + 1)begin
				wr_en = 1;
				wr_data = data;
				#(`clock_period);
			end
			wr_en = 0;
		end
	endtask
	
	task rd_fifo;
		begin
			for(i = 0; i < 16; i = i + 1)begin
				rd_en = 1;
				#(`clock_period);
			end
			rd_en = 0;
		end
	endtask
	
endmodule


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值