FPGA入门——同步FIFO

同步FIFO(First-In First-Out)是一种常用的数据缓冲方法,它允许数据在一个时钟域内按照先进先出的顺序进行存储和检索。同步FIFO使用相同的时钟信号来控制数据的写入和读出,这是它与异步FIFO(使用不同的时钟信号进行写入和读出)的主要区别。同步FIFO通常用于缓冲、数据传输、流控制等场景,尤其适用于数据生产和消费速率相近的应用中。

编写代码

`timescale 1ns/1ns
/**********************************RAM************************************/

module dual_port_RAM #(
	parameter WIDTH = 8,
	parameter DEPTH = 16
)(
	input wclk,
	input rclk,
	input [$clog2(DEPTH)-1:0] waddr,   //[3:0]   0010
	input [$clog2(DEPTH)-1:0] raddr,
	input wenc,
	input renc,
	input [WIDTH-1:0] wdata,
	output  reg [WIDTH-1:0] rdata
);

reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];

/***********写入操作***************/
always @(posedge wclk) begin
	if(wenc)begin
		RAM_MEM[waddr] <= wdata;
	end
end

/***********读出操作***************/
always @(posedge rclk) begin 
	if(renc)begin
		rdata = RAM_MEM[raddr];
	end
end

endmodule

/**********************************SFIFO************************************/

module sfifo#(
	parameter WIDTH = 8,
	parameter DEPTH = 16
)(
	input 		clk  ,
	input 		rst_n,
	input		winc ,
	input		rinc ,
	input	[WIDTH-1:0] wdata ,
	
	output reg  wfull,
	output reg  rempty,
	output wire [WIDTH-1:0] rdata

);

localparam ADDR_WIDTH = $clog2(DEPTH); //ADDR_WIDTH = 4

reg [ADDR_WIDTH:0] waddr; //4:0    5位
reg [ADDR_WIDTH:0] raddr; //4:0    5位

/***********写地址***************/
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)begin
		waddr <= 0;
	end
	else begin
		if( winc &&  ~wfull )begin
			waddr = waddr + 1'b1;
		end
		else begin
			waddr <= waddr;
		end
	end
end

/***********读地址***************/
always @ (posedge clk or negedge rst_n) begin
 	if(~rst_n) begin
 		raddr <= 'b0;
 	end
 	else begin
 		if( rinc && ~rempty ) begin
 			raddr <= raddr + 1'b1;
 		end
 		else begin
 			raddr <= raddr; 
 		end
 	end
end

/************写满信号*和*读空信号*********************************/
always @ (posedge clk or negedge rst_n) begin
	if(~rst_n) begin
 		wfull <= 'b0;
 		rempty <= 'b0;
 	end
 	else begin
 		wfull <= (raddr == {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH-1:0]});
 		rempty <= (raddr == waddr);
 	end
end

// RAM例化,注意读写使能端口的信号

dual_port_RAM 
#(
 	.DEPTH(DEPTH),
 	.WIDTH(WIDTH)
)
dual_port_RAM_u0
(
	.wclk(clk),
	.wenc(winc && ~wfull),
	.waddr(waddr[ADDR_WIDTH-1:0]), //3:0    4
	.wdata(wdata),
	
	.rclk(clk),
	.renc(rinc && ~rempty),
	.raddr(raddr[ADDR_WIDTH-1:0]),
	.rdata(rdata) // 数据输出

);

endmodule

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值