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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_10/] [rtl/] [verilog/] [pci_pciw_fifo_control.v] - Diff between revs 88 and 104

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 88 Rev 104
Line 39... Line 39...
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
//
// CVS Revision History
// CVS Revision History
//
//
// $Log
// $Log: not supported by cvs2svn $
//
//
 
 
/* 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 "pci_constants.v"
`include "pci_constants.v"
Line 56... Line 56...
    rclock_in,
    rclock_in,
    wclock_in,
    wclock_in,
    renable_in,
    renable_in,
    wenable_in,
    wenable_in,
    reset_in,
    reset_in,
//    flush_in,         // not used
 
    almost_full_out,
    almost_full_out,
    full_out,
    full_out,
    almost_empty_out,
    almost_empty_out,
    empty_out,
    empty_out,
    waddr_out,
    waddr_out,
Line 80... Line 79...
input  renable_in, wenable_in;
input  renable_in, wenable_in;
 
 
// reset input
// reset input
input  reset_in;
input  reset_in;
 
 
// flush input
 
//input flush_in ;      // not used
 
 
 
// 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;
Line 107... Line 103...
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 ; // previous
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next
 
 
// 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] ;
Line 122... Line 119...
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
// write allow - writes are allowed when fifo is not full
wire empty ;
assign wallow_out = wenable_in & ~full_out ;
wire full ;
 
 
 
// registered almost_empty and almost_full flags
 
wire almost_empty ;
 
wire almost_full ;
 
 
 
// write allow wire - writes are allowed when fifo is not full
 
wire wallow = wenable_in && !full ;
 
 
 
// write allow output assignment
 
assign wallow_out = wallow ;
 
 
 
// read allow wire
 
wire rallow ;
 
 
 
// full output assignment
 
assign full_out  = full ;
 
 
 
// almost full output assignment
 
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*/ ;     // flush not used for write fifo
wire clear = reset_in ;
 
 
assign empty_out = empty ;
 
 
 
//rallow generation
//rallow generation
assign rallow = renable_in && !empty ; // reads allowed if read enable is high and FIFO is not empty
assign rallow_out = renable_in & ~empty_out ; // reads allowed if read enable is high and FIFO is not empty
 
 
// rallow output assignment
 
assign rallow_out = rallow ;
 
 
 
// almost empty output assignment
 
assign almost_empty_out = almost_empty && !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 ;
 
 
 
 
// read address mux - when read is performed, next address is driven, so next data is available immediately after read
// read address mux - when read is performed, next address is driven, so next data is available immediately after read
// this is convenient for zero wait stait bursts
// this is convenient for zero wait stait bursts
assign raddr_out = rallow ? raddr_plus_one : raddr ;
assign raddr_out = rallow_out ? raddr_plus_one : raddr ;
 
 
always@(posedge rclock_in or posedge clear)
always@(posedge rclock_in or posedge clear)
begin
begin
    if (clear)
    if (clear)
    begin
    begin
        // initial values seem a bit odd - they are this way to allow easier grey pipeline implementation and to allow min fifo size of 8
        // initial values seem a bit odd - they are this way to allow easier grey pipeline implementation and to allow min fifo size of 8
        raddr_plus_one <= #`FF_DELAY 5 ;
        raddr_plus_one <= #`FF_DELAY 5 ;
        raddr          <= #`FF_DELAY 4 ;
        raddr          <= #`FF_DELAY 4 ;
    end
    end
    else if (rallow)
    else if (rallow_out)
    begin
    begin
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
        raddr          <= #`FF_DELAY raddr_plus_one ;
        raddr          <= #`FF_DELAY raddr_plus_one ;
    end
    end
end
end
Line 196... Line 165...
// grey coded address pipeline for status generation in read clock domain
// grey coded address pipeline for status generation in read clock domain
always@(posedge rclock_in or posedge clear)
always@(posedge rclock_in or posedge clear)
begin
begin
    if (clear)
    if (clear)
    begin
    begin
        rgrey_minus2 <= #`FF_DELAY 0 ;
        rgrey_minus2 <= #1 0 ;
        rgrey_minus1 <= #`FF_DELAY 1 ;
        rgrey_minus1 <= #`FF_DELAY 1 ;
        rgrey_addr   <= #`FF_DELAY 3 ;
        rgrey_addr   <= #1 3 ;
        rgrey_next   <= #`FF_DELAY 2 ;
        rgrey_next   <= #`FF_DELAY 2 ;
    end
    end
    else
    else
    if (rallow)
    if (rallow_out)
    begin
    begin
        rgrey_minus2 <= #`FF_DELAY rgrey_minus1 ;
        rgrey_minus2 <= #1 rgrey_minus1 ;
        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
        rgrey_addr   <= #`FF_DELAY rgrey_next ;
        rgrey_addr   <= #1 rgrey_next ;
        rgrey_next   <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
        rgrey_next   <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
    end
    end
end
end
 
 
/*--------------------------------------------------------------------------------------------
/*--------------------------------------------------------------------------------------------
Write address control consists of write address counter and 2 Grey Code Registers:
Write address control consists of write address counter and 3 Grey Code Registers:
 
    - wgrey_minus1 represents previous Grey coded 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 coded address pipeline for status generation in write clock domain
// grey coded address pipeline for status generation in write clock domain
always@(posedge wclock_in or posedge clear)
always@(posedge wclock_in or posedge clear)
begin
begin
    if (clear)
    if (clear)
    begin
    begin
        wgrey_addr   <= #`FF_DELAY 3 ;
        wgrey_minus1 <= #`FF_DELAY 1 ;
 
        wgrey_addr   <= #1 3 ;
        wgrey_next   <= #`FF_DELAY 2 ;
        wgrey_next   <= #`FF_DELAY 2 ;
    end
    end
    else
    else
    if (wallow)
    if (wallow_out)
    begin
    begin
        wgrey_addr   <= #`FF_DELAY wgrey_next ;
        wgrey_minus1 <= #`FF_DELAY wgrey_addr ;
 
        wgrey_addr   <= #1 wgrey_next ;
        wgrey_next   <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
        wgrey_next   <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
    end
    end
end
end
 
 
// write address counter - nothing special except initial value
// write address counter - nothing special except initial value
Line 239... Line 211...
begin
begin
    if (clear)
    if (clear)
        // initial value 5
        // initial value 5
        waddr <= #`FF_DELAY 4 ;
        waddr <= #`FF_DELAY 4 ;
    else
    else
    if (wallow)
    if (wallow_out)
        waddr <= #`FF_DELAY waddr + 1'b1 ;
        waddr <= #`FF_DELAY waddr + 1'b1 ;
end
end
 
 
/*------------------------------------------------------------------------------------------------------------------------------
/*------------------------------------------------------------------------------------------------------------------------------
Full control:
Gray coded address of read address decremented by two is synchronized to write clock domain and compared to:
Gray coded read address pointer is synchronized to write clock domain and compared to Gray coded next write address.
- previous grey coded write address - if they are equal, the fifo is full
If they are equal, fifo is full.
 
 
- gray coded write address. If they are equal, fifo is almost full.
Almost full control:
 
Gray coded address of read address decremented by two is synchronized to write clock domain and compared to Gray coded write
- grey coded next write address. If they are equal, the fifo has two free locations left.
address. If they are equal, fifo is almost full.
 
 
 
Two left control:
 
If Gray coded next write address is equal to Gray coded address of read address decremented by two, the fifo has two free
 
locations left.
 
--------------------------------------------------------------------------------------------------------------------------------*/
--------------------------------------------------------------------------------------------------------------------------------*/
wire [(ADDR_LENGTH - 1):0] wclk_sync_rgrey_addr ;
 
reg  [(ADDR_LENGTH - 1):0] wclk_rgrey_addr ;
 
wire [(ADDR_LENGTH - 1):0] wclk_sync_rgrey_minus2 ;
wire [(ADDR_LENGTH - 1):0] wclk_sync_rgrey_minus2 ;
reg  [(ADDR_LENGTH - 1):0] wclk_rgrey_minus2 ;
reg  [(ADDR_LENGTH - 1):0] wclk_rgrey_minus2 ;
 
 
synchronizer_flop #(ADDR_LENGTH, 3) i_synchronizer_reg_rgrey_addr
 
(
 
    .data_in        (rgrey_addr),
 
    .clk_out        (wclock_in),
 
    .sync_data_out  (wclk_sync_rgrey_addr),
 
    .async_reset    (clear)
 
) ;
 
 
 
synchronizer_flop #(ADDR_LENGTH, 0) i_synchronizer_reg_rgrey_minus2
synchronizer_flop #(ADDR_LENGTH, 0) i_synchronizer_reg_rgrey_minus2
(
(
    .data_in        (rgrey_minus2),
    .data_in        (rgrey_minus2),
    .clk_out        (wclock_in),
    .clk_out        (wclock_in),
    .sync_data_out  (wclk_sync_rgrey_minus2),
    .sync_data_out  (wclk_sync_rgrey_minus2),
Line 281... Line 238...
 
 
always@(posedge wclock_in or posedge clear)
always@(posedge wclock_in or posedge clear)
begin
begin
    if (clear)
    if (clear)
    begin
    begin
        wclk_rgrey_addr   <= #`FF_DELAY 3 ;
 
        wclk_rgrey_minus2 <= #`FF_DELAY 0 ;
        wclk_rgrey_minus2 <= #`FF_DELAY 0 ;
    end
    end
    else
    else
    begin
    begin
        wclk_rgrey_addr   <= #`FF_DELAY wclk_sync_rgrey_addr ;
 
        wclk_rgrey_minus2 <= #`FF_DELAY wclk_sync_rgrey_minus2 ;
        wclk_rgrey_minus2 <= #`FF_DELAY wclk_sync_rgrey_minus2 ;
    end
    end
end
end
 
 
assign full         = (wgrey_next == wclk_rgrey_addr) ;
assign full_out        = (wgrey_minus1 == wclk_rgrey_minus2) ;
assign almost_full  = (wgrey_addr == wclk_rgrey_minus2) ;
assign almost_full_out = (wgrey_addr   == wclk_rgrey_minus2) ;
assign two_left_out = (wgrey_next == wclk_rgrey_minus2) ;
assign two_left_out = (wgrey_next == wclk_rgrey_minus2) ;
 
 
/*------------------------------------------------------------------------------------------------------------------------------
/*------------------------------------------------------------------------------------------------------------------------------
Empty control:
Empty control:
Gray coded write address pointer is synchronized to read clock domain and compared to Gray coded read address pointer.
Gray coded write address pointer is synchronized to read clock domain and compared to Gray coded read address pointer.
Line 322... Line 277...
        rclk_wgrey_addr <= #`FF_DELAY 3 ;
        rclk_wgrey_addr <= #`FF_DELAY 3 ;
    else
    else
        rclk_wgrey_addr <= #`FF_DELAY rclk_sync_wgrey_addr ;
        rclk_wgrey_addr <= #`FF_DELAY rclk_sync_wgrey_addr ;
end
end
 
 
assign almost_empty = (rgrey_next == rclk_wgrey_addr) ;
assign almost_empty_out = (rgrey_next == rclk_wgrey_addr) ;
assign empty        = (rgrey_addr == rclk_wgrey_addr) ;
assign empty_out        = (rgrey_addr == rclk_wgrey_addr) ;
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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