天天看點

FPGA之FIFO設計(二)

異步FIFO在ISE下有兩種生成方法:

         法一:使用CORE Generator生成的DPRAM和自己設計的FIFO控制邏輯,将兩者連在一起就構成了FIFO。

         法二:直接使用FIFO的IP核。

現在我們來做一件事情:異步時鐘域的晶片A和B,假設A的頻率是48MHZ,B的頻率是100MHZ。設計一個異步FIFO,使得B發送的資料可以被A正确接收。A和B的資料寬度均為16。

         使用ISE的FIFO IP核:

FPGA之FIFO設計(二)

選擇這個IP核接着進入設定:Native類型就是之前的,可用于block ram,distributed ram等;AXI4就是支援AXI4總線标準的FIFO,在系統設計的時候用得到。這裡我們選擇Native就可以了。

FPGA之FIFO設計(二)

Step 2:如果我們選擇Common Clock的話就會生成同步FIFO,選擇Independent Clocks就變成了異步FIFO。後面的Features就是支援不同讀寫資料位寬,支援ECC資料校驗,首字直通等等。具體地去看Datasheet!

FPGA之FIFO設計(二)

Step 3:選擇First-Word-Fall-Through。這就可以沒有延時讀出資料。另外一個就會有一個周期延時。下面就可以設定位寬。

FPGA之FIFO設計(二)

Step 4:這裡選擇标志位,幾乎滿,幾乎空。

FPGA之FIFO設計(二)

Step 5:選擇複位設定複位後的值為0。

FPGA之FIFO設計(二)

Step 6:這裡設定Count記錄的是讀或者寫的資料的數量。

FPGA之FIFO設計(二)

Step 7:例化

FPGA之FIFO設計(二)

fifo1 YourInstanceName (

    .rst(rst),                                 //複位

    .wr_clk(wr_clk),                   //寫時鐘

    .rd_clk(rd_clk),                    //讀時鐘

    .din(din), // Bus [15 : 0]      //讀入資料

    .wr_en(wr_en),                   //寫使能

    .rd_en(rd_en),                    //讀使能

    .dout(dout), // Bus [15 : 0] //讀出資料

    .full(full),                               //滿

    .almost_full(almost_full), //幾乎滿

    .overflow(overflow),            //溢出

    .empty(empty),                    //空

    .almost_empty(almost_empty),                                  //幾乎空

    .underflow(underflow),                                                  //下溢

    .rd_data_count(rd_data_count), // Bus [9 : 0]           //記錄讀的資料數

    .wr_data_count(wr_data_count)); // Bus [9 : 0]        //記錄寫的資料數

仿真檔案部分:

`timescale 1ns / 100ps

module my_fifo_tb;

	// Inputs
	reg rst;
	reg wr_clk;
	reg rd_clk;
	reg [15:0] din;
	reg wr_en;
	reg rd_en;

	// Outputs
	wire [15:0] dout;
	wire full;
	wire almost_full;
	wire overflow;
	wire empty;
	wire almost_empty;
	wire underflow;
	wire [9:0] rd_data_count;
	wire [9:0] wr_data_count;

	// Instantiate the Unit Under Test (UUT)
	My_fifo uut (
		.rst(rst), 
		.wr_clk(wr_clk), 
		.rd_clk(rd_clk), 
		.din(din), 
		.wr_en(wr_en), 
		.rd_en(rd_en), 
		.dout(dout), 
		.full(full), 
		.almost_full(almost_full), 
		.overflow(overflow), 
		.empty(empty), 
		.almost_empty(almost_empty), 
		.underflow(underflow), 
		.rd_data_count(rd_data_count), 
		.wr_data_count(wr_data_count)
	);
	
	initial begin
		wr_clk = 0;
		forever #5 wr_clk = ~wr_clk;         //f = 100MHZ
	end
	
	initial begin
		rd_clk = 0;
		forever #10.4 rd_clk = ~rd_clk;      //48MHZ
	end
	
	//************************************************************
	//該異步FIFO是高電平複位,是以給系統一個寫時鐘周期的複位信号,使FIFO複位。
	//************************************************************
	task reset;
	begin
		rst = 1;
		@(posedge wr_clk);
		rst = 0;
		@(posedge wr_clk);
	end
	endtask
	
	
	initial begin
		// Initialize Inputs
		rst = 0;
		din = 0;
		wr_en = 0;
		rd_en = 0;

		// Wait 100 ns for global reset to finish
		#100;
      reset;  
		// Add stimulus here

	end
      
endmodule

           

參考資料:

http://www.cnblogs.com/BitArt/archive/2013/04/10/3010073.html