题解 | #异步FIFO#

异步FIFO

https://www.nowcoder.com/practice/40246577a1a04c08b3b7f529f9a268cf

//async_fifo
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 = $clog2(DEPTH);
reg [ADDR:0]    waddr;
reg [ADDR:0]    raddr;

always@(posedge wclk or negedge wrstn)begin
    if(!wrstn)begin
        waddr <= 0;
    end
    else if(winc&~wfull)begin
        waddr <= waddr + 1;
    end
end
always@(posedge rclk or negedge rrstn)begin
    if(!rrstn)begin
        raddr <= 0;
    end
    else if(rinc&~rempty)begin
        raddr <= raddr + 1;
    end
end

//双端口RAM例化
dual_port_RAM#(
	.DEPTH	(16),
	.WIDTH	(8)
)u_dual_port_RAM(
	.wclk	(wclk),
	.wenc	(winc&~wfull),
	.waddr  (waddr),
	.wdata  (wdata),
	.rclk	(rclk),
	.renc	(rinc&~rempty),
	.raddr  (raddr),
	.rdata  (rdata)
);

//读写地址指针格雷码转换
wire    [ADDR:0]    gray_wptr;
wire    [ADDR:0]    gray_rptr;
assign  gray_wptr = waddr ^ (waddr>>>1);
assign  gray_rptr = raddr ^ (raddr>>>1);

reg		[ADDR:0]	wptr;
reg		[ADDR:0]	rptr;
always@(posedge wclk or negedge wrstn)begin
    if(!wrstn)begin
        wptr <= 0;
    end
    else begin
        wptr <= gray_wptr;
    end
end
always@(posedge rclk or negedge rrstn)begin
    if(!rrstn)begin
        rptr <= 0;
    end
    else begin
        rptr <= gray_rptr;
    end
end

//同步打拍
reg [ADDR:0]    wptr2rclk_r1,wptr2rclk_r2;
reg [ADDR:0]    rptr2wclk_r1,rptr2wclk_r2;

always@(posedge rclk or negedge rrstn)begin
    if(!rrstn)begin
        wptr2rclk_r1 <= 0;
        wptr2rclk_r2 <= 0;
    end
    else begin
        wptr2rclk_r1 <= wptr;
        wptr2rclk_r2 <= wptr2rclk_r1;
    end
end
always@(posedge wclk or negedge wrstn)begin
    if(!wrstn)begin
        rptr2wclk_r1 <= 0;
        rptr2wclk_r2 <= 0;
    end
    else begin
        rptr2wclk_r1 <= rptr;
        rptr2wclk_r2 <= rptr2wclk_r1;
    end
end

//空满判断
assign  wfull = wptr == {~rptr2wclk_r2[ADDR:ADDR-1],rptr2wclk_r2[ADDR-2:0]};
assign  rempty = rptr == wptr2rclk_r2;



endmodule

module dual_port_RAM#(
	parameter	DEPTH	= 16,
	parameter	WIDTH	= 8
)(
	input	wclk	,
	input	wenc	,
	input	[$clog2(DEPTH)-1:0]	waddr,
	input	[WIDTH-1:0]			wdata,

	input	rclk	,
	input	renc	,
	input	[$clog2(DEPTH)-1:0]	raddr,
	output	reg[WIDTH-1:0]			rdata
);

reg [WIDTH-1:0] RAM_MEM [DEPTH-1:0];
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

全部评论

相关推荐

只写bug的程序媛:人家说一本以上,不是及以上
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务