目录
描述
输入描述:
输出描述:
参考代码
描述
请根据题目中给出的双口RAM代码和接口描述,实现异步FIFO,要求FIFO位宽和深度参数化可配置。
电路的接口如下图所示。

双口RAM端口说明:
| 端口名 | I/O | 描述 | 
| wclk | input | 写数据时钟 | 
| wenc | input | 写使能 | 
| waddr | input | 写地址 | 
| wdata | input | 输入数据 | 
| rclk | input | 读数据时钟 | 
| renc | input | 读使能 | 
| raddr | input | 读地址 | 
| rdata | output | 输出数据 | 
同步FIFO端口说明:
| 端口名 | I/O | 描述 | 
| wclk | input | 写时钟 | 
| rclk | input | 读时钟 | 
| wrstn | input | 写时钟域异步复位 | 
| rrstn | input | 读时钟域异步复位 | 
| winc | input | 写使能 | 
| rinc | input | 读使能 | 
| wdata | input | 写数据 | 
| wfull | output | 写满信号 | 
| rempty | output | 读空信号 | 
| rdata | output | 读数据 | 
双口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  输入描述:
    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
参考代码
`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) beginif(wenc)RAM_MEM[waddr] <= wdata;
end always @(posedge rclk) beginif(renc)rdata <= RAM_MEM[raddr];
end endmodule  /***************************************AFIFO*****************************************/
module asyn_fifo#(parameter	WIDTH = 8,parameter 	DEPTH = 16
)(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
);parameter ADDR_WIDTH = $clog2(DEPTH);/**********************addr bin gen*************************/
reg 	[ADDR_WIDTH:0]	waddr_bin;
reg 	[ADDR_WIDTH:0]	raddr_bin;always @(posedge wclk or negedge wrstn) beginif(~wrstn) beginwaddr_bin <= 'd0;end else if(!wfull && winc)beginwaddr_bin <= waddr_bin + 1'd1;end
end
always @(posedge rclk or negedge rrstn) beginif(~rrstn) beginraddr_bin <= 'd0;end else if(!rempty && rinc)beginraddr_bin <= raddr_bin + 1'd1;end
end/**********************addr gray gen*************************/
wire 	[ADDR_WIDTH:0]	waddr_gray;
wire 	[ADDR_WIDTH:0]	raddr_gray;
reg 	[ADDR_WIDTH:0]	wptr;
reg 	[ADDR_WIDTH:0]	rptr;
assign waddr_gray = waddr_bin ^ (waddr_bin>>1);
assign raddr_gray = raddr_bin ^ (raddr_bin>>1);
always @(posedge wclk or negedge wrstn) begin if(~wrstn) beginwptr <= 'd0;end else beginwptr <= waddr_gray;end
end
always @(posedge rclk or negedge rrstn) begin if(~rrstn) beginrptr <= 'd0;end else beginrptr <= raddr_gray;end
end
/**********************syn addr gray*************************/
reg		[ADDR_WIDTH:0]	wptr_buff;
reg		[ADDR_WIDTH:0]	wptr_syn;
reg		[ADDR_WIDTH:0]	rptr_buff;
reg		[ADDR_WIDTH:0]	rptr_syn;
always @(posedge wclk or negedge wrstn) begin if(~wrstn) beginrptr_buff <= 'd0;rptr_syn <= 'd0;end else beginrptr_buff <= rptr;rptr_syn <= rptr_buff;end
end
always @(posedge rclk or negedge rrstn) begin if(~rrstn) beginwptr_buff <= 'd0;wptr_syn <= 'd0;end else beginwptr_buff <= wptr;wptr_syn <= wptr_buff;end
end
/**********************full empty gen*************************/
assign wfull = (wptr == {~rptr_syn[ADDR_WIDTH:ADDR_WIDTH-1],rptr_syn[ADDR_WIDTH-2:0]});
assign rempty = (rptr == wptr_syn);/**********************RAM*************************/
wire 	wen	;
wire	ren	;
wire 	wren;//high write
wire [ADDR_WIDTH-1:0]	waddr;
wire [ADDR_WIDTH-1:0]	raddr;
assign wen = winc & !wfull;
assign ren = rinc & !rempty;
assign waddr = waddr_bin[ADDR_WIDTH-1:0];
assign raddr = raddr_bin[ADDR_WIDTH-1:0];dual_port_RAM #(.DEPTH(DEPTH),.WIDTH(WIDTH)
)dual_port_RAM(.wclk (wclk),  .wenc (wen),  .waddr(waddr[ADDR_WIDTH-1:0]),  //深度对2取对数,得到地址的位宽。.wdata(wdata),       	//数据写入.rclk (rclk), .renc (ren), .raddr(raddr[ADDR_WIDTH-1:0]),   //深度对2取对数,得到地址的位宽。.rdata(rdata)  		//数据输出
);endmodule