题解 | 同步FIFO

同步FIFO

https://www.nowcoder.com/practice/e5e86054a0ce4355b9dfc08238f25f5f

`timescale 1ns/1ns

/**********************************RAM************************************/
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 [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  

/**********************************SFIFO************************************/
module sfifo#(
	parameter	WIDTH = 8,
	parameter 	DEPTH = 16
)(
	input 					clk		, 
	input 					rst_n	,
	input 					winc	,
	input 			 		rinc	,
	input 		[WIDTH-1:0]	wdata	,

	output 	reg	wfull	,
	output 	reg	rempty	,
	output wire [WIDTH-1:0]	rdata
);
    
	//深度的位宽
    localparam DP_WD = $clog2(DEPTH);
    //ram的写使能,读使能
    wire wenc;
    assign wenc = winc & (!wfull);
    wire renc;
    assign renc = rinc & (!rempty);
    //写地址的变化
    reg  [DP_WD : 0] waddr;
    wire [DP_WD : 0] waddr_d;
    assign waddr_d[DP_WD]     = (waddr[DP_WD-1:0] == DEPTH - 1) ? ~waddr[DP_WD] : waddr[DP_WD];
    assign waddr_d[DP_WD-1:0] = (waddr[DP_WD-1:0] == DEPTH - 1) ? 0 : waddr[DP_WD-1:0] + 1;
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) waddr <= 0;
        else if (wenc) waddr <= waddr_d;
    end
    //读地址的变化
    reg  [DP_WD : 0] raddr;
    wire [DP_WD : 0] raddr_d;
    assign raddr_d[DP_WD]     = (raddr[DP_WD-1:0] == DEPTH - 1) ? ~raddr[DP_WD] : raddr[DP_WD];
    assign raddr_d[DP_WD-1:0] = (raddr[DP_WD-1:0] == DEPTH - 1) ? 0 : raddr[DP_WD-1:0] + 1;
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) raddr <= 0;
        else if (renc) raddr <= raddr_d;
    end
    //写满,读空标志
	wire wfull_1;
	wire rempty_1;
    assign wfull_1  = (waddr[DP_WD] != raddr[DP_WD]) && (waddr[DP_WD-1:0] == raddr[DP_WD-1:0]);
    assign rempty_1 = (waddr[DP_WD] == raddr[DP_WD]) && (waddr[DP_WD-1:0] == raddr[DP_WD-1:0]);
	
    //牛客上多出来的
	always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            wfull <= 0;
			rempty<= 0;
        end else begin
            wfull <= wfull_1;
			rempty<= rempty_1;
        end
    end

	dual_port_RAM #(.DEPTH(DEPTH),
                .WIDTH(WIDTH)
)dual_port_RAM(
    .wclk (clk),  
    .wenc (wenc),  
    .waddr(waddr[DP_WD-1:0]),  //深度对2取对数,得到地址的位宽。
    .wdata(wdata),           //数据写入
    .rclk (clk), 
    .renc (renc), 
    .raddr(raddr[DP_WD-1:0]),   //深度对2取对数,得到地址的位宽。
    .rdata(rdata)          //数据输出
);




endmodule

牛客上面的 wfull rempty落后了一拍,实际的SFIFO在写满后立即wfull 拉高,并且初始时 wfull rempty两个都为0。

要通过牛客的系统,加个延迟就行

全部评论

相关推荐

09-22 09:42
门头沟学院 Java
牛客37185681...:马德,我感觉这是我面过最恶心的公司,一面是两个女hr,说什么实习前几个月属于试用期,试用期过了才能转成正式实习生,我***笑了,问待遇就是不说,问能不能接受全栈,沙币公司
如果可以选,你最想去哪家...
点赞 评论 收藏
分享
牛客小菜鸡66:boss里面,招人的叫老板,找工作的叫牛人
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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