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

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.storage/] [fifos/] [gray_fifo/] [1.0/] [vhd/] [cdc_fifo_ctrl.vhd] - Rev 145

Compare with Previous | Blame | View Log

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.gray_code.all;
 
entity cdc_fifo_ctrl is
 
  generic (
    READ_AHEAD_g  : integer := 0;
    SYNC_CLOCKS_g : integer := 0;
    depth_log2_g  : integer := 0);
 
  port (
    rst_n : in std_logic;
 
    rd_clk       : in  std_logic;
    rd_en_in     : in  std_logic;
    rd_empty_out : out std_logic;
    rd_one_d_out : out std_logic;
    rd_addr_out  : out std_logic_vector (depth_log2_g-1 downto 0);
 
    wr_clk       : in  std_logic;
    wr_en_in     : in  std_logic;
    wr_full_out  : out std_logic;
    wr_one_p_out : out std_logic;
    wr_addr_out  : out std_logic_vector (depth_log2_g-1 downto 0)
    );
 
end entity cdc_fifo_ctrl;
 
architecture rtl of cdc_fifo_ctrl is
 
 
--  signal wr_counter_synchronized_r : unsigned (depth_log2_g-1 downto 0);
 
 
  -- (rd_clk) registers
  signal rd_counter_r            : unsigned (depth_log2_g-1 downto 0);
  signal rd_counter_gray_r       : std_logic_vector(depth_log2_g-1 downto 0);
  signal wr_counter_gray_sync1_r : std_logic_vector (depth_log2_g-1 downto 0);
  signal wr_counter_gray_sync2_r : std_logic_vector (depth_log2_g-1 downto 0);
  signal wr_counter_gray_sync3_r : std_logic_vector (depth_log2_g-1 downto 0);
  signal rd_empty : std_logic;
 
  -- (wr_clk) registers
  signal wr_counter_r            : unsigned (depth_log2_g-1 downto 0);
  signal wr_counter_gray_r       : std_logic_vector(depth_log2_g-1 downto 0);
  signal rd_counter_gray_sync1_r : std_logic_vector (depth_log2_g-1 downto 0);
  signal rd_counter_gray_sync2_r : std_logic_vector (depth_log2_g-1 downto 0);
  signal rd_counter_gray_sync3_r : std_logic_vector (depth_log2_g-1 downto 0);
 
  signal rd_counter_next : unsigned (depth_log2_g-1 downto 0);
  signal wr_counter_next : unsigned (depth_log2_g-1 downto 0);
 
  signal wr_counter_gray_syncd : std_logic_vector(depth_log2_g-1 downto 0);
  signal rd_counter_gray_syncd : std_logic_vector(depth_log2_g-1 downto 0);
begin  -- architecture rtl
 
  -- concurrent assignments
  wr_addr_out <= std_logic_vector(wr_counter_r);
 
  --AK TESTE CAHNGED
  -- data is available at the same clock cylce as the rd_en_in = '1'
  readahead : if READ_AHEAD_g /= 0 generate
    rd_addr_out <= std_logic_vector(rd_counter_next) when (rd_en_in = '1' and rd_empty = '0') else
                   std_logic_vector(rd_counter_r);
  end generate readahead;
 
  -- data is available at the next clock cycle
  no_readahead : if READ_AHEAD_g = 0 generate
    rd_addr_out <= std_logic_vector(rd_counter_r);
  end generate no_readahead;
 
 
  -- purpose: counter logic for write address (binary counter + gray counter)
  -- type   : sequential
  -- inputs : wr_clk, rst_n
  -- outputs: 
  wr_counter_next <= wr_counter_r + 1;
  write_counter : process (rst_n, wr_clk) is
  begin  -- process write_counter
    if (rst_n = '0') then               -- asynchronous reset (active low)
      wr_counter_r      <= (others => '0');
      wr_counter_gray_r <= (others => '0');
      wr_counter_gray_sync1_r <= (others => '0');      
    elsif rising_edge(wr_clk) then      -- rising clock edge
      -- check also if becoming full
      if (wr_en_in = '1') then
        wr_counter_r      <= wr_counter_next;        
        wr_counter_gray_r <= gray_encode(wr_counter_next);
      end if;
      wr_counter_gray_sync1_r <= wr_counter_gray_r;
    end if;
  end process write_counter;
 
  -- purpose: counter logic for read address (binary counter & gray counter)
  -- type   : sequential
  -- inputs : rd_clk, rst_n
  -- outputs: 
  rd_counter_next <= rd_counter_r + 1;
  read_counter : process (rd_clk, rst_n) is
  begin  -- process read_counter
    if (rst_n = '0') then               -- asynchronous reset (active low)
      rd_counter_r      <= (others => '0');
      rd_counter_gray_r <= (others => '0');
    elsif rising_edge(rd_clk) then      -- rising clock edge
      -- check also if becoming empty
      if (rd_en_in = '1') then  --  and (not rd_counter_gray_r = wr_counter_gray_syncd)
        rd_counter_r      <= rd_counter_next;
        rd_counter_gray_r <= gray_encode(rd_counter_next);
      end if;
    end if;
  end process read_counter;
 
 
  syncd_clocks : if SYNC_CLOCKS_g /= 0 generate
    -- use only 1 synchronization register
    wr_counter_gray_syncd <= wr_counter_gray_sync1_r;
    rd_counter_gray_syncd <= rd_counter_gray_sync1_r;
  end generate syncd_clocks;
 
  no_syncd_clocks : if SYNC_CLOCKS_g = 0 generate
    -- use 2 synchronization registers
--    wr_counter_gray_syncd <= wr_counter_gray_sync2_r;
    rd_counter_gray_syncd <= rd_counter_gray_sync2_r;
    wr_counter_gray_syncd <= wr_counter_gray_sync3_r;
--    rd_counter_gray_syncd <= rd_counter_gray_sync3_r;
 
  end generate no_syncd_clocks;
 
 
  rd_empty_out <= rd_empty;
 
  -- purpose: determines whether the fifo is empty or not
  -- combinational inputs : rd_counter_r, wr_counter_sync2_r outputs:
  -- empty
  empty_logic : process (rd_counter_gray_r, wr_counter_gray_syncd,
                         rd_counter_r) is
  begin  -- process empty_logic
    if (rd_counter_gray_r = wr_counter_gray_syncd) then
      rd_empty <= '1';
    else
      rd_empty <= '0';
    end if;
 
    if (gray_encode(rd_counter_r+1) = wr_counter_gray_syncd) then
      rd_one_d_out <= '1';
    else
      rd_one_d_out <= '0';
    end if;    
  end process empty_logic;
 
 
 
  full_logic : process (rd_counter_gray_syncd, wr_counter_next) is
  begin  -- process full_logic
    if (rd_counter_gray_syncd = gray_encode(wr_counter_next)) then
      wr_full_out <= '1';
    else
      wr_full_out <= '0';
    end if;
 
    if rd_counter_gray_syncd = gray_encode(wr_counter_next+1) then
      wr_one_p_out <= '1';
    else
      wr_one_p_out <= '0';
    end if;
 
  end process full_logic;
 
-- purpose: Synchronizes write counter value to read -side clock domain.
-- type   : sequential (avoids meta-stability)
-- inputs : rd_clk, rst_n
-- outputs: 
  rd_synchronizer : process (rd_clk, rst_n) is
  begin  -- process rd_synchronizer
    if rst_n = '0' then                 -- asynchronous reset (active low)
--      wr_counter_gray_sync1_r <= (others => '0');
      wr_counter_gray_sync2_r <= (others => '0');
      wr_counter_gray_sync3_r <= (others => '0');
    elsif rising_edge(rd_clk) then      -- rising clock edge
--        wr_counter_gray_sync1_r <= wr_counter_gray_r;      
      wr_counter_gray_sync2_r <= wr_counter_gray_sync1_r;
      wr_counter_gray_sync3_r <= wr_counter_gray_sync2_r;
    end if;
  end process rd_synchronizer;
 
-- purpose: Synchronizes read counter value to write -side clock domain.
-- type   : sequential (avoids meta-stability)
-- inputs : wr_clk, rst_n
-- outputs: 
  wr_synchronizer : process (rst_n, wr_clk) is
  begin  -- process rd_synchronizer
    if rst_n = '0' then                 -- asynchronous reset (active low)
      rd_counter_gray_sync1_r <= (others => '0');
      rd_counter_gray_sync2_r <= (others => '0');
      rd_counter_gray_sync3_r <= (others => '0');      
    elsif rising_edge(wr_clk) then      -- rising clock edge
      rd_counter_gray_sync1_r <= rd_counter_gray_r;
      rd_counter_gray_sync2_r <= rd_counter_gray_sync1_r;
      rd_counter_gray_sync3_r <= rd_counter_gray_sync2_r;
    end if;
  end process wr_synchronizer;
 
end architecture rtl;
 

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.