同步FIFO 两种方法

  • Post author:
  • Post category:其他


RAM+空满信号判断,两种方法


一、空满标志用指针位置得到


二、空满标志用fifo的中数据的计数得到

一、当写指针超过读指针一圈,写满;写指针等于读指针,读空

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    11:42:44 12/29/2021 
// Design Name: 
// Module Name:    fifo 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: //1、空满标志用指针位置得到
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module fifo#(
	parameter date_width=8,
	parameter date_addr =4,
	parameter date_depth=1<<date_addr
)
(
	input  clk,
	input  rst_n,
	input  [date_width-1:0] date_in,
	input  wr_en,
	input  rd_en,
	output reg [date_width-1:0] date_out,
	output  empty,
	output  full
//	output [date_addr-1:0]wr_adr,
//	output [date_addr-1:0]rd_adr
);
//=============读写指针,多一位来控制空满========
	reg [date_addr:0] wr_adr_ptr;
	reg [date_addr:0] rd_adr_ptr;
	
//=============Fifo中的读写地址=============
	wire [date_addr-1:0]wr_adr;
	wire [date_addr-1:0]rd_adr;
	assign wr_adr=wr_adr_ptr[date_addr-1:0];
	assign rd_adr=rd_adr_ptr[date_addr-1:0];//!!!rd_adr
	
//============读写指针控制=========
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			wr_adr_ptr <= 'd0;
		else if(wr_en && (~full))
			wr_adr_ptr <= wr_adr_ptr + 1'b1;
		else
			wr_adr_ptr <= wr_adr_ptr;
	end
		
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			rd_adr_ptr <= 'd0;
		else if(rd_en && (~empty))
			rd_adr_ptr <= rd_adr_ptr + 1'b1;
		else
			rd_adr_ptr <= rd_adr_ptr;
	end
//============双端口ram===========
	//Write
	integer i;
	reg [date_width-1:0] ram [date_depth-1:0];
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			for(i=0;i<=date_depth-1;i=i+1)
				ram[i]<=0;
		else if(wr_en&&(!full))
			ram[wr_adr]<=date_in;
		else
			ram[wr_adr]<=ram[wr_adr];	
	end
	//Read
		always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			date_out<=0;
		else if(rd_en&&(!empty))
			date_out<=ram[rd_adr];
		else	
			date_out<=date_out;
	end
	
//=============空满信号判断,读写指针同则空,MSB不同,其他同则满===========
	assign empty=(wr_adr_ptr==rd_adr_ptr)?1'b1:1'b0;
	assign full =({(!wr_adr_ptr[date_addr]),wr_adr_ptr[date_addr-1:0]}==rd_adr_ptr)?1'b1:1'b0;
endmodule

testbench:写的同时读入

`timescale 1ns / 1ps


// Company: 
// Engineer:
//
// Create Date:   16:25:00 12/29/2021
// Design Name:   fifo
// Module Name:   C:/Users/74172/Desktop/IC/FPGA/zsz_project/sync_fifo_prt/test.v
// Project Name:  sync_fifo_prt
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: fifo
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module test;

	// Inputs
	reg clk;
	reg rst_n;
	reg [7:0] date_in;
	reg wr_en;
	reg rd_en;

	// Outputs
	wire [7:0] date_out;
	wire empty;
	wire full;

	// Instantiate the Unit Under Test (UUT)
	fifo uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.date_in(date_in), 
		.wr_en(wr_en), 
		.rd_en(rd_en), 
		.date_out(date_out), 
		.empty(empty), 
		.full(full)
	);

	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			date_in<=0;
      else if(wr_en)
         date_in <= date_in + 1'b1;
	end
	
	initial clk=0;
	always #5 clk=~clk;
	initial begin
		// Initialize Inputs
		rst_n = 0;
		wr_en = 0;
		rd_en = 0;
		#100;
		
		rst_n = 1;
		wr_en = 1;
		#100
		rd_en = 1;
		#50
		wr_en=0;
		rd_en=1;
		#400;
		rd_en=0;
		$stop;
	end
endmodule

二、根据读写状态,对fifo中的数据进行计数,等于date_depth时候,为full



修改

1、

修改计数器的宽度,需要cnt==16时候,判断空满。




2、 修改full的判断值,当cnt==16时候,立刻ful==1,所以正好0-15。


`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    16:22:26 12/28/2021 
// Design Name: 
// Module Name:    fifo_cnt 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description:    //2、空满标志用fifo的中数据的计数得到
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module fifo_cnt#(
	parameter date_width=8,
	parameter date_addr =4,   //深度16
	parameter date_depth=1<<date_addr
)
(
	input  clk,
	input  rst_n,
	input  [date_width-1:0] date_in,
	input  wr_en,
	input  rd_en,
	output reg [date_width-1:0] date_out,
	output  empty,
	output  full,
	output reg [date_addr:0] fifo_counter,
	output reg [date_addr-1:0] wr_addr,
	output reg [date_addr-1:0] rd_addr
	//output wr_err,
	//output rd_err
);
//=============RAM中的读写地址=============
	//reg [date_addr-1:0] wr_addr;
	//reg [date_addr-1:0] rd_addr;
	
	always@(posedge clk or negedge rst_n)begin//写成negedge clk能对吗!
		if(!rst_n)
			wr_addr<=0;
		else if(wr_en&&(!full))
			wr_addr<=wr_addr+1'b1;
		else
			wr_addr<=wr_addr;
	end
		
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			rd_addr<=0;
		else if(rd_en&&(!empty))
			rd_addr<=rd_addr+1'b1;
		else
			rd_addr<=rd_addr;
	end 
	
	//=====================双端口RAM=====================
	integer i;
	reg [date_width-1:0] register [date_depth-1:0];
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			for(i=0;i<=date_depth-1;i=i+1)
				register[i]<=0;
		else if(wr_en&&!full)
				register[wr_addr]<=date_in;
	end
		
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			date_out<=0;
		else if(rd_en&&!empty)
			date_out<=register[rd_addr];
	end
//=====================FIFO中数据Counter==============
	//reg [date_addr-1:0] fifo_counter;
//	always@(posedge clk or negedge rst_n)begin
//		if(!rst_n)
//			fifo_counter<=0;
//		else if((wr_en&&!full)&&!rd_en)
//			fifo_counter<=fifo_counter+1'b1;
//		else if((rd_en&&!empty)&&!wr_en)
//			fifo_counter<=fifo_counter-1'b1;
//		else
//			fifo_counter<=fifo_counter;
//	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			fifo_counter<=0;
		else begin
			case({wr_en,rd_en})
				2'b00: fifo_counter<=fifo_counter;
				2'b01: if(!empty)
							fifo_counter<=fifo_counter-1'b1;
						else
							fifo_counter<=fifo_counter;
				2'b10: if(!full)
							fifo_counter<=fifo_counter+1'b1;
						else
							fifo_counter<=fifo_counter;
				2'b11: fifo_counter<=fifo_counter;
			endcase
		end
	end

//====================判断空满信号===============
	assign full =(fifo_counter==date_depth)?1'b1:1'b0;
	assign empty=(fifo_counter==0)?1'b1:1'b0;

endmodule

testbench

`timescale 1ns / 1ps


// Company: 
// Engineer:
//
// Create Date:   16:31:19 12/28/2021
// Design Name:   fifo_cnt
// Module Name:   C:/Users/74172/Desktop/IC/FPGA/zsz_project/sync_fifo_cnt/zzz.v
// Project Name:  sync_fifo_cnt
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: fifo_cnt
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module zzz;

	// Inputs
	reg clk;
	reg rst_n;
	reg [7:0] date_in;
	reg wr_en;
	reg rd_en;

	// Outputs
	wire [7:0] date_out;
	wire empty;
	wire full;
	wire [3:0] fifo_counter;
	wire [3:0] wr_addr;
	wire [3:0] rd_addr;
	

	// Instantiate the Unit Under Test (UUT)
	fifo_cnt uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.date_in(date_in), 
		.wr_en(wr_en), 
		.rd_en(rd_en), 
		.date_out(date_out), 
		.empty(empty), 
		.full(full),
		.fifo_counter(fifo_counter),
		.wr_addr(wr_addr),
		.rd_addr(rd_addr)
	);
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			date_in<=0;
      else if(wr_en)
         date_in <= date_in + 1'b1;
	end
	
	initial clk=0;
	always #5 clk=~clk;
	initial begin
		// Initialize Inputs
		rst_n = 0;
		wr_en = 0;
		rd_en = 0;
		#100;
		
		rst_n = 1;
		wr_en = 1;
		#300
		wr_en=0;
		rd_en = 1;
		#300
		rd_en=0;
		$stop;
	end
      
endmodule



版权声明:本文为qq_42107624原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。