VL45 异步FIFO

请根据题目中给出的双口RAM代码和接口描述,实现异步FIFO,要求FIFO位宽和深度参数化可配置。

电路的接口如下图所示。
在这里插入图片描述
在这里插入图片描述
双口RAM代码如下,可在本题答案中添加并例化此代码。

module dual_port_RAM #(parameter DEPTH = 16,
   parameter WIDTH = 8)(
 input wclk
,input wenc
,input [$clog2(DEPTH)-1:0] waddr  //深度对2取对数,得到地址的位宽。
,input [WIDTH-1:0] wdata      //数据写入
,input rclk
,input renc
,input [$clog2(DEPTH)-1:0] raddr  //深度对2取对数,得到地址的位宽。
,output reg [WIDTH-1:0] rdata //数据输出
);

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

always @(posedge wclk) begin
if(wenc)
RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
if(renc)
rdata <= RAM_MEM[raddr];
end 

endmodule  

题解:

`timescale 1ns/1ns

/***************************************RAM*****************************************/
module dual_port_RAM #(parameter DEPTH = 16,
					   parameter WIDTH = 8)(
	 input wclk
	,input wenc
	,input [$clog2(DEPTH)-1:0] waddr  //深度对2取对数,得到地址的位宽。
	,input [WIDTH-1:0] wdata      	//数据写入
	,input rclk
	,input renc
	,input [$clog2(DEPTH)-1:0] raddr  //深度对2取对数,得到地址的位宽。
	,output reg [WIDTH-1:0] rdata 		//数据输出
);

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

always @(posedge wclk) begin
	if(wenc)
		RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
	if(renc)
		rdata <= RAM_MEM[raddr];
end 

endmodule  

/***************************************AFIFO*****************************************/
module asyn_fifo#(
	parameter	WIDTH = 8, //数据位宽8
	parameter 	DEPTH = 16 //地址位宽为4,即[3:0],深度为8
)(
	input 					wclk	, 
	input 					rclk	,   
	input 					wrstn	,
	input					rrstn	,
	input 					winc	,
	input 			 		rinc	,
	input 		[WIDTH-1:0]	wdata	,

	output wire				wfull	,
	output wire				rempty	,
	output wire [WIDTH-1:0]	rdata
);

//格雷码计数 0000 0001 0011 0010 0110 0111 0101 0100  // 1100 1101 1111 1110 1010 1011 1001 1000
//当读写指针相等时,fifo空;当写指针比读指针多循环一周时(读写指针最高位和次高位都相反,其余位同),fifo满


/*  读写地址  */

reg		[$clog2(DEPTH):0]  waddr_fifo;//注意位宽比地址位宽多一位(以便进行空满判断)
reg		[$clog2(DEPTH):0]  raddr_fifo;


always@(posedge wclk or negedge wrstn)begin
	if(!wrstn)
		waddr_fifo <= 0 ;
	else if(!wfull & winc)
		waddr_fifo<=waddr_fifo+1;
end

always@(posedge rclk or negedge rrstn)begin
	if(!rrstn)
		raddr_fifo <= 0 ;
	else if(!rempty & rinc)
		raddr_fifo<=raddr_fifo+1;
end

/*  地址转换为指针后 转换为格雷码指针  */
wire	[$clog2(DEPTH) : 0]  waddr_gray;
wire	[$clog2(DEPTH) : 0]  raddr_gray;
reg  	[$clog2(DEPTH) : 0]  wptr;
reg  	[$clog2(DEPTH) : 0]  rptr;

assign  waddr_gray = waddr_fifo ^ (waddr_fifo>>1);
assign  raddr_gray = raddr_fifo ^ (raddr_fifo>>1);


always @(posedge wclk or negedge wrstn) begin
	if(~wrstn) 
		wptr <= 0;
 
    else 
        wptr <= waddr_gray; 
end

always @(posedge rclk or negedge rrstn) begin
	if(~rrstn) 
		rptr <= 0;
 
    else 
        rptr <= raddr_gray; 
end

/*  指针打两拍同步,注意是跨时钟  */

reg     [$clog2(DEPTH):0]  wptr_buff;
reg     [$clog2(DEPTH):0]  wptr_syn;
reg     [$clog2(DEPTH):0]  rptr_buff;
reg     [$clog2(DEPTH):0]  rptr_syn;

always @(posedge wclk or negedge wrstn) begin
	if(~wrstn) begin
		rptr_buff <= 0 ;
		rptr_syn  <= 0 ;

	end
    else begin
		rptr_buff <= rptr ;
		rptr_syn  <= rptr_buff ;
	end

end

always @(posedge rclk or negedge rrstn) begin
	if(~rrstn) begin
		wptr_buff <= 0 ;
		wptr_syn  <= 0 ;

	end
    else begin
		wptr_buff <= wptr ;
		wptr_syn  <= wptr_buff ;
	end
end

/*  产生空满信号(相同时钟下信号的比较)  */

assign wfull  =  (wptr == {~rptr_syn[$clog2(DEPTH):$clog2(DEPTH)-1],rptr_syn[$clog2(DEPTH)-2:0]});//最高位和次高位都相反
assign rempty =  (rptr == wptr_syn);

/* 例化RAM  */

//wire [$clog2(DEPTH)-1:0] waddr;
//wire [$clog2(DEPTH)-1:0] raddr;
//wire wenc;
//wire renc;
//assign waddr = waddr_fifo[$clog2(DEPTH)-1:0] ;
//assign raddr = raddr_fifo[$clog2(DEPTH)-1:0] ;
//assign wenc  = !wfull & winc ;
//assign renc  = !rempty & rinc ;

dual_port_RAM #(.DEPTH(DEPTH),
				.WIDTH(WIDTH)
)dual_port_RAM_inst(

	.wclk	(wclk), 
	.wenc	(!wfull & winc),   
	.waddr	(waddr_fifo[$clog2(DEPTH)-1:0]),
	.wdata	(wdata),

	.rclk	(rclk), 
	.renc	(!rempty & rinc),   
	.raddr	(raddr_fifo[$clog2(DEPTH)-1:0]),
	.rdata	(rdata)
);

endmodule
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值