OpenCores
URL https://opencores.org/ocsvn/usb_fpga_2_14/usb_fpga_2_14/trunk

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [examples/] [memfifo/] [fpga-2.13/] [dram_fifo.v] - Rev 2

Compare with Previous | Blame | View Log

/*%
   memfifo -- Connects the bi-directional high speed interface of default firmware to a FIFO built of on-board SDRAM or on-chip BRAM
   Copyright (C) 2009-2017 ZTEX GmbH.
   http://www.ztex.de
 
   Copyright and related rights are licensed under the Solderpad Hardware
   License, Version 0.51 (the "License"); you may not use this file except
   in compliance with the License. You may obtain a copy of the License at
 
       http://solderpad.org/licenses/SHL-0.51.
 
   Unless required by applicable law or agreed to in writing, software, hardware
   and materials distributed under this License is distributed on an "AS IS"
   BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied. See the License for the specific language governing permissions
   and limitations under the License.
%*/
/* 
   Implements a huge FIFO  from all SDRAM.
*/  
 
module fifo_512x128 #(
	parameter ALMOST_EMPTY_OFFSET1 = 13'h0020,    // Sets the almost empty threshold
	parameter ALMOST_EMPTY_OFFSET2 = 13'h0006,    // Sets the almost empty threshold
        parameter ALMOST_FULL_OFFSET1 = 13'h0020,     // Sets almost full threshold
        parameter ALMOST_FULL_OFFSET2 = 13'h0006,     // Sets almost full threshold
        parameter FIRST_WORD_FALL_THROUGH = "TRUE"   // Sets the FIFO FWFT to FALSE, TRUE
    ) (
        input RST,                     // 1-bit input: Reset
	// input signals
        input [127:0] DI,               // 64-bit input: Data input
        output FULL,                    // 1-bit output: Full flag
        output ALMOSTFULL1,       	// 1-bit output: Almost full flag
        output ALMOSTFULL2,       	// 1-bit output: Almost full flag
        output WRERR,                   // 1-bit output: Write error
        input WRCLK,                    // 1-bit input: Rising edge write clock.
        input WREN,                     // 1-bit input: Write enable
	// output signals
	output [127:0] DO,
	output EMPTY,                   // 1-bit output: Empty flag
        output ALMOSTEMPTY1,            // 1-bit output: Almost empty flag
        output ALMOSTEMPTY2,            // 1-bit output: Almost empty flag
        output RDERR,                   // 1-bit output: Read error
        input RDCLK,                    // 1-bit input: Read clock
        input RDEN                      // 1-bit input: Read enable
    );
 
    FIFO36E1 #(
	.ALMOST_EMPTY_OFFSET(ALMOST_EMPTY_OFFSET1),
        .ALMOST_FULL_OFFSET(ALMOST_FULL_OFFSET1),
        .DATA_WIDTH(72),
        .DO_REG(1),
        .EN_ECC_READ("TRUE"),
        .EN_ECC_WRITE("TRUE"),
        .EN_SYN("FALSE"),
        .FIFO_MODE("FIFO36_72"), 
        .FIRST_WORD_FALL_THROUGH(FIRST_WORD_FALL_THROUGH),
        .INIT(72'h000000000000000000),
        .SIM_DEVICE("7SERIES"), 
        .SRVAL(72'h000000000000000000)
    )
    U (
      .DBITERR(),
      .ECCPARITY(),
      .SBITERR(),
      .DO(DO[127:64]),
      .DOP(),
      .ALMOSTEMPTY(ALMOSTEMPTY1),
      .ALMOSTFULL(ALMOSTFULL1),
      .EMPTY(EMPTY_U),
      .FULL(FULL_U),
      .RDCOUNT(),
      .RDERR(RDERR_U),
      .WRCOUNT(),
      .WRERR(WRERR_U),
      .INJECTDBITERR(1'b0),
      .INJECTSBITERR(1'b0),
      .RDCLK(RDCLK),
      .RDEN(RDEN),
      .REGCE(1'b0),
      .RST(RST),
      .RSTREG(1'b0),
      .WRCLK(WRCLK),
      .WREN(WREN),
      .DI(DI[127:64]),
      .DIP(4'd0)
   );
 
    FIFO36E1 #(
	.ALMOST_EMPTY_OFFSET(ALMOST_EMPTY_OFFSET2),
        .ALMOST_FULL_OFFSET(ALMOST_FULL_OFFSET2),
        .DATA_WIDTH(72),
        .DO_REG(1),
        .EN_ECC_READ("TRUE"),
        .EN_ECC_WRITE("TRUE"),
        .EN_SYN("FALSE"),
        .FIFO_MODE("FIFO36_72"), 
        .FIRST_WORD_FALL_THROUGH(FIRST_WORD_FALL_THROUGH),
        .INIT(72'h000000000000000000),
        .SIM_DEVICE("7SERIES"), 
        .SRVAL(72'h000000000000000000)
    )
    L (
      .DBITERR(),
      .ECCPARITY(),
      .SBITERR(),
      .DO(DO[63:0]),
      .DOP(),
      .ALMOSTEMPTY(ALMOSTEMPTY2),
      .ALMOSTFULL(ALMOSTFULL2),
      .EMPTY(EMPTY_L),
      .FULL(FULL_L),
      .RDCOUNT(),
      .RDERR(RDERR_L),
      .WRCOUNT(),
      .WRERR(WRERR_L),
      .INJECTDBITERR(1'b0),
      .INJECTSBITERR(1'b0),
      .RDCLK(RDCLK),
      .RDEN(RDEN),
      .REGCE(1'b0),
      .RST(RST),
      .RSTREG(1'b0),
      .WRCLK(WRCLK),
      .WREN(WREN),
      .DI(DI[63:0]),
      .DIP(4'd0)
   );
 
   assign EMPTY = EMPTY_U || EMPTY_L;
   assign FULL = FULL_U || FULL_L;
   assign RDERR = RDERR_U || RDERR_L;
   assign WRERR = WRERR_U || WRERR_L;
 
endmodule
 
 
module dram_fifo # (
	// fifo parameters, see "7 Series Memory Resources" user guide (ug743)
	parameter ALMOST_EMPTY_OFFSET1 = 13'h0010,      // Sets the almost empty threshold
	parameter ALMOST_EMPTY_OFFSET2 = 13'h0010,      // Sets the almost empty threshold
        parameter ALMOST_FULL_OFFSET1 = 13'h0010,       // Sets almost full threshold
        parameter ALMOST_FULL_OFFSET2 = 13'h0010,       // Sets almost full threshold
        parameter FIRST_WORD_FALL_THROUGH = "TRUE",  	// Sets the FIFO FWFT to FALSE, TRUE
        // clock dividers for PLL outputs not used for memory interface, VCO frequency is 1200 MHz
      	parameter CLKOUT2_DIVIDE = 1,
      	parameter CLKOUT3_DIVIDE = 1,
      	parameter CLKOUT4_DIVIDE = 1,
      	parameter CLKOUT5_DIVIDE = 1,
      	parameter CLKOUT2_PHASE = 0.0,
      	parameter CLKOUT3_PHASE = 0.0,
      	parameter CLKOUT4_PHASE = 0.0,
      	parameter CLKOUT5_PHASE = 0.0
    ) (
	input fxclk_in,					// 48 MHz input clock pin
        input reset,
        output reset_out,				// reset output
      	output clkout2, clkout3, clkout4, clkout5,	// PLL clock outputs not used for memory interface
 
	// ddr3 pins
	inout [15:0] ddr3_dq,
	inout [1:0] ddr3_dqs_n,
	inout [1:0] ddr3_dqs_p,
	output [13:0] ddr3_addr,
	output [2:0] ddr3_ba,
	output ddr3_ras_n,
	output ddr3_cas_n,
	output ddr3_we_n,
        output ddr3_reset_n,
	output [0:0] ddr3_ck_p,
        output [0:0] ddr3_ck_n,
	output [0:0] ddr3_cke,
        output [1:0] ddr3_dm,
	output [0:0] ddr3_odt,
 
	// input fifo interface, see "7 Series Memory Resources" user guide (ug743)
        input [127:0] DI,               // 64-bit input: Data input
        output FULL,                    // 1-bit output: Full flag
        output ALMOSTFULL1,       	// 1-bit output: Almost full flag
        output ALMOSTFULL2,       	// 1-bit output: Almost full flag
        output WRERR,                   // 1-bit output: Write error
        input WRCLK,                    // 1-bit input: Rising edge write clock.
        input WREN,                     // 1-bit input: Write enable
 
	// output fifo interface, see "7 Series Memory Resources" user guide (ug743)
	output [127:0] DO,
	output EMPTY,                   // 1-bit output: Empty flag
        output ALMOSTEMPTY1,            // 1-bit output: Almost empty flag
        output ALMOSTEMPTY2,            // 1-bit output: Almost empty flag
        output RDERR,                   // 1-bit output: Read error
        input RDCLK,                    // 1-bit input: Read clock
        input RDEN,                     // 1-bit input: Read enable
 
	// free memory
	output [APP_ADDR_WIDTH:0] mem_free_out,
 
	// for debugging
	output [9:0] status
    );
 
    localparam APP_DATA_WIDTH = 128;	
    localparam APP_MASK_WIDTH = 16;
    localparam APP_ADDR_WIDTH = 24;
 
    wire pll_fb, clk200_in, clk400_in, clk200, clk400, uiclk, fxclk;
 
    wire mem_reset, ui_clk_sync_rst, init_calib_complete;
    reg reset_buf;
 
// memory control
    reg [7:0] wr_cnt, rd_cnt;
    reg [APP_ADDR_WIDTH-1:0] mem_wr_addr, mem_rd_addr;
    reg [APP_ADDR_WIDTH:0] mem_free;
    reg rd_mode, wr_mode_buf;
    wire wr_mode;
 
// fifo control
    wire infifo_empty, infifo_almost_empty, outfifo_almost_full, infifo_rden;
    wire [APP_DATA_WIDTH-1:0] infifo_do;
    reg [6:0] outfifo_pending;
    reg [9:0] rd_cnt_dbg;
 
// debug
    wire infifo_err_w, outfifo_err_w;
    reg infifo_err, outfifo_err, outfifo_err_uf;
 
// memory interface    
    reg [APP_ADDR_WIDTH-1:0] app_addr;
    reg [2:0] app_cmd;
    reg app_en, app_wdf_wren;
    wire app_rdy, app_wdf_rdy, app_rd_data_valid;
    reg [APP_DATA_WIDTH-1:0] app_wdf_data;
    wire [APP_DATA_WIDTH-1:0] app_rd_data;
 
    BUFG fxclk_buf (
	.I(fxclk_in),
	.O(fxclk) 
    );
 
    BUFG clk200_buf (  		// sometimes it is generated automatically, sometimes not ...
	.I(clk200_in),
	.O(clk200) 
    );
 
    BUFG clk400_buf (
	.I(clk400_in),
	.O(clk400) 
    );
 
    PLLE2_BASE #(
    	.BANDWIDTH("LOW"),
      	.CLKFBOUT_MULT(25),       // f_VCO = 1200 MHz (valid: 800 .. 1600 MHz)
      	.CLKFBOUT_PHASE(0.0),
      	.CLKIN1_PERIOD(0.0),
      	.CLKOUT0_DIVIDE(3),	// 400 MHz
      	.CLKOUT1_DIVIDE(6),	// 200 MHz
      	.CLKOUT2_DIVIDE(CLKOUT2_DIVIDE),
      	.CLKOUT3_DIVIDE(CLKOUT3_DIVIDE),
      	.CLKOUT4_DIVIDE(CLKOUT4_DIVIDE),
      	.CLKOUT5_DIVIDE(CLKOUT5_DIVIDE),
      	.CLKOUT0_DUTY_CYCLE(0.5),
      	.CLKOUT1_DUTY_CYCLE(0.5),
      	.CLKOUT2_DUTY_CYCLE(0.5),
      	.CLKOUT3_DUTY_CYCLE(0.5),
      	.CLKOUT4_DUTY_CYCLE(0.5),
      	.CLKOUT5_DUTY_CYCLE(0.5),
      	.CLKOUT0_PHASE(0.0),
      	.CLKOUT1_PHASE(0.0),
      	.CLKOUT2_PHASE(CLKOUT2_PHASE),
      	.CLKOUT3_PHASE(CLKOUT3_PHASE),
      	.CLKOUT4_PHASE(CLKOUT4_PHASE),
      	.CLKOUT5_PHASE(CLKOUT5_PHASE),
      	.DIVCLK_DIVIDE(1),
      	.REF_JITTER1(0.0),
      	.STARTUP_WAIT("FALSE")
    )
    dram_fifo_pll_inst (
      	.CLKIN1(fxclk),
      	.CLKOUT0(clk400_in),
      	.CLKOUT1(clk200_in),   
      	.CLKOUT2(clkout2),   
      	.CLKOUT3(clkout3),   
      	.CLKOUT4(clkout4),   
      	.CLKOUT5(clkout5),   
      	.CLKFBOUT(pll_fb),
      	.CLKFBIN(pll_fb),
      	.PWRDWN(1'b0),
      	.RST(1'b0)
    );
 
    fifo_512x128 #(
	.ALMOST_EMPTY_OFFSET1(13'h0026),
	.ALMOST_EMPTY_OFFSET2(13'h0006),
	.ALMOST_FULL_OFFSET1(ALMOST_FULL_OFFSET1),
	.ALMOST_FULL_OFFSET2(ALMOST_FULL_OFFSET2),
        .FIRST_WORD_FALL_THROUGH("TRUE")
    ) infifo (
	.RST(reset_buf),
	// output
	.DO(infifo_do),
	.EMPTY(infifo_empty),
	.ALMOSTEMPTY1(infifo_almost_empty),
	.ALMOSTEMPTY2(),
	.RDERR(infifo_err_w),
	.RDCLK(uiclk),
	.RDEN(infifo_rden),
	// input
        .DI(DI),
	.FULL(FULL),
        .ALMOSTFULL1(ALMOSTFULL1),
        .ALMOSTFULL2(ALMOSTFULL2),
        .WRERR(WRERR),
        .WRCLK(WRCLK),
        .WREN(WREN)
    );
 
    fifo_512x128 #(
	.ALMOST_FULL_OFFSET1(13'h0044),
	.ALMOST_FULL_OFFSET2(13'h0004),
	.ALMOST_EMPTY_OFFSET1(ALMOST_EMPTY_OFFSET1),
	.ALMOST_EMPTY_OFFSET2(ALMOST_EMPTY_OFFSET2),
        .FIRST_WORD_FALL_THROUGH(FIRST_WORD_FALL_THROUGH)
    ) outfifo (
	.RST(reset_buf),
	// output
	.DO(DO),
	.EMPTY(EMPTY),
	.ALMOSTEMPTY1(ALMOSTEMPTY1),
	.ALMOSTEMPTY2(ALMOSTEMPTY2),
	.RDERR(RDERR),
	.RDCLK(RDCLK),
	.RDEN(RDEN),
	// input
        .DI(app_rd_data),
	.FULL(),
        .ALMOSTFULL1(outfifo_almost_full),
        .ALMOSTFULL2(),
        .WRERR(outfifo_err_w),
        .WRCLK(uiclk),
        .WREN(app_rd_data_valid)
    );
 
    mig_7series_0   mem0 (
// Memory interface ports
	.ddr3_dq(ddr3_dq),
        .ddr3_dqs_n(ddr3_dqs_n),
        .ddr3_dqs_p(ddr3_dqs_p),
        .ddr3_addr(ddr3_addr),
        .ddr3_ba(ddr3_ba),
        .ddr3_ras_n(ddr3_ras_n),
        .ddr3_cas_n(ddr3_cas_n),
        .ddr3_we_n(ddr3_we_n),
        .ddr3_reset_n(ddr3_reset_n),
        .ddr3_ck_p(ddr3_ck_p[0]),
        .ddr3_ck_n(ddr3_ck_n[0]),
        .ddr3_cke(ddr3_cke[0]),
	.ddr3_dm(ddr3_dm),
        .ddr3_odt(ddr3_odt[0]),
// Application interface ports
        .app_addr( {1'b0, app_addr, 3'b000} ),	
        .app_cmd(app_cmd),
        .app_en(app_en),
        .app_rdy(app_rdy),
        .app_wdf_rdy(app_wdf_rdy), 
        .app_wdf_data(app_wdf_data),
        .app_wdf_mask({ APP_MASK_WIDTH {1'b0} }),
        .app_wdf_end(app_wdf_wren), // always the last word in 4:1 mode 
        .app_wdf_wren(app_wdf_wren),
        .app_rd_data(app_rd_data),
        .app_rd_data_end(app_rd_data_end),
        .app_rd_data_valid(app_rd_data_valid),
        .app_sr_req(1'b0), 
        .app_sr_active(),
        .app_ref_req(1'b0),
        .app_ref_ack(),
        .app_zq_req(1'b0),
        .app_zq_ack(),
        .ui_clk(uiclk),
        .ui_clk_sync_rst(ui_clk_sync_rst),
        .init_calib_complete(init_calib_complete),
        .sys_rst(!reset),
// clocks inputs
        .sys_clk_i(clk400),
        .clk_ref_i(clk200)
    );
 
    assign mem_reset = reset || ui_clk_sync_rst || !init_calib_complete;
    assign reset_out = reset_buf;
    assign wr_mode = wr_mode_buf && app_wdf_rdy && !infifo_empty;
    assign infifo_rden = app_rdy && wr_mode && !rd_mode;
 
    assign status[0] = init_calib_complete;
    assign status[1] = app_rdy;
    assign status[2] = app_wdf_rdy;
    assign status[3] = app_rd_data_valid;
    assign status[4] = infifo_err;
    assign status[5] = outfifo_err;
    assign status[6] = outfifo_err_uf;
    assign status[7] = wr_mode;
    assign status[8] = rd_mode;
    assign status[9] = !reset;
 
    assign mem_free_out = mem_free;
 
    always @ (posedge uiclk)
    begin
// reset
	reset_buf <= mem_reset;
 
	// used for debugging only
	if ( reset_buf ) outfifo_err <= 1'b0;
	else if ( outfifo_err_w ) outfifo_err <= 1'b1;
	if ( reset_buf ) infifo_err <= 1'b0;
	else if ( infifo_err_w ) infifo_err <= 1'b1;
 
	// memory interface --> outfifo
	if ( reset_buf )
	begin
	    outfifo_err_uf <= 1'b0;
	    outfifo_pending <= 7'd0;
	end else if ( app_rd_data_valid && !(rd_mode && app_rdy) ) 
	begin
	    if ( outfifo_pending != 7'd0 ) 
	    begin
		outfifo_pending = outfifo_pending - 7'd1;
	    end else 
	    begin
	        outfifo_err_uf <= 1'b1;
	    end
	end else if ( (!app_rd_data_valid) && rd_mode && app_rdy ) 
	begin
	    outfifo_pending = outfifo_pending + 7'd1;
	end
 
	// wr_mode
	if ( reset_buf )
	begin
	    wr_mode_buf <= 1'b0;
	end else if ( infifo_empty || (!app_wdf_rdy) || wr_cnt[7] || ( mem_free[APP_ADDR_WIDTH:1] == {APP_ADDR_WIDTH{1'b0}} ) )     //  at maximum 128 words
	begin
	    wr_mode_buf <= 1'b0;
	end else if ( (!rd_mode) && !infifo_almost_empty && (mem_free[APP_ADDR_WIDTH:5] != {(APP_ADDR_WIDTH-4){1'b0}}) )  // at least 32 words
	begin
	    wr_mode_buf <= 1'b1;
	end
 
	// rd_mode
	if ( reset_buf )
	begin
	    rd_mode <= 1'b0;
	end else if ( rd_mode || outfifo_almost_full || outfifo_pending[6] || rd_cnt[7] || ( mem_free[APP_ADDR_WIDTH-1:0] == {(APP_ADDR_WIDTH){1'b1}}) || mem_free[APP_ADDR_WIDTH] )	 //  at maximum 128 words )
	begin
	    rd_mode <= 1'b0;
	end else if ( (!wr_mode_buf) && (outfifo_pending[6:5] == 2'd0) && (mem_free[APP_ADDR_WIDTH-1:5] != {(APP_ADDR_WIDTH-5){1'b1}}) )  // at least 32 words
	begin
	    rd_mode <= 1'b1;
	end
 
	if ( reset_buf )
	begin
    	    rd_cnt_dbg <= 10'd0;
    	end else if ( app_rd_data_valid )
	begin
    	    rd_cnt_dbg <= rd_cnt_dbg + 1;
    	end;
 
// command generator
	if ( reset_buf )
	begin
	    app_en <= 1'b0;
	    mem_wr_addr <= {APP_ADDR_WIDTH{1'b0}};
	    mem_rd_addr <= {APP_ADDR_WIDTH{1'b0}};
  	    mem_free <= {1'b1, {APP_ADDR_WIDTH{1'b0}}};
	    wr_cnt <= 8'd0;
	    rd_cnt <= 8'd0;
	end else if ( app_rdy )
	begin
	    if ( rd_mode )
	    begin
		app_cmd <= 3'b001;
		app_en <= 1'b1;
		app_addr <= mem_rd_addr;
		mem_rd_addr <= mem_rd_addr + 1;
	        rd_cnt <= rd_cnt + 1;
		wr_cnt <= 8'd0;
	        mem_free <= mem_free + 1;
	    end else if ( wr_mode )
	    begin
		app_cmd <= 3'b000;
		app_en <= 1'b1;
		app_addr <= mem_wr_addr;
		app_wdf_data <= infifo_do;
//		app_wdf_data <= { 8{mem_wr_addr[15:0]} };
//		app_wdf_data <= { {7{mem_wr_addr[15:0]}},  infifo_do[71:64], infifo_do[7:0] };
		mem_wr_addr <= mem_wr_addr + 1;
		mem_free <= mem_free - 1;
		wr_cnt <= wr_cnt + 1;
		rd_cnt <= 8'd0;
	    end else
	    begin
		app_en <= 1'b0;
		wr_cnt <= 8'd0;
		rd_cnt <= 8'd0;
	    end
	end
 
	if ( reset_buf )
	begin
	    app_wdf_wren <= 1'b0;
//   infifo_rden <= 1'b0;
	end else if ( app_rdy && (!rd_mode) && wr_mode )
	begin
	    app_wdf_wren <= 1'b1;
//   infifo_rden <= 1'b1;
	end else 
	begin
	    if ( app_wdf_rdy ) app_wdf_wren <= 1'b0;
//   infifo_rden <= 1'b0;
	end
 
 
    end
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.