题解 | #异步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

全部评论

相关推荐

来个厂收我吧:首先,市场侧求职我不是很懂。 但是,如果hr把这份简历给我,我会觉得求职人不适合做产品经理。 问题点: 1,简历的字体格式不统一,排版不尽如人意 2,重点不突出,建议参考star法则写个人经历 3,印尼官方货币名称为印度尼西亚卢比(IDR),且GMV690000印尼盾换算为305人民币,总成交额不高。 4,右上角的意向职位在发给其他公司时记得删除。 5,你所有的经历都是新媒体运营,但是你要投市场营销岗位,jd和简历不匹配,建议用AI+提示词,参照多个jd改一下经历内容。 修改建议: 1,统一字体(中文:思源黑体或微软雅黑,英文数字:time new romans),在word中通过表格进行排版(b站学) 2,校招个人经历权重:实习经历=创业经历(大创另算)>项目经历>实训经历>校园经历 3,请将项目经历时间顺序改为倒序,最新的放最上方。 4,求职方向不同,简历文字描述侧重点也需要不同。
点赞 评论 收藏
分享
06-07 19:59
门头沟学院 C++
补药卡我啊😭:都快15年前的了还在11新特性
你的简历改到第几版了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务