牛客进阶题目:同步FIFO

给定一个双端口RAM作为sFIFO的存储空间,所以可以一套端口读,另一套端口写。在sFIFO里维护读写指针各一个,作为DRAM的地址。

判满判空采取扩1bit操作,只有这样才能标识反卷,指示写满。
其余地方根据RAM端口去思考要添加的控制逻辑即可

`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
);
localparam ADDR_WIDTH = $clog2(DEPTH) ;
reg[ADDR_WIDTH:0]	write_pointer;
reg[ADDR_WIDTH:0]	read_pointer ;
wire		wenc	;
wire		renc 	;

//assign wfull = (raddr == {!waddr[ADDR_WIDTH],waddr[ADDR_WIDTH-1:0]}) ? 1'b1 : 1'b0 ;
//assign rempty= (raddr == waddr) ? 1'b1 : 1'b0 ;

assign	wenc = winc & !wfull	;
assign 	renc = rinc & !rempty	;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		wfull <= 1'b0 ;
	else if(read_pointer == {!write_pointer[ADDR_WIDTH],write_pointer[ADDR_WIDTH-1:0]})
		wfull <= 1'b1 ;
	else
		wfull <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		rempty <= 1'b0 ;
	else if(read_pointer == write_pointer)
		rempty <= 1'b1 ;
	else
		rempty <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		write_pointer <= 'd0 ;
	else if(winc & !wfull)
		write_pointer <= write_pointer + 1 ;
	else
		write_pointer <= write_pointer ;
end

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		read_pointer <= 'd0 ;
	else if(rinc & !rempty)
		read_pointer <= read_pointer + 1 ;
	else
		read_pointer <= read_pointer ;
end



dual_port_RAM  
    #(
        .DEPTH(DEPTH),
        .WIDTH(WIDTH)
    )
    dual_port_RAM_U0 
    (
        .wclk(clk),
      .wenc(wenc),
        .waddr(write_pointer[ADDR_WIDTH-1:0]), 
      .wdata(wdata),        
      .rclk(clk),
        .renc(renc),
        .raddr(read_pointer[ADDR_WIDTH-1:0]), 
      .rdata(rdata)     
);       
endmodule
posted @   骑猪上树的少年  阅读(76)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
回到顶部
点击右上角即可分享
微信分享提示