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.01b/] [bram_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 FWFT FIFO from all BRAM.
*/  
 
 
module bram_fifo # (
      	parameter BRAM_N = 32		// Number of BRAM blocks; 32 available on LX16
    ) (
	input reset,			// reset
	// FIFO protocol equal to FWFT FIFO in "7 Series Memory Resources" user guide (ug743)
	// input fifo interface
        input [31:0] DI,                // must be hold while FULL is asserted
        output FULL,                    // 1-bit output: Full flag
        output reg 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
	output reg [31:0] DO,
	output reg EMPTY,               // 1-bit output: Empty flag, can be used as data valid indicator
        output reg RDERR,               // 1-bit output: Read error
        input RDCLK,                    // 1-bit input: Read clock
        input RDEN                      // 1-bit input: Read enable
    );
 
    localparam ADDR_WIDTH = 15;		
    localparam ADDR_MAX = 512*BRAM_N-1;
 
    reg [31:0] BRAM[0:ADDR_MAX];
 
    // DRAM controller: writing
    reg reset_wr, WREN_BUF;
    reg [7:0] reset_wr_buf = 8'd0;
    reg [ADDR_WIDTH-1:0] WR_ADDR, WR_ADDR_NEXT, RD_ADDR_WR1, RD_ADDR_WR2, RD_ADDR_WR3;
 
    // DRAM controller: reading
    reg reset_rd;
    reg [7:0] reset_rd_buf = 8'd0;
    reg [ADDR_WIDTH-1:0] RD_ADDR, RD_ADDR_NEXT, WR_ADDR_RD1, WR_ADDR_RD2, WR_ADDR_RD3;
 
    assign FULL = reset_wr || FULL2;
    wire FULL2 = (WR_ADDR_NEXT==RD_ADDR_WR3) || (WR_ADDR_NEXT==RD_ADDR_WR2) || (WR_ADDR_NEXT==RD_ADDR_WR1);
 
    always @ (posedge WRCLK)
    begin
        RD_ADDR_WR1 <= RD_ADDR;
        RD_ADDR_WR2 <= RD_ADDR_WR1;
        RD_ADDR_WR3 <= RD_ADDR_WR2;
 
	reset_wr_buf <= { reset, reset_wr_buf[7:1] };
	reset_wr <= reset_wr_buf != 8'd0;
 
	if ( reset_wr )
	begin
	    WR_ADDR <= ADDR_MAX;
	    WR_ADDR_NEXT <= { (ADDR_WIDTH){1'b0} };
	    WREN_BUF <= 1'b0;
	end else
	begin
	    if ( WREN || WREN_BUF ) 		// process data
	    begin
		if ( ! FULL2 ) 
		begin
		    BRAM[WR_ADDR] <= DI;
		    WR_ADDR <= WR_ADDR_NEXT;
		    WR_ADDR_NEXT <= WR_ADDR_NEXT == ADDR_MAX ? { ADDR_WIDTH{1'b0} } : WR_ADDR_NEXT + 1;
		end
		WREN_BUF <= FULL2;
	    end
	    WRERR <= WREN && WREN_BUF;
	end
    end
 
 
    always @ (posedge RDCLK)
    begin
        WR_ADDR_RD1 <= WR_ADDR;
        WR_ADDR_RD2 <= WR_ADDR_RD1;
        WR_ADDR_RD3 <= WR_ADDR_RD2;
 
	reset_rd_buf <= { reset, reset_rd_buf[7:1] };
	reset_rd <= reset_rd_buf != 8'd0;
 
	if ( reset_rd )
	begin
	    RD_ADDR <= ADDR_MAX;
	    RD_ADDR_NEXT <= { (ADDR_WIDTH){1'b0} };
	    EMPTY <= 1'b1;
	end else
	begin
	    RDERR <= RDEN && EMPTY;
 
	    if ( RDEN || EMPTY )
	    begin
		if ( (RD_ADDR_NEXT!=WR_ADDR_RD3) && (RD_ADDR_NEXT!=WR_ADDR_RD2) && (RD_ADDR_NEXT!=WR_ADDR_RD1) && (RD_ADDR!=WR_ADDR_RD3) && (RD_ADDR!=WR_ADDR_RD2) && (RD_ADDR!=WR_ADDR_RD1) ) 
		begin
		    EMPTY <= 1'b0;
    		    DO <= BRAM[RD_ADDR];
//		    DO <= { BRAM[RD_ADDR][23:0], RD_ADDR[7:0] };
		    RD_ADDR <= RD_ADDR_NEXT;
		    RD_ADDR_NEXT <= RD_ADDR_NEXT == ADDR_MAX ? { ADDR_WIDTH{1'b0} } : RD_ADDR_NEXT + 1;
		end else
		begin
		    EMPTY <= 1'b1;
		end
	    end
	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.