`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  


//	请设置  带有空满信号  的同步FIFO.
/**********************************SFIFO************************************/
module sfifo#(
	parameter	WIDTH = 8,		//	FIFO,本质是  先进先出,可以同时读写.
	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
);

//	加寄存器计数,来判断   空满.
parameter	ADDR_WIDTH = $clog2(DEPTH);		//	4
		//	waddr[4]	== raddr[4];	如果相等,则要么相等是1,要么相等是0.
//	代码
reg		[ADDR_WIDTH:0]		waddr;			//	reg		[4:0]	waddr;
reg		[ADDR_WIDTH:0]		raddr;

//	采用计数器方法:fifo_cnt
reg		[ADDR_WIDTH:0]	fifo_cnt;

always@(posedge clk or negedge rst_n)		begin
	if(!rst_n)		begin
		waddr		<= 'd0;
		raddr		<= 'd0;
		fifo_cnt	<= 'd0;
		end
	else if(!wfull && winc && fifo_cnt < DEPTH)		begin
		waddr		<= waddr + 1'd1;
		fifo_cnt	<= fifo_cnt	+ 1'd1;
		end
	else if(!rempty && rinc && fifo_cnt > 0)	begin
		raddr		<= raddr + 1'd1;
		fifo_cnt	<= fifo_cnt - 1'd1;
		end
end

always@(posedge clk or negedge rst_n)		begin
	if(!rst_n)		begin
		wfull			<= 'd0;
		rempty			<= 'd0;
		end
	else if(fifo_cnt == 'd0)			//	如果
		rempty			<= 1'd1;
	else if(fifo_cnt == DEPTH)	
		wfull			<= 1'd1;
	else	begin
		wfull			<= 'd0;
		rempty			<= 'd0;
		end
end

/*
//	写,写满后,保持
always@(posedge clk or negedge rst_n)	begin
	if(!rst_n)
		waddr		<= 'd0;
	else if(!wfull && winc)				//	只要有效,就一直写下去.
		waddr		<= waddr + 1'd1;
end

//	读,读满后,保持
always@(posedge clk or negedge rst_n)	begin
	if(!rst_n)
		raddr		<= 'd0;
	else if(!rempty && rinc)			//	只要有效,就一直读下去.
		raddr		<= raddr + 1'd1;
end

/*
//			full 		empty		gen
wire		[ADDR_WIDTH:0]		fifo_cnt;
//	判断 写地址、读地址是:0, DEPTH。
/*	如果最高位相等,则可能相等,  	判断	是否相等是 0;	
	如果最高位不等,则一定不等,	判断	是否是 DEPTH.
*/
/*																		//	[4:0] - [4:0].
assign		fifo_cnt	= (waddr[ADDR_WIDTH] == raddr[ADDR_WIDTH]) ? (waddr[ADDR_WIDTH:0] - raddr[ADDR_WIDTH:0]) :
				(DEPTH + waddr[ADDR_WIDTH-1:0] - raddr[ADDR_WIDTH-1:0]);
				//	 DEPTH + [3:0] - [3:0].
*/
						
//			RAM_MEM
wire		wen;
wire		ren;
wire		wren;		//	1, write.

assign		wen = winc & !wfull;	//  写使能有效,写不满
assign		ren	= rinc & !rempty;	//	读使能有效,读不空

//
dual_port_RAM	u1_dual_port_RAM(
.wclk				(clk			),
.wenc				(wen			),
.waddr				(waddr			),
.wdata				(wdata			),		//	写数据

.rclk				(clk			),
.renc				(ren			),
.raddr				(raddr			),
.rdata				(rdata			)		//	读数据
);
 
endmodule

/*
//	读空
always@(posedge clk or negedge rst_n)		begin
	if(!rst_n)	begin
		rempty		<= 1'd0;
		raddr		<= 4'd0;
		end
	else if(rinc == 1 && raddr >= 4'd15)	begin
		rempty		<= 1'd0;
		raddr		<= 
		end
end

//	写满
always@(posedge clk or negedge rst_n)		begin
	if(!rst_n)	begin
		wfull		<= 1'd0;
		rempty		<= 1'd0;
		addr		<= 4'd0;
		end								//	写地址
	else if(winc == 1 && addr < 4'd15)	begin
		wfull		<= 1'd0;
		rempty		<= 1'd0;
		addr		<= addr + 1'd1;
		end	
	else if(winc == 1 && addr == 4'd15)		begin
		wfull		<= 1'd1;
		rempty		<= 1'd0;
		addr		<= addr;			//	写满后,保持
		end
								//	读空
	else if(rinc == 1 && addr > 4'd0)		begin
		wfull		<= 1'd0;
		rempty		<= 1'd0;
		addr		<= addr - 1'd1;
		end	
	else if(rinc == 1 && addr == 4'd0)	begin
		wfull		<= 1'd0;
		rempty		<= 1'd1;
		addr		<= addr;	//	读空后,保持
		end
end

*/