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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_3/] [rtl/] [verilog/] [fifo_control.v] - Diff between revs 2 and 6

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 6
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////  File name "fifo_control.v"                                  ////
////  File name "fifo_control.v"                                  ////
////                                                              ////
////                                                              ////
////  This file is part of the "PCI bridge" project               ////
////  This file is part of the "PCI bridge" project               ////
////  http://www.opencores.org/cores/pci/                         ////
////  http://www.opencores.org/cores/pci/                         ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////  Author(s):                                                  ////
////      - Miha Dolenc (mihad@opencores.org)                     ////
////      - Miha Dolenc (mihad@opencores.org)                     ////
////                                                              ////
////                                                              ////
////  All additional information is avaliable in the README       ////
////  All additional information is avaliable in the README       ////
////  file.                                                       ////
////  file.                                                       ////
////                                                              ////
////                                                              ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org          ////
//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org          ////
////                                                              ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
//// later version.                                               ////
////                                                              ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
//// details.                                                     ////
////                                                              ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
//
// CVS Revision History
// CVS Revision History
//
//
// $Log: not supported by cvs2svn $
// $Log: not supported by cvs2svn $
 
// Revision 1.1.1.1  2001/10/02 15:33:46  mihad
 
// New project directory structure
 
//
//
//
 
 
/* FIFO_CONTROL module provides read/write address and status generation for
/* FIFO_CONTROL module provides read/write address and status generation for
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
 
 
`include "constants.v"
`include "constants.v"
`ifdef FPGA
`ifdef FPGA
    // fifo design in FPGA will be synchronous
    // fifo design in FPGA will be synchronous
    `ifdef SYNCHRONOUS
    `ifdef SYNCHRONOUS
    `else
    `else
        `define SYNCHRONOUS
        `define SYNCHRONOUS
    `endif
    `endif
`endif
`endif
 
 
 
`include "timescale.v"
 
 
module FIFO_CONTROL
module FIFO_CONTROL
(
(
    rclock_in,
    rclock_in,
    wclock_in,
    wclock_in,
    renable_in,
    renable_in,
    wenable_in,
    wenable_in,
    reset_in,
    reset_in,
    flush_in,
    flush_in,
    almost_full_out,
    almost_full_out,
    full_out,
    full_out,
    almost_empty_out,
    almost_empty_out,
    empty_out,
    empty_out,
    waddr_out,
    waddr_out,
    raddr_out,
    raddr_out,
    rallow_out,
    rallow_out,
    wallow_out
    wallow_out
);
);
 
 
// address length parameter - depends on fifo depth
// address length parameter - depends on fifo depth
parameter ADDR_LENGTH = 7 ;
parameter ADDR_LENGTH = 7 ;
 
 
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
input  rclock_in, wclock_in;
input  rclock_in, wclock_in;
 
 
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
//                 write address changes on rising edge of wclock_in when writes are allowed
//                 write address changes on rising edge of wclock_in when writes are allowed
input  renable_in, wenable_in;
input  renable_in, wenable_in;
 
 
// reset input
// reset input
input  reset_in;
input  reset_in;
 
 
// flush input
// flush input
input flush_in ;
input flush_in ;
 
 
// almost full and empy status outputs
// almost full and empy status outputs
output almost_full_out, almost_empty_out;
output almost_full_out, almost_empty_out;
 
 
// full and empty status outputs
// full and empty status outputs
output full_out, empty_out;
output full_out, empty_out;
 
 
// read and write addresses outputs
// read and write addresses outputs
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
 
 
// read and write allow outputs
// read and write allow outputs
output rallow_out, wallow_out ;
output rallow_out, wallow_out ;
 
 
// read address register
// read address register
reg [(ADDR_LENGTH - 1):0] raddr ;
reg [(ADDR_LENGTH - 1):0] raddr ;
 
 
// write address register
// write address register
reg [(ADDR_LENGTH - 1):0] waddr;
reg [(ADDR_LENGTH - 1):0] waddr;
assign waddr_out = waddr ;
assign waddr_out = waddr ;
 
 
// grey code registers
// grey code registers
// grey code pipeline for write address
// grey code pipeline for write address
reg [(ADDR_LENGTH - 1):0] wgrey_minus1 ; // one before current grey coded write address
reg [(ADDR_LENGTH - 1):0] wgrey_minus1 ; // one before current grey coded write address
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current grey coded write address
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current grey coded write address
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next grey coded write address
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next grey coded write address
 
 
// next write gray address calculation - bitwise xor between address and shifted address
// next write gray address calculation - bitwise xor between address and shifted address
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
 
 
// grey code pipeline for read address
// grey code pipeline for read address
reg [(ADDR_LENGTH - 1):0] rgrey_minus2 ; // two before current
reg [(ADDR_LENGTH - 1):0] rgrey_minus2 ; // two before current
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
 
 
// next read gray address calculation - bitwise xor between address and shifted address
// next read gray address calculation - bitwise xor between address and shifted address
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
 
 
// FFs for registered empty and full flags
// FFs for registered empty and full flags
reg empty ;
reg empty ;
reg full ;
reg full ;
 
 
// almost_empty and almost_full tag - implemented as latches
// almost_empty and almost_full tag - implemented as latches
reg almost_empty ;
reg almost_empty ;
reg almost_full ;
reg almost_full ;
 
 
// write allow wire - writes are allowed when fifo is not full
// write allow wire - writes are allowed when fifo is not full
wire wallow = wenable_in && ~full ;
wire wallow = wenable_in && ~full ;
 
 
// write allow output assignment
// write allow output assignment
assign wallow_out = wallow ;
assign wallow_out = wallow ;
 
 
// read allow wire
// read allow wire
wire rallow ;
wire rallow ;
 
 
// full output assignment
// full output assignment
assign full_out  = full ;
assign full_out  = full ;
 
 
// almost full output assignment
// almost full output assignment
assign almost_full_out  = almost_full && ~full ;
assign almost_full_out  = almost_full && ~full ;
 
 
// clear generation for FFs and registers
// clear generation for FFs and registers
wire clear = reset_in || flush_in ;
wire clear = reset_in || flush_in ;
 
 
`ifdef SYNCHRONOUS
`ifdef SYNCHRONOUS
 
 
    reg wclock_nempty_detect ;
    reg wclock_nempty_detect ;
    always@(posedge reset_in or posedge wclock_in)
    always@(posedge reset_in or posedge wclock_in)
    begin
    begin
        if (reset_in)
        if (reset_in)
            wclock_nempty_detect <= #`FF_DELAY 1'b0 ;
            wclock_nempty_detect <= #`FF_DELAY 1'b0 ;
        else
        else
            wclock_nempty_detect <= #`FF_DELAY (rgrey_addr != wgrey_addr) ;
            wclock_nempty_detect <= #`FF_DELAY (rgrey_addr != wgrey_addr) ;
    end
    end
 
 
    // special synchronizing mechanism for different implementations - in synchronous imp., empty is prolonged for 1 clock edge if no write clock comes after initial write
    // special synchronizing mechanism for different implementations - in synchronous imp., empty is prolonged for 1 clock edge if no write clock comes after initial write
    reg stretched_empty ;
    reg stretched_empty ;
    always@(posedge rclock_in or posedge clear)
    always@(posedge rclock_in or posedge clear)
    begin
    begin
        if(clear)
        if(clear)
            stretched_empty <= #`FF_DELAY 1'b1 ;
            stretched_empty <= #`FF_DELAY 1'b1 ;
        else
        else
            stretched_empty <= #`FF_DELAY empty && ~wclock_nempty_detect ;
            stretched_empty <= #`FF_DELAY empty && ~wclock_nempty_detect ;
    end
    end
 
 
    // empty output is actual empty + 1 read clock cycle ( stretched empty )
    // empty output is actual empty + 1 read clock cycle ( stretched empty )
    assign empty_out = empty || stretched_empty ;
    assign empty_out = empty || stretched_empty ;
 
 
    //rallow generation    
    //rallow generation    
    assign rallow = renable_in && ~empty && ~stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
    assign rallow = renable_in && ~empty && ~stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
 
 
    // rallow output assignment
    // rallow output assignment
    assign rallow_out = rallow ;
    assign rallow_out = rallow ;
 
 
    // almost empty output assignment
    // almost empty output assignment
    assign almost_empty_out = almost_empty && ~empty && ~stretched_empty ;
    assign almost_empty_out = almost_empty && ~empty && ~stretched_empty ;
 
 
    // at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
    // at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
    // when FIFO is empty, this register provides actual read address, so first location can be read
    // when FIFO is empty, this register provides actual read address, so first location can be read
    reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
    reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
 
 
    // address output mux - when FIFO is empty, current actual address is driven out, when it is non - empty next address is driven out
    // address output mux - when FIFO is empty, current actual address is driven out, when it is non - empty next address is driven out
    // done for zero wait state burst
    // done for zero wait state burst
    assign raddr_out = empty_out ? raddr : raddr_plus_one ;
    assign raddr_out = empty_out ? raddr : raddr_plus_one ;
 
 
    // enable for this register
    // enable for this register
    wire raddr_plus_one_en = rallow ;
    wire raddr_plus_one_en = rallow ;
    always@(posedge rclock_in or posedge clear)
    always@(posedge rclock_in or posedge clear)
    begin
    begin
        if (clear)
        if (clear)
        begin
        begin
            raddr_plus_one[(ADDR_LENGTH - 1):1] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0}} ;
            raddr_plus_one[(ADDR_LENGTH - 1):1] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0}} ;
            raddr_plus_one[0] <= #`FF_DELAY 1'b1 ;
            raddr_plus_one[0] <= #`FF_DELAY 1'b1 ;
        end
        end
        else if (raddr_plus_one_en)
        else if (raddr_plus_one_en)
            raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
            raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
    end
    end
 
 
    // raddr is filled with raddr_plus_one on rising read clock edge when rallow is high
    // raddr is filled with raddr_plus_one on rising read clock edge when rallow is high
    always@(posedge rclock_in or posedge clear)
    always@(posedge rclock_in or posedge clear)
    begin
    begin
            if (clear)
            if (clear)
            // initial value is 000......00
            // initial value is 000......00
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
            else if (rallow)
            else if (rallow)
                raddr <= #`FF_DELAY raddr_plus_one ;
                raddr <= #`FF_DELAY raddr_plus_one ;
    end
    end
 
 
`else
`else
    // asynchronous RAM storage for FIFOs - somewhat simpler control logic
    // asynchronous RAM storage for FIFOs - somewhat simpler control logic
    //rallow generation    
    //rallow generation    
    assign rallow = renable_in && ~empty ;
    assign rallow = renable_in && ~empty ;
 
 
    assign rallow_out = rallow;
    assign rallow_out = rallow;
 
 
    assign almost_empty_out = almost_empty && ~empty ;
    assign almost_empty_out = almost_empty && ~empty ;
 
 
    // read address counter - normal counter, nothing to it
    // read address counter - normal counter, nothing to it
    // for asynchronous implementation, there is no need for pointing to next address.
    // for asynchronous implementation, there is no need for pointing to next address.
    // On clock edge that read is performed, read address will change and on the next clock edge
    // On clock edge that read is performed, read address will change and on the next clock edge
    // asynchronous memory will provide next data
    // asynchronous memory will provide next data
    always@(posedge rclock_in or posedge clear)
    always@(posedge rclock_in or posedge clear)
    begin
    begin
            if (clear)
            if (clear)
            // initial value is 000......00
            // initial value is 000......00
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
            else if (rallow)
            else if (rallow)
                    raddr <= #`FF_DELAY raddr + 1'b1 ;
                    raddr <= #`FF_DELAY raddr + 1'b1 ;
    end
    end
 
 
    assign empty_out = empty ;
    assign empty_out = empty ;
    assign raddr_out = raddr ;
    assign raddr_out = raddr ;
`endif
`endif
 
 
/*-----------------------------------------------------------------------------------------------
/*-----------------------------------------------------------------------------------------------
Read address control consists of Read address counter and Grey Address pipeline
Read address control consists of Read address counter and Grey Address pipeline
There are 4 Grey addresses:
There are 4 Grey addresses:
    - rgrey_minus2 is Grey Code of address two before current address
    - rgrey_minus2 is Grey Code of address two before current address
    - rgrey_minus1 is Grey Code of address one before current address
    - rgrey_minus1 is Grey Code of address one before current address
    - rgrey_addr is Grey Code of current read address
    - rgrey_addr is Grey Code of current read address
    - rgrey_next is Grey Code of next read address
    - rgrey_next is Grey Code of next read address
--------------------------------------------------------------------------------------------------*/
--------------------------------------------------------------------------------------------------*/
// grey code register for two before read address
// grey code register for two before read address
always@(posedge rclock_in or posedge clear)
always@(posedge rclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
    begin
    begin
        // initial value is 100......010
        // initial value is 100......010
                rgrey_minus2[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
                rgrey_minus2[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
        rgrey_minus2[(ADDR_LENGTH  - 2):2] <= #`FF_DELAY { (ADDR_LENGTH  - 3){1'b0} } ;
        rgrey_minus2[(ADDR_LENGTH  - 2):2] <= #`FF_DELAY { (ADDR_LENGTH  - 3){1'b0} } ;
        rgrey_minus2[1:0] <= #`FF_DELAY 2'b10 ;
        rgrey_minus2[1:0] <= #`FF_DELAY 2'b10 ;
    end
    end
        else
        else
                if (rallow)
                if (rallow)
                        rgrey_minus2 <= #`FF_DELAY rgrey_minus1 ;
                        rgrey_minus2 <= #`FF_DELAY rgrey_minus1 ;
end
end
 
 
// grey code register for one before read address
// grey code register for one before read address
always@(posedge rclock_in or posedge clear)
always@(posedge rclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
    begin
    begin
        // initial value is 100......011
        // initial value is 100......011
                rgrey_minus1[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
                rgrey_minus1[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
        rgrey_minus1[(ADDR_LENGTH  - 2):2] <= #`FF_DELAY { (ADDR_LENGTH  - 3){1'b0} } ;
        rgrey_minus1[(ADDR_LENGTH  - 2):2] <= #`FF_DELAY { (ADDR_LENGTH  - 3){1'b0} } ;
        rgrey_minus1[1:0] <= #`FF_DELAY 2'b11 ;
        rgrey_minus1[1:0] <= #`FF_DELAY 2'b11 ;
    end
    end
        else
        else
                if (rallow)
                if (rallow)
                        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
                        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
end
end
 
 
// grey code register for read address - represents current Read Address
// grey code register for read address - represents current Read Address
always@(posedge rclock_in or posedge clear)
always@(posedge rclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
    begin
    begin
        // initial value is 100.......01
        // initial value is 100.......01
                rgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
                rgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
        rgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
        rgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
        rgrey_addr[0] <= #`FF_DELAY 1'b1 ;
        rgrey_addr[0] <= #`FF_DELAY 1'b1 ;
    end
    end
        else
        else
                if (rallow)
                if (rallow)
                        rgrey_addr <= #`FF_DELAY rgrey_next ;
                        rgrey_addr <= #`FF_DELAY rgrey_next ;
end
end
 
 
// grey code register for next read address - represents Grey Code of next read address    
// grey code register for next read address - represents Grey Code of next read address    
always@(posedge rclock_in or posedge clear)
always@(posedge rclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
    begin
    begin
        // initial value is 100......00
        // initial value is 100......00
                rgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
                rgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
        rgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
        rgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
    end
    end
        else
        else
                if (rallow)
                if (rallow)
            rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
            rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
end
end
 
 
/*--------------------------------------------------------------------------------------------
/*--------------------------------------------------------------------------------------------
Write address control consists of write address counter and three Grey Code Registers:
Write address control consists of write address counter and three Grey Code Registers:
    - wgrey_minus1 represents Grey Coded address of location one before current write address
    - wgrey_minus1 represents Grey Coded address of location one before current write address
    - wgrey_addr represents current Grey Coded write address
    - wgrey_addr represents current Grey Coded write address
    - wgrey_next represents Grey Coded next write address
    - wgrey_next represents Grey Coded next write address
----------------------------------------------------------------------------------------------*/
----------------------------------------------------------------------------------------------*/
// grey code register for one before write address
// grey code register for one before write address
always@(posedge wclock_in or posedge clear)
always@(posedge wclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
    begin
    begin
        // initial value is 100.....001
        // initial value is 100.....001
        wgrey_minus1[(ADDR_LENGTH - 1)]   <= #`FF_DELAY 1'b1 ;
        wgrey_minus1[(ADDR_LENGTH - 1)]   <= #`FF_DELAY 1'b1 ;
        wgrey_minus1[(ADDR_LENGTH - 2):2] <= #`FF_DELAY { (ADDR_LENGTH - 3){1'b0} } ;
        wgrey_minus1[(ADDR_LENGTH - 2):2] <= #`FF_DELAY { (ADDR_LENGTH - 3){1'b0} } ;
        wgrey_minus1[1:0] <= #`FF_DELAY 2'b11 ;
        wgrey_minus1[1:0] <= #`FF_DELAY 2'b11 ;
    end
    end
        else
        else
    if (wallow)
    if (wallow)
            wgrey_minus1 <= #`FF_DELAY wgrey_addr ;
            wgrey_minus1 <= #`FF_DELAY wgrey_addr ;
end
end
 
 
// grey code register for write address
// grey code register for write address
always@(posedge wclock_in or posedge clear)
always@(posedge wclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
    begin
    begin
        // initial value is 100.....001
        // initial value is 100.....001
        wgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
        wgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
        wgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
        wgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
        wgrey_addr[0] <= #`FF_DELAY 1'b1 ;
        wgrey_addr[0] <= #`FF_DELAY 1'b1 ;
    end
    end
        else
        else
    if (wallow)
    if (wallow)
            wgrey_addr <= #`FF_DELAY wgrey_next ;
            wgrey_addr <= #`FF_DELAY wgrey_next ;
end
end
 
 
// grey code register for next write address
// grey code register for next write address
always@(posedge wclock_in or posedge clear)
always@(posedge wclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
    begin
    begin
        // initial value is 100......00
        // initial value is 100......00
                wgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
                wgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
        wgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
        wgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
    end
    end
        else
        else
    if (wallow)
    if (wallow)
        wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
        wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
end
end
 
 
// write address counter - nothing special
// write address counter - nothing special
always@(posedge wclock_in or posedge clear)
always@(posedge wclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
        // initial value 00.........00
        // initial value 00.........00
                waddr <= #`FF_DELAY { (ADDR_LENGTH){1'b0} } ;
                waddr <= #`FF_DELAY { (ADDR_LENGTH){1'b0} } ;
        else
        else
        if (wallow)
        if (wallow)
                waddr <= #`FF_DELAY waddr + 1'b1 ;
                waddr <= #`FF_DELAY waddr + 1'b1 ;
end
end
 
 
/*------------------------------------------------------------------------------------------------------------------------------
/*------------------------------------------------------------------------------------------------------------------------------
Registered full control:
Registered full control:
registered full is set on rising edge of wclock_in, when fifo is almost full and something gets written to it.
registered full is set on rising edge of wclock_in, when fifo is almost full and something gets written to it.
It's kept high until something is read from FIFO, which is registered on next rising write clock edge.
It's kept high until something is read from FIFO, which is registered on next rising write clock edge.
 
 
Registered almost full control:
Registered almost full control:
Almost full flag is set on rising write clock edge whenever two free locations are left in fifo and another entry is written to it.
Almost full flag is set on rising write clock edge whenever two free locations are left in fifo and another entry is written to it.
It remains set if nothing is read/written from/to fifo. All operations are synchronized on write clock.
It remains set if nothing is read/written from/to fifo. All operations are synchronized on write clock.
--------------------------------------------------------------------------------------------------------------------------------*/
--------------------------------------------------------------------------------------------------------------------------------*/
wire comb_full          = wgrey_next == rgrey_addr ;
wire comb_full          = wgrey_next == rgrey_addr ;
wire comb_almost_full   = wgrey_addr == rgrey_minus2 ;
wire comb_almost_full   = wgrey_addr == rgrey_minus2 ;
wire comb_two_left      = wgrey_next == rgrey_minus2 ;
wire comb_two_left      = wgrey_next == rgrey_minus2 ;
 
 
//combinatorial input to Registered full FlipFlop
//combinatorial input to Registered full FlipFlop
wire reg_full = (wallow && comb_almost_full) || (comb_full) ;
wire reg_full = (wallow && comb_almost_full) || (comb_full) ;
 
 
always@(posedge wclock_in or posedge clear)
always@(posedge wclock_in or posedge clear)
begin
begin
        if (clear)
        if (clear)
                full <= #`FF_DELAY 1'b0 ;
                full <= #`FF_DELAY 1'b0 ;
        else
        else
                full <= #`FF_DELAY reg_full ;
                full <= #`FF_DELAY reg_full ;
end
end
 
 
// input for almost full flip flop
// input for almost full flip flop
wire reg_almost_full_in = wallow && comb_two_left || comb_almost_full ;
wire reg_almost_full_in = wallow && comb_two_left || comb_almost_full ;
 
 
always@(posedge clear or posedge wclock_in)
always@(posedge clear or posedge wclock_in)
begin
begin
    if (clear)
    if (clear)
        almost_full <= #`FF_DELAY 1'b0 ;
        almost_full <= #`FF_DELAY 1'b0 ;
    else
    else
        almost_full <= #`FF_DELAY reg_almost_full_in ;
        almost_full <= #`FF_DELAY reg_almost_full_in ;
end
end
 
 
/*------------------------------------------------------------------------------------------------------------------------------
/*------------------------------------------------------------------------------------------------------------------------------
Registered empty control:
Registered empty control:
registered empty is set on rising edge of rclock_in when one location is occupied and read from it. It remains set until
registered empty is set on rising edge of rclock_in when one location is occupied and read from it. It remains set until
something is written to fifo which is detected on next read clock edge.
something is written to fifo which is detected on next read clock edge.
 
 
Registered almost empty control:
Registered almost empty control:
Almost empty is set on rising clock edge of read clock when two locations are used in fifo and one of them is read from it.
Almost empty is set on rising clock edge of read clock when two locations are used in fifo and one of them is read from it.
It remains set until something is read/written from/to fifo. All operations are detected on rising edge of read clock.
It remains set until something is read/written from/to fifo. All operations are detected on rising edge of read clock.
--------------------------------------------------------------------------------------------------------------------------------*/
--------------------------------------------------------------------------------------------------------------------------------*/
wire comb_almost_empty  = rgrey_next == wgrey_addr ;
wire comb_almost_empty  = rgrey_next == wgrey_addr ;
wire comb_empty         = rgrey_addr == wgrey_addr ;
wire comb_empty         = rgrey_addr == wgrey_addr ;
wire comb_two_used      = rgrey_next == wgrey_minus1 ;
wire comb_two_used      = rgrey_next == wgrey_minus1 ;
 
 
// combinatorial input for registered emty FlipFlop
// combinatorial input for registered emty FlipFlop
wire reg_empty = (rallow && comb_almost_empty) || comb_empty ;
wire reg_empty = (rallow && comb_almost_empty) || comb_empty ;
 
 
always@(posedge rclock_in or posedge clear)
always@(posedge rclock_in or posedge clear)
begin
begin
    if (clear)
    if (clear)
        empty <= #`FF_DELAY 1'b1 ;
        empty <= #`FF_DELAY 1'b1 ;
        else
        else
        empty <= #`FF_DELAY reg_empty ;
        empty <= #`FF_DELAY reg_empty ;
end
end
 
 
// input for almost empty flip flop
// input for almost empty flip flop
wire reg_almost_empty = rallow && comb_two_used || comb_almost_empty ;
wire reg_almost_empty = rallow && comb_two_used || comb_almost_empty ;
always@(posedge clear or posedge rclock_in)
always@(posedge clear or posedge rclock_in)
begin
begin
    if (clear)
    if (clear)
        almost_empty <= #`FF_DELAY 1'b0 ;
        almost_empty <= #`FF_DELAY 1'b0 ;
    else
    else
        almost_empty <= #`FF_DELAY reg_almost_empty ;
        almost_empty <= #`FF_DELAY reg_almost_empty ;
end
end
 
 
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

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