题解 | #同步FIFO#啊啊啊啊

同步FIFO

https://www.nowcoder.com/practice/3ece2bed6f044ceebd172a7bf5cfb416

`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  

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

reg [$clog2(DEPTH)-1:0] w_pointer,r_pointer; // 读写指针

always@(posedge clk or negedge rst_n)begin
	if(~rst_n)begin
		w_pointer <= 'b0;
	end
	else if(winc && w_pointer < 4'd15 && ~wfull)begin
		w_pointer <= w_pointer + 1'b1;
	end
	else if(winc && w_pointer == 4'd15 && ~wfull)begin
		w_pointer <= 'b0;
	end
end
always@(posedge clk or negedge rst_n)begin
	if(~rst_n)begin
		r_pointer <= 'b0;
	end
	else if(rinc && r_pointer < 4'd15 && ~rempty)begin
		r_pointer <= r_pointer + 1'b1;
	end
	else if(rinc && r_pointer == 4'd15 && ~rempty)begin
		r_pointer <= 'b0;
	end
end

//写使能,读使能打一拍去看当pointer相等时,是哪个使能达到的,来驱动full empty 并不行,不知道哪有问题
// reg winc_d,rinc_d;
// always@(posedge clk or negedge rst_n)begin
// 	if(~rst_n)begin
// 		winc_d <= 1'b0;
// 	end
// 	else begin
// 		winc_d <= winc;
// 	end
// end
// always@(posedge clk or negedge rst_n)begin
// 	if(~rst_n)begin
// 		rinc_d <= 1'b0;
// 	end
// 	else begin
// 		rinc_d <= rinc;
// 	end
// end

// always@(posedge clk or negedge rst_n)begin
// 	if(~rst_n)begin
// 		wfull <= 1'b0;
// 	end
// 	else if(w_pointer != r_pointer)begin
// 		wfull <= 1'b0;
// 	end
// 	else if(w_pointer == r_pointer && winc_d)begin
// 		wfull <= 1'b1;
// 	end
// end

// always@(posedge clk or negedge rst_n)begin
// 	if(~rst_n)begin
// 		rempty <= 1'b0;
// 	end
// 	else if(w_pointer != r_pointer)begin
// 		rempty <= 1'b0;
// 	end
// 	else if(w_pointer == r_pointer && rinc_d)begin
// 		rempty <= 1'b1;
// 	end
// end

//看答案,地址的变化写的没问题,空满状态的判断有点问题,答案采用的计数器的形式,写就加1,读减一
reg [$clog2(DEPTH):0] cnt;
always@(posedge clk or negedge rst_n)begin
	if(~rst_n)begin
		cnt<= 1'b0;
	end
	else if(winc&~wfull)
            cnt <= cnt + 1;
        else if(rinc&~rempty)
            cnt <= cnt - 1;
        else
            cnt <= cnt;
end

always@(posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            wfull  = 0;
            rempty = 0;
        end
        else begin
            wfull  = cnt == DEPTH;
            rempty = cnt == 0;
        end
end

dual_port_RAM dual_port_RAM_u0
(
	.wclk(clk),
	.wenc(winc),
	.waddr(w_pointer),
	.wdata(wdata),
	.rclk(clk),
	.renc(rinc),
	.raddr(r_pointer),

	.rdata(rdata)
);



endmodule

全部评论
用使能判断是可以的,但这个题正确答案空满信号晚了一个clk,所以不好提交
点赞 回复 分享
发布于 2023-05-04 19:55 广东

相关推荐

SadnessAlex:跟三十五岁原则一样,人太多给这些***惯坏了
点赞 评论 收藏
分享
AI牛可乐:哇塞,恭喜恭喜!48万的年薪,真是让人羡慕呀!看来你找到了一个超棒的工作,可以享受不卷的生活啦!🎉有没有什么求职秘诀想要分享给小牛牛呢?或者,想不想知道我是谁呢?😉(点击我的头像,我们可以私信聊聊哦~)
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务