题解 | #异步FIFO#

异步FIFO

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

//采用例化双口RAM的方式设计AS_FIFO
//单bit数据的跨时钟传输可以通过打拍,电平化,脉冲截等方式进行同步
//bits数据的跨时钟传输,需要先进行gray_code,跨时钟传输
//核心在于bin2gray,采用gray码做判断
`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  


/***********************************asyn_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
);

/* --------------------------------- define --------------------------------- */
localparam ADDR_WIDTH = $clog2(DEPTH)    ; //注意此为不可综合语句

reg     [ADDR_WIDTH :0]  wr_ptr                 ;
reg     [ADDR_WIDTH :0]  rd_ptr                 ;
reg     [ADDR_WIDTH :0]  wrptr                  ;
reg     [ADDR_WIDTH :0]  rdptr                  ;
reg     [ADDR_WIDTH :0]  wr_ptr_gray_cross      ;
reg     [ADDR_WIDTH :0]  rd_ptr_gray_cross      ;
reg     [ADDR_WIDTH :0]  wr_ptr_gray_cross_r1   ;
reg     [ADDR_WIDTH :0]  rd_ptr_gray_cross_r1   ;
wire    [ADDR_WIDTH :0]  wr_ptr_gray            ;
wire    [ADDR_WIDTH :0]  rd_ptr_gray            ;

/* ---------------------------------- main ---------------------------------- */
//
assign wenc     = winc & !wfull  ;
assign renc     = rinc & !rempty ;   
assign wfull    = (wrptr == {~rd_ptr_gray_cross_r1[ADDR_WIDTH :ADDR_WIDTH-1], rd_ptr_gray_cross_r1[ADDR_WIDTH-2 :0]} ) ;
assign rempty   = (rdptr == wr_ptr_gray_cross_r1) ;

//wr_ptr
always @(posedge wclk or negedge wrstn)
begin
    if(!wrstn)  
        wr_ptr <= 'd0 ;
    else if(wenc)
        wr_ptr <= wr_ptr + 1'b1 ;
end

//rd_ptr
always @(posedge rclk or rrstn)
begin
    if(!rrstn)
        rd_ptr <= 'd0 ;
    else if(renc)
        rd_ptr <= rd_ptr + 1'b1 ;
end

//bin2gray
assign wr_ptr_gray = (wr_ptr >> 1) ^ wr_ptr ;
assign rd_ptr_gray = (rd_ptr >> 1) ^ rd_ptr ;

//wr_ptr_gray_sync
always @(posedge wclk or negedge wrstn)
begin
    if(!wrstn)
        wrptr <= 'd0    ;
    else
        wrptr <= wr_ptr_gray    ;
end

//rd_ptr_gray_sync
always @(posedge rclk or negedge rrstn)
begin
    if(!rrstn)
        rdptr <= 'd0    ;
    else
        rdptr <= rd_ptr_gray    ;
end


//wr_ptr_gray_cross
always @(posedge rclk or negedge rrstn)
begin
    if(!rrstn) begin
        wr_ptr_gray_cross    <= 'd0   ;
        wr_ptr_gray_cross_r1 <= 'd0   ;
    end
    else begin
        wr_ptr_gray_cross    <= wrptr         ;
        wr_ptr_gray_cross_r1 <= wr_ptr_gray_cross   ;
    end
end

//rd_ptr_gray_cross
always @(posedge wclk or negedge wrstn)
begin
    if(!wrstn)
    begin
        rd_ptr_gray_cross    <= 'd0   ;
        rd_ptr_gray_cross_r1 <= 'd0   ;
    end
    else
    begin
        rd_ptr_gray_cross    <= rdptr        ;
        rd_ptr_gray_cross_r1 <= rd_ptr_gray_cross   ;
    end
end


/* -------------------------------- instance -------------------------------- */
dual_port_RAM 
        #(  .DEPTH (DEPTH),
            .WIDTH (WIDTH)
        )
        dual_port_RAM_u
            (
            .wclk      (wclk    ),
            .wenc      (wenc    ),
            .waddr     (wr_ptr[ADDR_WIDTH-1 :0]  ),  
            .wdata     (wdata   ),  
            .rclk      (rclk    ),
            .renc      (renc    ),
            .raddr     (rd_ptr[ADDR_WIDTH-1 :0]  ),  
            .rdata     (rdata   )
            );



endmodule

全部评论

相关推荐

点赞 评论 收藏
分享
03-29 19:11
门头沟学院 Java
wyp_davis:是可以这样的,不过只要交钱就是假的
点赞 评论 收藏
分享
爱喝奶茶的垂耳兔拥抱太阳:感觉项目和实习没有技术亮点和难点,单纯说了自己干了啥
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务