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/] [multiclk_fifo/] [1.0/] [vhd/] [multiclk_fifo_v3.vhd] - Rev 145

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Title      : Multiclock FIFO
-- Project    : 
-------------------------------------------------------------------------------
-- File       : multiclk_fifo.vhd
-- Author     : kulmala3
-- Created    : 16.12.2005
-- Last update: 02.01.2006
-- Description: Synchronous multi-clock FIFO. Note that clock frequencies MUST
-- be realted (synchronized) in order to avoid metastability.
-- Clocks that are asynchronous wrt. each other do not work.
--
-- Note! data must be ready in the data in wrt. faster clock when writing!
-- same applies for re and we
--
-- In this implementation we really utilize both clocks, whch can be a problem
-- in some systems (routing the another clock).
-------------------------------------------------------------------------------
-- Copyright (c) 2005 
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 16.12.2005  1.0      AK      Created
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
 
entity multiclk_fifo is
 
  generic (
    re_freq_g    : integer := 0;        -- integer multiple of clk_we
    we_freq_g    : integer := 0;        -- or vice versa
    depth_g      : integer := 0;
    data_width_g : integer := 0
    );
  port (
    clk_re : in std_logic;
    clk_we : in std_logic;
    rst_n  : in std_logic;
 
    data_in   : in  std_logic_vector (data_width_g-1 downto 0);
    we_in     : in  std_logic;
    full_out  : out std_logic;
    one_p_out : out std_logic;
 
    re_in     : in  std_logic;
    data_out  : out std_logic_vector (data_width_g-1 downto 0);
    empty_out : out std_logic;
    one_d_out : out std_logic
    );
end multiclk_fifo;
 
architecture rtl of multiclk_fifo is
 
  component fifo
    generic (
      data_width_g : integer;
      depth_g      : integer);
    port (
      clk       : in  std_logic;
      rst_n     : in  std_logic;
      data_in   : in  std_logic_vector (data_width_g-1 downto 0);
      we_in     : in  std_logic;
      full_out  : out std_logic;
      one_p_out : out std_logic;
      re_in     : in  std_logic;
      data_out  : out std_logic_vector (data_width_g-1 downto 0);
      empty_out : out std_logic;
      one_d_out : out std_logic);
  end component;
 
  constant re_per_we_c : integer := re_freq_g / we_freq_g;
  constant we_per_re_c : integer := we_freq_g / re_freq_g;
 
  -- no 0 to x-1, cuz otherwise range 0 to -1 is possible
  signal re_cnt_r : integer range 0 to re_per_we_c;
  signal we_cnt_r : integer range 0 to we_per_re_c;
 
  signal data_to_fifo    : std_logic_vector (data_width_g-1 downto 0);
  signal we_to_fifo      : std_logic;
  signal full_from_fifo  : std_logic;
  signal one_p_from_fifo : std_logic;
  signal re_to_fifo      : std_logic;
  signal data_from_fifo  : std_logic_vector (data_width_g-1 downto 0);
  signal empty_from_fifo : std_logic;
  signal one_d_from_fifo : std_logic;
  signal clk_fifo : std_logic;
  signal slow_r : std_logic;            -- frequncy halver for slower clock
  signal slow_was_r : std_logic;
  signal rst_cnt : std_logic;
  signal clk_slow : std_logic;
begin  -- rtl
 
  data_to_fifo <= data_in;
  full_out     <= full_from_fifo;
  one_p_out    <= one_p_from_fifo;
  data_out     <= data_from_fifo;
  empty_out    <= empty_from_fifo;
  one_d_out    <= one_d_from_fifo;
 
    regular_fifo: fifo
      generic map (
        data_width_g => data_width_g,
        depth_g      => depth_g)
      port map (
        clk       => clk_fifo,            -- this is the difference
        rst_n     => rst_n,
        data_in   => data_to_fifo,
        we_in     => we_to_fifo,
        full_out  => full_from_fifo,
        one_p_out => one_p_from_fifo,
        re_in     => re_to_fifo,
        data_out  => data_from_fifo,
        empty_out => empty_from_fifo,
        one_d_out => one_d_from_fifo
        );
 
  process (clk_slow, rst_n)
  begin  -- process
    if rst_n = '0' then                 -- asynchronous reset (active low)
      slow_r <= '0';
    elsif clk_slow'event and clk_slow = '1' then  -- rising clock edge
      slow_r <= not slow_r;
    end if;
  end process;
 
  process (clk_fifo, rst_n)
  begin  -- process
    if rst_n = '0' then                 -- asynchronous reset (active low)
      slow_was_r <= '0';
    elsif clk_fifo'event and clk_fifo = '1' then  -- rising clock edge
      slow_was_r <= slow_r;
    end if;
  end process;
 
  nullify: process (slow_r, slow_was_r)
  begin  -- process nullify
    rst_cnt <= slow_was_r xor slow_r;
  end process nullify;
 
  re_gt_we : if re_freq_g >= we_freq_g generate
    clk_fifo <= clk_re;
    clk_slow <= clk_we;
 
    re_to_fifo <= re_in;
 
    equal : if re_per_we_c = 1 generate
      we_to_fifo <= we_in;
    end generate equal;
 
    greater : if re_per_we_c > 1 generate
      -- re clk is faster than we
 
      gen_we : process (re_cnt_r, we_in, rst_cnt)
      begin  -- process gen_we
        if we_in = '1' then
          if re_cnt_r = re_per_we_c-2 and rst_cnt = '0' then
            we_to_fifo <= '1';
          else
            we_to_fifo <= '0';
          end if;
        else
          we_to_fifo <= '0';
        end if;
      end process gen_we;
 
      process (clk_re, rst_n)
      begin  -- process
        if rst_n = '0' then             -- asynchronous reset (active low)
          re_cnt_r <= 0;
 
        elsif clk_re'event and clk_re = '1' then  -- rising clock edge
          if rst_cnt = '1' then
            re_cnt_r <= 0;
          else
            re_cnt_r <= re_cnt_r+1;
          end if;
 
        end if;
      end process;
 
 
    end generate greater;
 
 
  end generate re_gt_we;
 
  we_gt_re : if re_freq_g < we_freq_g generate
 
    clk_fifo <= clk_we;
    clk_slow <= clk_re;
    we_to_fifo <= we_in;
 
    -- we clk is faster than re
      gen_we : process (we_cnt_r, re_in, rst_cnt)
      begin  -- process gen_we
        if re_in = '1' then
          if we_cnt_r = we_per_re_c-2 and rst_cnt = '0' then
            re_to_fifo <= '1';
          else
            re_to_fifo <= '0';
          end if;
        else
          re_to_fifo <= '0';
        end if;
      end process gen_we;
 
      process (clk_we, rst_n)
      begin  -- process
        if rst_n = '0' then             -- asynchronous reset (active low)
          we_cnt_r <= 0;
 
        elsif clk_we'event and clk_we = '1' then  -- rising clock edge
          if rst_cnt = '1' then
            we_cnt_r <= 0;
          else
            we_cnt_r <= we_cnt_r+1;
          end if;
 
        end if;
      end process;
 
 
  end generate we_gt_re;
 
end 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.