verilog实现同步FIFO

verilog实现同步FIFO:


同步FIFO是一种先进先出的数据缓存器,在逻辑设计里面用的非常多,FIFO 设计可以说是逻辑设计人员必须掌握的常识性设计。FIFO 一般用在隔离两边读写带宽不一致,或者位宽不一样的地方。
FIFO 与普通存储器 RAM 的区别是没有外部读写地址线,使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加 1 完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。 FIFO 本质上是由 RAM 加读写控制逻辑构成的一种先进先出的数据缓冲器。

下面设计一个16*8(16是深度,8是位宽)的FIFO:

module syn_fifo(

	input	clk,
	input	rst_n,
	
	input	wr_en,
	input	[7:0]	data_in,
	output	full,
	
	input	rd_en,
	output	reg	[7:0]	data_out,
	output	empty

);

reg	[3:0]	wr_addr;
reg	[3:0]	rd_addr;
reg	[3:0]	cnt;

parameter	max_cnt = 4'd15;
reg	[7:0]	fifo[max_cnt:0]; //16*8(16是深度,8是位宽)的fifo

assign empty = (cnt==4'd0) ? 1'b1:1'b0;
assign full = (cnt==max_cnt) ? 1'b1:1'b0;

//写数据
integer i;
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		for(i=0;i<max_cnt+1'b1;i=i+1)
			fifo[i] <= 8'd0;
	end
	else if(wr_en && (full==1'b0))
		fifo[wr_addr] <= data_in;
	else
		fifo[wr_addr] <= fifo[wr_addr];
end

//更新写地址
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		wr_addr <= 4'd0;
	else if(wr_en && (full==1'b0))
		wr_addr <= wr_addr + 1'b1;
	else
		wr_addr <= wr_addr;
end

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

//更新读地址
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		rd_addr <= 4'd0;
	else if(rd_en && (empty==1'b0))
		rd_addr <= rd_addr + 1'b1;
	else
		rd_addr <= rd_addr;
end

//更新计数器
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		cnt <= 4'd0;
	else begin
		case({wr_en,rd_en})
			2'b00: cnt <= cnt;
			2'b01: begin
					if(cnt != 4'd0)
						cnt <= cnt - 1'b1;
					else
						cnt <= cnt;
					end
			2'b10: begin
					if(cnt != max_cnt)
						cnt <= cnt + 1'b1;
					else
						cnt <= cnt;
					end
			2'b11: cnt <= cnt;
			default: ;
		endcase
	end
end

endmodule



仿真代码:


`timescale 1 ps/ 1 ps
module syn_fifo_tb();

reg clk;
reg [7:0] data_in;
reg rd_en;
reg rst_n;
reg wr_en;
                                             
wire [7:0]  data_out;
wire empty;
wire full;


initial	begin 
	clk = 0;
	rst_n = 0;
	rd_en = 0;
	wr_en = 0;
	data_in = 0;
	
	#40 rst_n = 1;
	#35 wr_en = 1;
	#200 rd_en = 1;
	
end     

always #20 data_in <= data_in + 1'b1;

always #10 clk <= ~clk;


syn_fio i1 (
	.clk(clk),
	.data_in(data_in),
	.data_out(data_out),
	.empty(empty),
	.full(full),
	.rd_en(rd_en),
	.rst_n(rst_n),
	.wr_en(wr_en)
);                                                 
endmodule



仿真图片:

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
异步FIFO是一种用于在两个异步时钟域之间传输数据的解决方案。在Verilog实现异步FIFO可以采用以下步骤: 1. 定义FIFO的输入和输出接口:包括读写时钟、读写使能信号、读写数据和读写指针等。 2. 使用两个时钟域的寄存器同步输入信号:由于读写时钟不同,需要使用两级寄存器级联来同步输入信号,以消除亚稳态。 3. 实现FIFO的读写逻辑:根据读写使能信号和读写指针,确定读写操作的时机和数据。 4. 实现FIFO的存储器:可以使用RAM或者其他存储结构来存储数据。 5. 实现FIFO的读写指针逻辑:根据读写操作的完成情况,更新读写指针的值。 6. 添加互斥逻辑:为了避免读写冲突,可以使用互斥逻辑来控制读写操作的互斥性。 需要注意的是,在实现异步FIFO时,需要考虑跨时钟域的问题。可以使用两级寄存器同步和格雷码等方法来解决跨时钟域的问题,确保读写指针的比较正确。 总之,通过定义接口、同步输入信号、实现读写逻辑和存储器、更新读写指针以及添加互斥逻辑等步骤,可以在Verilog实现异步FIFO。 #### 引用[.reference_title] - *1* *3* [异步FIFO---Verilog实现](https://blog.csdn.net/alangaixiaoxiao/article/details/81432144)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [基于Verilog实现的异步FIFO](https://blog.csdn.net/ZHOUJIAN1997/article/details/121597269)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值