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

Subversion Repositories nysa_sata

[/] [nysa_sata/] [trunk/] [rtl/] [generic/] [ppfifo.v] - Diff between revs 3 and 5

Only display areas with differences | Details | Blame | View Log

Rev 3 Rev 5
/*
/*
Distributed under the MIT licesnse.
Distributed under the MIT licesnse.
Copyright (c) 2011 Dave McCoy (dave.mccoy@cospandesign.com)
Copyright (c) 2011 Dave McCoy (dave.mccoy@cospandesign.com)
 
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
so, subject to the following conditions:
 
 
The above copyright notice and this permission notice shall be included in all
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
copies or substantial portions of the Software.
 
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
*/
*/
 
 
`timescale 1ns/1ps
`timescale 1ns/1ps
 
 
//XXX: NOTE: All counts are 24bits long, this could be a parameter in the future
//XXX: NOTE: All counts are 24bits long, this could be a parameter in the future
 
 
 
 
module ppfifo
module ppfifo
#(parameter     DATA_WIDTH    = 8,
#(parameter     DATA_WIDTH    = 8,
                ADDRESS_WIDTH = 4
                ADDRESS_WIDTH = 4
)(
)(
 
 
  //universal input
  //universal input
  input                             reset,
  input                             reset,
 
 
  //write side
  //write side
  input                             write_clock,
  input                             write_clock,
  output reg  [1:0]                 write_ready,
  output reg  [1:0]                 write_ready,
  input       [1:0]                 write_activate,
  input       [1:0]                 write_activate,
  output      [23:0]                write_fifo_size,
  output      [23:0]                write_fifo_size,
  input                             write_strobe,
  input                             write_strobe,
  input       [DATA_WIDTH - 1: 0]   write_data,
  input       [DATA_WIDTH - 1: 0]   write_data,
  output                            starved,
  output                            starved,
 
 
  //read side
  //read side
  input                             read_clock,
  input                             read_clock,
  input                             read_strobe,
  input                             read_strobe,
  output reg                        read_ready,
  output reg                        read_ready,
  input                             read_activate,
  input                             read_activate,
  output reg  [23:0]                read_count,
  output reg  [23:0]                read_count,
  output      [DATA_WIDTH - 1: 0]   read_data,
  output      [DATA_WIDTH - 1: 0]   read_data,
 
 
  output                            inactive
  output                            inactive
 
 
);
);
 
 
localparam FIFO_DEPTH = (1 << ADDRESS_WIDTH);
localparam FIFO_DEPTH = (1 << ADDRESS_WIDTH);
 
 
//Local Registers/Wires
//Local Registers/Wires
 
 
//Write Side
//Write Side
wire                        ppfifo_ready;  // The write side only needs to
wire                        ppfifo_ready;  // The write side only needs to
                                           // know were ready if we don't
                                           // know were ready if we don't
                                           // write anything read won't start
                                           // write anything read won't start
wire  [ADDRESS_WIDTH: 0]    addr_in;       // Actual address to the BRAM
wire  [ADDRESS_WIDTH: 0]    addr_in;       // Actual address to the BRAM
reg   [ADDRESS_WIDTH - 1: 0]write_address;
reg   [ADDRESS_WIDTH - 1: 0]write_address;
reg                         r_wselect;      // Select the FIFO to work with
reg                         r_wselect;      // Select the FIFO to work with
reg                         write_enable;  // Enable a write to the BRAM
reg                         write_enable;  // Enable a write to the BRAM
 
 
reg   [1:0]                 wcc_read_ready;// Tell read side a FIFO is ready
reg   [1:0]                 wcc_read_ready;// Tell read side a FIFO is ready
wire  [1:0]                 wcc_read_done;
wire  [1:0]                 wcc_read_done;
                                            // write status of the read
                                            // write status of the read
                                            // available
                                            // available
reg                         wcc_tie_select; //because it's possible if the read
reg                         wcc_tie_select; //because it's possible if the read
                                            //side is slower than the write
                                            //side is slower than the write
                                            //side it might be unknown which
                                            //side it might be unknown which
                                            //side was selected first, so use
                                            //side was selected first, so use
                                            //this signal to break ties
                                            //this signal to break ties
 
 
reg   [23:0]                w_count[1:0];   // save the write count for the read
reg   [23:0]                w_count[1:0];   // save the write count for the read
                                            // side
                                            // side
reg                         w_empty[1:0];
reg                         w_empty[1:0];
reg                         w_reset;        //write side reset
reg                         w_reset;        //write side reset
reg   [4:0]                 w_reset_timeout;
reg   [4:0]                 w_reset_timeout;
wire                        ready;
wire                        ready;
 
 
//Read Side
//Read Side
wire  [ADDRESS_WIDTH: 0]    addr_out;     //Actual address to the BRAM
wire  [ADDRESS_WIDTH: 0]    addr_out;     //Actual address to the BRAM
reg                         r_reset;
reg                         r_reset;
reg   [4:0]                 r_reset_timeout;
reg   [4:0]                 r_reset_timeout;
 
 
reg   [ADDRESS_WIDTH - 1: 0]r_address;    //Address to access a bank
reg   [ADDRESS_WIDTH - 1: 0]r_address;    //Address to access a bank
reg                         r_rselect;     //Select a bank (Select a FIFO)
reg                         r_rselect;     //Select a bank (Select a FIFO)
 
 
wire  [1:0]                 rcc_read_ready;
wire  [1:0]                 rcc_read_ready;
                                          // Write side says X is ready
                                          // Write side says X is ready
reg   [1:0]                 rcc_read_done;// Tell write side X is ready
reg   [1:0]                 rcc_read_done;// Tell write side X is ready
wire                        rcc_tie_select;
wire                        rcc_tie_select;
                                          //If there is a tie, then this will
                                          //If there is a tie, then this will
                                          //break it
                                          //break it
 
 
reg   [23:0]                r_size[1:0];  // Size of FX read
reg   [23:0]                r_size[1:0];  // Size of FX read
 
 
reg   [1:0]                 r_ready;      //FIFO is ready
reg   [1:0]                 r_ready;      //FIFO is ready
reg   [1:0]                 r_wait;       //Waiting for write side to send data
reg   [1:0]                 r_wait;       //Waiting for write side to send data
reg   [1:0]                 r_activate;   //Controls which FIFO is activated
reg   [1:0]                 r_activate;   //Controls which FIFO is activated
 
 
reg                         r_next_fifo;  //If both FIFOs are availalbe use this
reg                         r_next_fifo;  //If both FIFOs are availalbe use this
 
 
reg   [1:0]                 r_pre_activate; //Used to delay the clock cycle by
reg   [1:0]                 r_pre_activate; //Used to delay the clock cycle by
                                            //one when the user activates the
                                            //one when the user activates the
                                            //FIFO
                                            //FIFO
 
 
reg                         r_pre_strobe;
reg                         r_pre_strobe;
reg                         r_pre_read_wait;//Wait an extra cycle so the registered data has a chance to set
reg                         r_pre_read_wait;//Wait an extra cycle so the registered data has a chance to set
                                            //the data to be registered
                                            //the data to be registered
wire  [DATA_WIDTH - 1: 0]   w_read_data;    //data from the read FIFO
wire  [DATA_WIDTH - 1: 0]   w_read_data;    //data from the read FIFO
reg   [DATA_WIDTH - 1: 0]   r_read_data;    //data from the read FIFO
reg   [DATA_WIDTH - 1: 0]   r_read_data;    //data from the read FIFO
 
 
 
 
 
 
//assign  r_wselect           = (write_activate == 2'b00) ? 1'b0 :
//assign  r_wselect           = (write_activate == 2'b00) ? 1'b0 :
//                              (write_activate == 2'b01) ? 1'b0 :
//                              (write_activate == 2'b01) ? 1'b0 :
//                              (write_activate == 2'b10) ? 1'b1 :
//                              (write_activate == 2'b10) ? 1'b1 :
//                              reset ?                     1'b0 :
//                              reset ?                     1'b0 :
//                              r_wselect;
//                              r_wselect;
//                            //I know this can be shortened down but it's more
//                            //I know this can be shortened down but it's more
//                            //readible thi way
//                            //readible thi way
 
 
assign  write_fifo_size     = FIFO_DEPTH;
assign  write_fifo_size     = FIFO_DEPTH;
 
 
assign  addr_in             = {r_wselect, write_address};
assign  addr_in             = {r_wselect, write_address};
//assign  write_enable        = (write_activate > 0) && write_strobe;
//assign  write_enable        = (write_activate > 0) && write_strobe;
assign  ppfifo_ready        = !(w_reset || r_reset);
assign  ppfifo_ready        = !(w_reset || r_reset);
assign  ready               = ppfifo_ready;
assign  ready               = ppfifo_ready;
 
 
//assign  wcc_tie_select      = (wcc_read_ready == 2'b00) ? 1'b0 :
//assign  wcc_tie_select      = (wcc_read_ready == 2'b00) ? 1'b0 :
//                              (wcc_read_ready == 2'b01) ? 1'b0 :
//                              (wcc_read_ready == 2'b01) ? 1'b0 :
//                              (wcc_read_ready == 2'b10) ? 1'b1 :
//                              (wcc_read_ready == 2'b10) ? 1'b1 :
//                              wcc_tie_select;
//                              wcc_tie_select;
                                            // If the first FIFO is ready,
                                            // If the first FIFO is ready,
                                            // then both FIFOs are ready then
                                            // then both FIFOs are ready then
                                            // keep the first FIFO
                                            // keep the first FIFO
 
 
assign  addr_out            = {r_rselect, r_address};
assign  addr_out            = {r_rselect, r_address};
 
 
 
 
//Debug
//Debug
//wire  [23:0]                debug_f0_w_count;
//wire  [23:0]                debug_f0_w_count;
//wire  [23:0]                debug_f1_w_count;
//wire  [23:0]                debug_f1_w_count;
 
 
//wire  [23:0]                debug_f0_r_size;
//wire  [23:0]                debug_f0_r_size;
//wire  [23:0]                debug_f1_r_size;
//wire  [23:0]                debug_f1_r_size;
 
 
//wire  [23:0]                debug_f0_r_count;
//wire  [23:0]                debug_f0_r_count;
//wire  [23:0]                debug_f1_r_count;
//wire  [23:0]                debug_f1_r_count;
 
 
//assign  debug_f0_w_count    = w_count[0];
//assign  debug_f0_w_count    = w_count[0];
//assign  debug_f1_w_count    = w_count[1];
//assign  debug_f1_w_count    = w_count[1];
 
 
//assign  debug_f0_r_size     = r_size[0];
//assign  debug_f0_r_size     = r_size[0];
//assign  debug_f1_r_size     = r_size[1];
//assign  debug_f1_r_size     = r_size[1];
 
 
assign  inactive            = (w_count[0] == 0) &&
assign  inactive            = (w_count[0] == 0) &&
                              (w_count[1] == 0) &&
                              (w_count[1] == 0) &&
                              (write_ready == 2'b11) &&
                              (write_ready == 2'b11) &&
                              (!write_strobe);
                              (!write_strobe);
 
 
 
 
assign  read_data           = (r_pre_strobe) ? w_read_data : r_read_data;
assign  read_data           = (r_pre_strobe) ? w_read_data : r_read_data;
 
 
 
 
//Submodules
//Submodules
blk_mem #(
blk_mem #(
  .DATA_WIDTH(DATA_WIDTH),
  .DATA_WIDTH(DATA_WIDTH),
  .ADDRESS_WIDTH(ADDRESS_WIDTH + 1)
  .ADDRESS_WIDTH(ADDRESS_WIDTH + 1)
) fifo0 (
) fifo0 (
  //Write
  //Write
  .clka     (write_clock        ),
  .clka     (write_clock        ),
  .wea      (write_enable       ), //This may just be replaced with write activate
  .wea      (write_enable       ), //This may just be replaced with write activate
  .dina     (write_data         ),
  .dina     (write_data         ),
  .addra    (addr_in            ),
  .addra    (addr_in            ),
 
 
  .clkb     (read_clock         ),
  .clkb     (read_clock         ),
  .doutb    (w_read_data        ),
  .doutb    (w_read_data        ),
  .addrb    (addr_out           )
  .addrb    (addr_out           )
);
);
 
 
//W - R FIFO 0
//W - R FIFO 0
cross_clock_enable ccwf0 (
cross_clock_enable ccwf0 (
  .rst      (reset              ),
  .rst      (reset              ),
  .in_en    (wcc_read_ready[0]  ),
  .in_en    (wcc_read_ready[0]  ),
 
 
  .out_clk  (read_clock         ),
  .out_clk  (read_clock         ),
  .out_en   (rcc_read_ready[0]  )
  .out_en   (rcc_read_ready[0]  )
);
);
//W - R FIFO 1
//W - R FIFO 1
cross_clock_enable ccwf1 (
cross_clock_enable ccwf1 (
  .rst      (reset              ),
  .rst      (reset              ),
  .in_en    (wcc_read_ready[1]  ),
  .in_en    (wcc_read_ready[1]  ),
 
 
  .out_clk  (read_clock         ),
  .out_clk  (read_clock         ),
  .out_en   (rcc_read_ready[1]  )
  .out_en   (rcc_read_ready[1]  )
 
 
);
);
 
 
//W - R Tie Select
//W - R Tie Select
cross_clock_enable ccts (
cross_clock_enable ccts (
  .rst      (reset              ),
  .rst      (reset              ),
  .in_en    (wcc_tie_select     ),
  .in_en    (wcc_tie_select     ),
 
 
  .out_clk  (read_clock         ),
  .out_clk  (read_clock         ),
  .out_en   (rcc_tie_select     )
  .out_en   (rcc_tie_select     )
);
);
 
 
//R - W FIFO 0
//R - W FIFO 0
cross_clock_enable ccrf0 (
cross_clock_enable ccrf0 (
  .rst      (reset              ),
  .rst      (reset              ),
  .in_en    (rcc_read_done[0]   ),
  .in_en    (rcc_read_done[0]   ),
 
 
  .out_clk  (read_clock         ),
  .out_clk  (read_clock         ),
  .out_en   (wcc_read_done[0]   )
  .out_en   (wcc_read_done[0]   )
);
);
//R - W FIFO 1
//R - W FIFO 1
cross_clock_enable ccrf1 (
cross_clock_enable ccrf1 (
  .rst      (reset              ),
  .rst      (reset              ),
  .in_en    (rcc_read_done[1]   ),
  .in_en    (rcc_read_done[1]   ),
 
 
  .out_clk  (read_clock         ),
  .out_clk  (read_clock         ),
  .out_en   (wcc_read_done[1]   )
  .out_en   (wcc_read_done[1]   )
);
);
 
 
//R - W Reset
//R - W Reset
cross_clock_enable cc_starved(
cross_clock_enable cc_starved(
  .rst      (reset                         ),
  .rst      (reset                         ),
  .in_en    (!read_ready && !read_activate ),
  .in_en    (!read_ready && !read_activate ),
 
 
  .out_clk  (write_clock                   ),
  .out_clk  (write_clock                   ),
  .out_en   (starved                       )
  .out_en   (starved                       )
);
);
 
 
 
 
 
 
 
 
//asynchronous logic
//asynchronous logic
always @ (*) begin
always @ (*) begin
  case (wcc_read_ready)
  case (wcc_read_ready)
    2'b00: begin
    2'b00: begin
      wcc_tie_select  = 1'b0;
      wcc_tie_select  = 1'b0;
    end
    end
    2'b01: begin
    2'b01: begin
      wcc_tie_select  = 1'b0;
      wcc_tie_select  = 1'b0;
    end
    end
    2'b10: begin
    2'b10: begin
      wcc_tie_select  = 1'b1;
      wcc_tie_select  = 1'b1;
    end
    end
    default: begin
    default: begin
      wcc_tie_select  = 1'b0;
      wcc_tie_select  = 1'b0;
    end
    end
  endcase
  endcase
end
end
always @ (*) begin
always @ (*) begin
  case (write_activate)
  case (write_activate)
    2'b00: begin
    2'b00: begin
      r_wselect   = 1'b0;
      r_wselect   = 1'b0;
    end
    end
    2'b01: begin
    2'b01: begin
      r_wselect   = 1'b0;
      r_wselect   = 1'b0;
    end
    end
    2'b10: begin
    2'b10: begin
      r_wselect   = 1'b1;
      r_wselect   = 1'b1;
    end
    end
    default: begin
    default: begin
      r_wselect   = 1'b0;
      r_wselect   = 1'b0;
    end
    end
  endcase
  endcase
end
end
 
 
always @ (*) begin
always @ (*) begin
  if (write_activate > 0 && write_strobe) begin
  if (write_activate > 0 && write_strobe) begin
    write_enable  = 1'b1;
    write_enable  = 1'b1;
  end
  end
  else begin
  else begin
    write_enable  = 1'b0;
    write_enable  = 1'b0;
  end
  end
end
end
//synchronous logic
//synchronous logic
 
 
//Reset Logic
//Reset Logic
always @ (posedge write_clock) begin
always @ (posedge write_clock) begin
  if (reset) begin
  if (reset) begin
    w_reset         <=  1;
    w_reset         <=  1;
    w_reset_timeout <=  0;
    w_reset_timeout <=  0;
  end
  end
  else begin
  else begin
    if (w_reset && (w_reset_timeout < 5'h4)) begin
    if (w_reset && (w_reset_timeout < 5'h4)) begin
      w_reset_timeout <=  w_reset_timeout + 5'h1;
      w_reset_timeout <=  w_reset_timeout + 5'h1;
    end
    end
    else begin
    else begin
      w_reset       <=  0;
      w_reset       <=  0;
    end
    end
  end
  end
end
end
 
 
always @ (posedge read_clock) begin
always @ (posedge read_clock) begin
  if (reset) begin
  if (reset) begin
    r_reset           <=  1;
    r_reset           <=  1;
    r_reset_timeout   <=  0;
    r_reset_timeout   <=  0;
  end
  end
  else begin
  else begin
    if (r_reset && (r_reset_timeout < 5'h4)) begin
    if (r_reset && (r_reset_timeout < 5'h4)) begin
      r_reset_timeout <= r_reset_timeout + 5'h1;
      r_reset_timeout <= r_reset_timeout + 5'h1;
    end
    end
    else begin
    else begin
      r_reset         <=  0;
      r_reset         <=  0;
    end
    end
  end
  end
end
end
 
 
//---------------Write Side---------------
//---------------Write Side---------------
initial begin
initial begin
  write_address     = 0;
  write_address     = 0;
 
 
  wcc_read_ready    = 2'b00;
  wcc_read_ready    = 2'b00;
  write_ready       = 2'b00;
  write_ready       = 2'b00;
  w_reset           = 1;
  w_reset           = 1;
  w_reset_timeout   = 0;
  w_reset_timeout   = 0;
  write_enable      = 0;
  write_enable      = 0;
  r_wselect         = 0;
  r_wselect         = 0;
  wcc_tie_select    = 0;
  wcc_tie_select    = 0;
end
end
 
 
always @ (posedge write_clock) begin
always @ (posedge write_clock) begin
  if (reset) begin
  if (reset) begin
    write_ready     <=  0;
    write_ready     <=  0;
  end
  end
  else if (ready) begin
  else if (ready) begin
    //Logic for the Write Enable
    //Logic for the Write Enable
    if (write_activate[0] && write_strobe) begin
    if (write_activate[0] && write_strobe) begin
      write_ready[0] <=  1'b0;
      write_ready[0] <=  1'b0;
    end
    end
    if (write_activate[1] && write_strobe) begin
    if (write_activate[1] && write_strobe) begin
      write_ready[1] <=  1'b0;
      write_ready[1] <=  1'b0;
    end
    end
 
 
    if (!write_activate[0] && (w_count[0] == 0) && wcc_read_done[0]) begin
    if (!write_activate[0] && (w_count[0] == 0) && wcc_read_done[0]) begin
      //FIFO 0 is not accessed by the read side, and user has not activated
      //FIFO 0 is not accessed by the read side, and user has not activated
      write_ready[0]  <=  1;
      write_ready[0]  <=  1;
    end
    end
    if (!write_activate[1] && (w_count[1] == 0) && wcc_read_done[1]) begin
    if (!write_activate[1] && (w_count[1] == 0) && wcc_read_done[1]) begin
      //FIFO 1 is not accessed by the read side, and user has not activated
      //FIFO 1 is not accessed by the read side, and user has not activated
      write_ready[1]  <=  1;
      write_ready[1]  <=  1;
    end
    end
 
 
    //When the user is finished reading the ready signal might go high
    //When the user is finished reading the ready signal might go high
    //I SHOULD MAKE A CONDITION WHERE THE WRITE COUND MUST BE 0
    //I SHOULD MAKE A CONDITION WHERE THE WRITE COUND MUST BE 0
  end
  end
end
end
 
 
always @ (posedge write_clock) begin
always @ (posedge write_clock) begin
  if (reset) begin  //Asynchronous Reset
  if (reset) begin  //Asynchronous Reset
    wcc_read_ready  <=  2'b00;
    wcc_read_ready  <=  2'b00;
    write_address   <=  0;
    write_address   <=  0;
    w_count[0]      <=  24'h0;
    w_count[0]      <=  24'h0;
    w_count[1]      <=  24'h0;
    w_count[1]      <=  24'h0;
  end
  end
  else begin
  else begin
    if (write_activate > 0 && write_strobe) begin
    if (write_activate > 0 && write_strobe) begin
      write_address <=  write_address + 1;
      write_address <=  write_address + 1;
      if (write_activate[0]) begin
      if (write_activate[0]) begin
        w_count[0]  <=  w_count[0] + 1;
        w_count[0]  <=  w_count[0] + 1;
      end
      end
      if (write_activate[1]) begin
      if (write_activate[1]) begin
        w_count[1]  <=  w_count[1] + 1;
        w_count[1]  <=  w_count[1] + 1;
      end
      end
    end
    end
    if (write_activate == 0) begin
    if (write_activate == 0) begin
      write_address     <=  0;
      write_address     <=  0;
      if (w_count[0] > 0) begin
      if (w_count[0] > 0) begin
        wcc_read_ready[0]  <=  1;
        wcc_read_ready[0]  <=  1;
      end
      end
      if (w_count[1] > 0) begin
      if (w_count[1] > 0) begin
        wcc_read_ready[1]  <=  1;
        wcc_read_ready[1]  <=  1;
      end
      end
    end
    end
    //I can't reset the w_count until the read side has indicated that it
    //I can't reset the w_count until the read side has indicated that it
    //is done but that may be mistriggered when the write side finishes
    //is done but that may be mistriggered when the write side finishes
    //a write. So how do
    //a write. So how do
 
 
    //Only reset the write count when the done signal has been de-asserted
    //Only reset the write count when the done signal has been de-asserted
 
 
    //Deassert w_readX_ready when we see the read has de-asserted r_readX_done
    //Deassert w_readX_ready when we see the read has de-asserted r_readX_done
    if (!wcc_read_done[0]) begin
    if (!wcc_read_done[0]) begin
      //Only reset write count when the read side has said it's busy so it
      //Only reset write count when the read side has said it's busy so it
      //must be done reading
      //must be done reading
      w_count[0]        <=  0;
      w_count[0]        <=  0;
      wcc_read_ready[0] <=  0;
      wcc_read_ready[0] <=  0;
    end
    end
    if (!wcc_read_done[1]) begin
    if (!wcc_read_done[1]) begin
      w_count[1]        <=  0;
      w_count[1]        <=  0;
      wcc_read_ready[1] <=  0;
      wcc_read_ready[1] <=  0;
    end
    end
  end
  end
end
end
 
 
 
 
//---------------Read Side---------------
//---------------Read Side---------------
initial begin
initial begin
  r_rselect       = 0;
  r_rselect       = 0;
  r_address       = 0;
  r_address       = 0;
 
 
  rcc_read_done   = 2'b00;
  rcc_read_done   = 2'b00;
 
 
  r_size[0]       = 24'h0;
  r_size[0]       = 24'h0;
  r_size[1]       = 24'h0;
  r_size[1]       = 24'h0;
 
 
  r_wait          = 2'b11;
  r_wait          = 2'b11;
  r_ready         = 2'b00;
  r_ready         = 2'b00;
  r_activate      = 2'b00;
  r_activate      = 2'b00;
  r_pre_activate  = 0;
  r_pre_activate  = 0;
 
 
  r_next_fifo     = 0;
  r_next_fifo     = 0;
  r_reset         = 1;
  r_reset         = 1;
  r_reset_timeout = 0;
  r_reset_timeout = 0;
  read_ready      = 0;
  read_ready      = 0;
  r_read_data     = 32'h0;
  r_read_data     = 32'h0;
  r_pre_read_wait = 0;
  r_pre_read_wait = 0;
end
end
 
 
always @ (posedge read_clock) begin
always @ (posedge read_clock) begin
  if (reset) begin  //Asynchronous Reset
  if (reset) begin  //Asynchronous Reset
    r_rselect                       <=  0;
    r_rselect                       <=  0;
    r_address                       <=  0;
    r_address                       <=  0;
    rcc_read_done                   <=  2'b11;
    rcc_read_done                   <=  2'b11;
    read_count                      <=  0;
    read_count                      <=  0;
    r_activate                      <=  2'b00;
    r_activate                      <=  2'b00;
    r_pre_activate                  <=  2'b00;
    r_pre_activate                  <=  2'b00;
    r_pre_read_wait                 <=  0;
    r_pre_read_wait                 <=  0;
 
 
    r_size[0]                       <=  24'h0;
    r_size[0]                       <=  24'h0;
    r_size[1]                       <=  24'h0;
    r_size[1]                       <=  24'h0;
 
 
    //are these signals redundant?? can I just use the done?
    //are these signals redundant?? can I just use the done?
    r_wait                          <=  2'b11;
    r_wait                          <=  2'b11;
 
 
    r_ready                         <=  2'b00;
    r_ready                         <=  2'b00;
 
 
    r_next_fifo                     <=  0;
    r_next_fifo                     <=  0;
    r_read_data                     <=  0;
    r_read_data                     <=  0;
 
    read_ready                      <=  0;
 
 
  end
  end
  else begin
  else begin
    r_pre_strobe                    <=  read_strobe;
    r_pre_strobe                    <=  read_strobe;
    //Handle user enable and ready
    //Handle user enable and ready
    if (!read_activate && !r_pre_activate) begin
    if (!read_activate && !r_pre_activate) begin
      //User has not activated the read side
      //User has not activated the read side
 
 
      //Prepare the read side
      //Prepare the read side
      //Reset the address
      //Reset the address
      if (r_activate == 0) begin
      if (r_activate == 0) begin
        read_count                      <=  0;
        read_count                      <=  0;
        r_address                       <=  0;
        r_address                       <=  0;
        r_pre_read_wait                 <=  0;
        r_pre_read_wait                 <=  0;
        if (r_ready > 0) begin
        if (r_ready > 0) begin
          //This goes to one instead of activate
          //This goes to one instead of activate
          //Output select
          //Output select
          //read_ready                  <=  1;
          //read_ready                  <=  1;
 
 
          if (r_ready[0] && r_ready[1]) begin
          if (r_ready[0] && r_ready[1]) begin
            //$display ("Tie");
            //$display ("Tie");
            //Tie
            //Tie
            r_rselect                   <=  r_next_fifo;
            r_rselect                   <=  r_next_fifo;
            r_pre_activate[r_next_fifo] <=  1;
            r_pre_activate[r_next_fifo] <=  1;
            r_pre_activate[~r_next_fifo]<=  0;
            r_pre_activate[~r_next_fifo]<=  0;
            r_next_fifo                 <=  ~r_next_fifo;
            r_next_fifo                 <=  ~r_next_fifo;
            read_count                  <=  r_size[r_next_fifo];
            read_count                  <=  r_size[r_next_fifo];
          end
          end
          else begin
          else begin
            //Only one side is ready
            //Only one side is ready
            if (r_ready[0]) begin
            if (r_ready[0]) begin
              //$display ("select 0");
              //$display ("select 0");
              r_rselect                 <=  0;
              r_rselect                 <=  0;
              r_pre_activate[0]         <=  1;
              r_pre_activate[0]         <=  1;
              r_pre_activate[1]         <=  0;
              r_pre_activate[1]         <=  0;
              r_next_fifo               <=  1;
              r_next_fifo               <=  1;
              read_count                <=  r_size[0];
              read_count                <=  r_size[0];
            end
            end
            else begin
            else begin
              //$display ("select 1");
              //$display ("select 1");
              r_rselect                 <=  1;
              r_rselect                 <=  1;
              r_pre_activate[0]         <=  0;
              r_pre_activate[0]         <=  0;
              r_pre_activate[1]         <=  1;
              r_pre_activate[1]         <=  1;
              r_next_fifo               <=  0;
              r_next_fifo               <=  0;
              read_count                <=  r_size[1];
              read_count                <=  r_size[1];
            end
            end
          end
          end
        end
        end
      end
      end
      //User has finished reading something
      //User has finished reading something
      else if (r_activate[r_rselect] && !r_ready[r_rselect]) begin
      else if (r_activate[r_rselect] && !r_ready[r_rselect]) begin
        r_activate[r_rselect]          <=  0;
        r_activate[r_rselect]          <=  0;
        rcc_read_done[r_rselect]       <=  1;
        rcc_read_done[r_rselect]       <=  1;
      end
      end
    end
    end
    else begin
    else begin
      if ((r_pre_activate > 0) && r_pre_read_wait) begin
      if ((r_pre_activate > 0) && r_pre_read_wait) begin
        read_ready                      <=  1;
        read_ready                      <=  1;
      end
      end
 
 
 
 
      if (r_activate) begin
      if (r_activate) begin
        read_ready                    <=  0;
        read_ready                    <=  0;
        //User is requesting an accss
        //User is requesting an accss
        //Handle read strobes
        //Handle read strobes
        //Only handle strobes when we are enabled
        //Only handle strobes when we are enabled
        r_ready[r_rselect]            <=  0;
        r_ready[r_rselect]            <=  0;
      end
      end
 
 
      //XXX: There should be a better way to handle these edge conditions
      //XXX: There should be a better way to handle these edge conditions
      if (!r_activate && r_pre_read_wait) begin
      if (!r_activate && r_pre_read_wait) begin
        r_read_data                     <=  w_read_data;
        r_read_data                     <=  w_read_data;
        r_address                       <=  r_address + 1;
        r_address                       <=  r_address + 1;
        r_activate                      <=  r_pre_activate;
        r_activate                      <=  r_pre_activate;
        r_pre_activate                  <=  0;
        r_pre_activate                  <=  0;
      end
      end
      else if (!r_pre_read_wait) begin
      else if (!r_pre_read_wait) begin
        r_pre_read_wait                 <=  1;
        r_pre_read_wait                 <=  1;
      end
      end
 
 
      if (read_strobe && (r_address < (r_size[r_rselect] + 1))) begin
      if (read_strobe && (r_address < (r_size[r_rselect] + 1))) begin
        //Increment the address
        //Increment the address
        r_read_data                     <=  w_read_data;
        r_read_data                     <=  w_read_data;
        r_address                       <=  r_address + 1;
        r_address                       <=  r_address + 1;
      end
      end
      if (r_pre_strobe && !read_strobe) begin
      if (r_pre_strobe && !read_strobe) begin
        r_read_data                     <=  w_read_data;
        r_read_data                     <=  w_read_data;
      end
      end
    end
    end
    if (!rcc_read_ready[0] && !r_ready[0] && !r_activate[0]) begin
    if (!rcc_read_ready[0] && !r_ready[0] && !r_activate[0]) begin
      r_wait[0]                       <=  1;
      r_wait[0]                       <=  1;
    end
    end
    if (!rcc_read_ready[1] && !r_ready[1] && !r_activate[1]) begin
    if (!rcc_read_ready[1] && !r_ready[1] && !r_activate[1]) begin
      r_wait[1]                       <=  1;
      r_wait[1]                       <=  1;
    end
    end
 
 
 
 
    //Check if the write side has sent over some data
    //Check if the write side has sent over some data
    if (rcc_read_ready > 0) begin
    if (rcc_read_ready > 0) begin
      if ((r_wait == 2'b11) && (rcc_read_ready == 2'b11) && (w_count[0] > 0) && (w_count[1] > 0)) begin
      if ((r_wait == 2'b11) && (rcc_read_ready == 2'b11) && (w_count[0] > 0) && (w_count[1] > 0)) begin
        //An ambiguous sitution that can arrise if the read side is much
        //An ambiguous sitution that can arrise if the read side is much
        //slower than the write side, both sides can arrise seemingly at the
        //slower than the write side, both sides can arrise seemingly at the
        //same time, so there needs to be a tie breaker
        //same time, so there needs to be a tie breaker
        //$display ("Combo breaker goes to: %h", rcc_tie_select);
        //$display ("Combo breaker goes to: %h", rcc_tie_select);
        r_next_fifo         <= rcc_tie_select;
        r_next_fifo         <= rcc_tie_select;
      end
      end
 
 
 
 
 
 
 
 
      if (r_wait[0] && rcc_read_ready[0]) begin
      if (r_wait[0] && rcc_read_ready[0]) begin
        //$display ("write has send over data t othe 0 side");
        //$display ("write has send over data t othe 0 side");
        //Normally it would not be cool to transfer data over a clock domain
        //Normally it would not be cool to transfer data over a clock domain
        //but the w_count[x] is stable before the write side sends over a write
        //but the w_count[x] is stable before the write side sends over a write
        //strobe
        //strobe
        if (w_count[0] > 0) begin
        if (w_count[0] > 0) begin
          //Only enable when count > 0
          //Only enable when count > 0
          if ((r_activate == 0) && (!rcc_read_ready[1])) begin
          if ((r_activate == 0) && (!rcc_read_ready[1])) begin
              //$display ("select 0");
              //$display ("select 0");
              r_next_fifo   <=  0;
              r_next_fifo   <=  0;
          end
          end
          r_size[0]         <=  w_count[0];
          r_size[0]         <=  w_count[0];
          r_ready[0]        <=  1;
          r_ready[0]        <=  1;
          r_wait[0]         <=  0;
          r_wait[0]         <=  0;
          rcc_read_done[0]  <=  0;
          rcc_read_done[0]  <=  0;
        end
        end
      end
      end
 
 
      if (r_wait[1] && rcc_read_ready[1]) begin
      if (r_wait[1] && rcc_read_ready[1]) begin
        //$display ("write has send over data t othe 1 side");
        //$display ("write has send over data t othe 1 side");
        //Write side has sent some data over
        //Write side has sent some data over
        if (w_count[1] > 0) begin
        if (w_count[1] > 0) begin
         if ((r_activate == 0) && (!rcc_read_ready[0])) begin
         if ((r_activate == 0) && (!rcc_read_ready[0])) begin
              //$display ("select 1");
              //$display ("select 1");
              r_next_fifo   <=  1;
              r_next_fifo   <=  1;
          end
          end
          r_size[1]         <=  w_count[1];
          r_size[1]         <=  w_count[1];
          r_ready[1]        <=  1;
          r_ready[1]        <=  1;
          r_wait[1]         <=  0;
          r_wait[1]         <=  0;
          rcc_read_done[1]  <=  0;
          rcc_read_done[1]  <=  0;
        end
        end
      end
      end
    end
    end
  end
  end
end
end
 
 
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

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