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.communication/] [hibi/] [3.0/] [vhd/] [double_fifo_mux_rd.vhd] - Rev 145

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- File        : double_fifo_mux_rd.vhd
-- Description : Includes two fifos and a special multiplexer
--               so that the reader sees only one fifo. Multiplexer
--               selects addr+data first from fifo 0 (i.e. it has a higher priority)
-- Author      : Erno Salminen
-- Project      
-- Design      : 
-- Date        : 07.02.2003
-- Modified    : 
--
--15.12.04      ES names changed
--18.12.2006 AK modified to support different kinds of IF fifos
-------------------------------------------------------------------------------
-- Funbase IP library Copyright (C) 2011 TUT Department of Computer Systems
--
-- This file is part of HIBI
--
-- This source file may be used and distributed without
-- restriction provided that this copyright statement is not
-- removed from the file and that any derivative work contains
-- the original copyright notice and the associated disclaimer.
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE.  See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.opencores.org/lgpl.shtml
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
 
 
 
entity double_fifo_mux_rd is
 
  generic (
    -- 0 synch multiclk, 1 basic GALS,
    -- 2 Gray FIFO (depth=2^n!), 3 mixed clock pausible
    fifo_sel_g : integer;
 
    -- needed for fifos 0 (accurate) and 3 (to know which is faster, wr or rd)
    re_freq_g       : integer;
    we_freq_g       : integer;
    depth_0_g       : integer;          -- #words, log2 for fifo 2!
    depth_1_g       : integer;          -- -"-
    data_width_g    : integer;          -- in bits
    debug_width_g   : integer;          -- for debugging
    comm_width_g    : integer;
    separate_addr_g : integer
    );
  port (
    clk_re     : in std_logic;
    clk_we     : in std_logic;
    -- pulsed clocks. used in pausible clock scheme
    -- used in 1 for faster synchronization, when they are integer multiples
    -- of re and we (can also be 1 if the same as clk_re and clk_we
    clk_re_pls : in std_logic;
    clk_we_pls : in std_logic;
    rst_n      : in std_logic;
 
    av_0_in     : in  std_logic;
    data_0_in   : in  std_logic_vector (data_width_g-1 downto 0);
    comm_0_in   : in  std_logic_vector (comm_width_g-1 downto 0);
    we_0_in     : in  std_logic;
    full_0_out  : out std_logic;
    one_p_0_out : out std_logic;
 
    av_1_in     : in  std_logic;
    data_1_in   : in  std_logic_vector (data_width_g-1 downto 0);
    comm_1_in   : in  std_logic_vector (comm_width_g-1 downto 0);
    we_1_in     : in  std_logic;
    full_1_out  : out std_logic;
    one_p_1_out : out std_logic;
 
    re_in     : in  std_logic;
    av_out    : out std_logic;
    data_out  : out std_logic_vector (data_width_g-1 downto 0);
    comm_out  : out std_logic_vector (comm_width_g-1 downto 0);
    empty_out : out std_logic;
    one_d_out : out std_logic;
    debug_out : out std_logic_vector(debug_width_g downto 0)
    );
end double_fifo_mux_rd;
 
 
 
architecture structural of double_fifo_mux_rd is
 
  -- Mixed-clk fifo must know which faster, reader or writer
  constant re_faster_c : integer := re_freq_g/we_freq_g;
 
 
  --
  --
  --
  -- one_p currently statically at '0' ...
  component mixed_clk_fifo
    generic (
      re_faster_g  : integer := 1;      -- integer multiple of clk_we
--      we_freq_g    : integer := 0;      -- or vice versa
      data_width_g : integer := 0;
      depth_g      : integer := 0
      );
    port (
      clk_re    : in std_logic;
      clk_we    : in std_logic;
      clk_ps_re : in std_logic;         -- phase shifted pulse      
      clk_ps_we : in std_logic;         -- phase shifted pulse         
      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);
      one_d_out : out std_logic;
      empty_out : out std_logic
      );
  end component;  --multiclk_fifo;
 
  --
  --
  --
  component multiclk_fifo
    generic (
      re_freq_g    : integer;
      we_freq_g    : integer;
      depth_g      : integer;
      data_width_g : integer);
    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 component;
  -- basic gals, for fifo 1
  component aif_we_top
    generic (
      data_width_g : integer);
    port (
      tx_clk      : in  std_logic;
      tx_rst_n    : in  std_logic;
      tx_we_in    : in  std_logic;
      tx_data_in  : in  std_logic_vector(data_width_g-1 downto 0);
      tx_full_out : out std_logic;
      rx_clk      : in  std_logic;
      rx_rst_n    : in  std_logic;
      rx_full_in  : in  std_logic;
      rx_we_out   : out std_logic;
      rx_data_out : out std_logic_vector(data_width_g-1 downto 0));
  end component;
 
  --
  --
  --
  component cdc_fifo
    generic (
      READ_AHEAD_g  : integer;
      SYNC_CLOCKS_g : integer;
      depth_log2_g  : integer;
      dataw_g       : integer);
    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_data_out  : out std_logic_vector(dataw_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_data_in   : in  std_logic_vector(dataw_g-1 downto 0));
  end component;
 
  component fifo_mux_rd
    generic (
      data_width_g    : integer;
      comm_width_g    : integer;
      separate_addr_g : integer
      );
    port (
      clk   : in std_logic;
      rst_n : in std_logic;
 
      av_0_in    : in  std_logic;
      data_0_in  : in  std_logic_vector (data_width_g-1 downto 0);
      comm_0_in  : in  std_logic_vector (comm_width_g-1 downto 0);
      empty_0_in : in  std_logic;
      one_d_0_in : in  std_logic;
      re_0_out   : out std_logic;
 
      av_1_in    : in  std_logic;
      data_1_in  : in  std_logic_vector (data_width_g-1 downto 0);
      comm_1_in  : in  std_logic_vector (comm_width_g-1 downto 0);
      empty_1_in : in  std_logic;
      one_d_1_in : in  std_logic;
      re_1_out   : out std_logic;
 
      re_in     : in  std_logic;
      av_out    : out std_logic;
      data_out  : out std_logic_vector (data_width_g-1 downto 0);
      comm_out  : out std_logic_vector (comm_width_g-1 downto 0);
      empty_out : out std_logic;
      one_d_out : out std_logic
      );
  end component;  --fifo_mux_rd;
 
 
 
 
  -- from inputs to fifos (addr_valid + comm + data concatenated together)
  signal a_c_d_input_f0 : std_logic_vector (1 + comm_width_g + data_width_g-1 downto 0);
  signal a_c_d_input_f1 : std_logic_vector (1 + comm_width_g + data_width_g-1 downto 0);
 
  -- from fifo 0 to mux
  signal a_c_d_f0_mux : std_logic_vector (1 + comm_width_g + data_width_g-1 downto 0);
  signal av_f0_mux    : std_logic;
  signal data_f0_mux  : std_logic_vector (data_width_g-1 downto 0);
  signal comm_f0_mux  : std_logic_vector (comm_width_g-1 downto 0);
  signal empty_f0_mux : std_logic;
  signal one_d_f0_mux : std_logic;
 
  -- from fifo 1 to mux
  signal a_c_d_f1_mux : std_logic_vector (1 + comm_width_g + data_width_g-1 downto 0);
  signal av_f1_mux    : std_logic;
  signal data_f1_mux  : std_logic_vector (data_width_g-1 downto 0);
  signal comm_f1_mux  : std_logic_vector (comm_width_g-1 downto 0);
  signal empty_f1_mux : std_logic;
  signal one_d_f1_mux : std_logic;
 
 
  -- Control signals from mux to fifos
  signal re_mux_f0 : std_logic;
  signal re_mux_f1 : std_logic;
 
 
  signal Tie_High : std_logic;
  signal Tie_Low  : std_logic;
 
 
  -- For asynch. interface (aif) used with fifo_sel=1
  signal tx_we_to_we_aif     : std_logic;
  signal tx_data_to_we_aif   : std_logic_vector(data_width_g+comm_width_g+1-1 downto 0);
  signal tx_full_from_we_aif : std_logic;
 
  signal rx_full_to_we_aif   : std_logic;
  signal rx_we_from_we_aif   : std_logic;
  signal rx_data_from_we_aif : std_logic_vector(data_width_g+comm_width_g+1-1 downto 0);
 
  signal tx_msg_we_to_we_aif     : std_logic;
  signal tx_msg_data_to_we_aif   : std_logic_vector(data_width_g+comm_width_g+1-1 downto 0);
  signal tx_msg_full_from_we_aif : std_logic;
 
  signal rx_msg_full_to_we_aif   : std_logic;
  signal rx_msg_we_from_we_aif   : std_logic;
  signal rx_msg_data_from_we_aif : std_logic_vector(data_width_g+comm_width_g+1-1 downto 0);
 
 
 
  -- Helper function (needed at least for Gray fifo)
  function log2 (
    constant value : integer)
    return integer is
    variable temp    : integer := 1;
    variable counter : integer := 0;
  begin  -- log2
    while temp < value loop
      temp    := temp*2;
      counter := counter+1;
    end loop;
 
    return counter;
  end log2;
 
 
begin  -- structural
  -- Check generics
  assert (depth_0_g + depth_1_g > 0) report "Both fifo depths zero!" severity warning;
 
  -- Concurrent assignments
  Tie_High       <= '1';
  Tie_Low        <= '0';
 
 
  -- Combine fifo inputs
  a_c_d_input_f0 <= av_0_in & comm_0_in & data_0_in;
  a_c_d_input_f1 <= av_1_in & comm_1_in & data_1_in;
 
  -- Split fifo output
  av_f0_mux   <= a_c_d_f0_mux (1+comm_width_g + data_width_g-1);
  comm_f0_mux <= a_c_d_f0_mux (comm_width_g + data_width_g-1 downto data_width_g);
  data_f0_mux <= a_c_d_f0_mux (data_width_g-1 downto 0);
  av_f1_mux   <= a_c_d_f1_mux (1+comm_width_g + data_width_g-1);
  comm_f1_mux <= a_c_d_f1_mux (comm_width_g + data_width_g-1 downto data_width_g);
  data_f1_mux <= a_c_d_f1_mux (data_width_g-1 downto 0);
 
  --
  -- Lots of if-generates depending on which fifo type is selected
  -- and if both fifos are really needed
  -- 
 
 
  multi : if fifo_sel_g = 0 generate
    -- regular / multiclock synchronous
 
    Map_Fifo_0 : if depth_0_g > 0 generate
      multiclk_fifo_0 : multiclk_fifo
        generic map(
          re_freq_g    => re_freq_g,
          we_freq_g    => we_freq_g,
          data_width_g => 1 + comm_width_g + data_width_g,
          depth_g      => depth_0_g
          )
        port map(
          clk_re => clk_re,
          clk_we => clk_we,
          rst_n  => rst_n,
 
          data_in   => a_c_d_input_f0,
          we_in     => we_0_in,
          full_out  => full_0_out,
          one_p_out => one_p_0_out,
 
          re_in     => re_mux_f0,
          data_out  => a_c_d_f0_mux,
          one_d_out => one_d_f0_mux,
          empty_out => empty_f0_mux
          );
    end generate Map_Fifo_0;
 
 
    Map_Fifo_1 : if depth_1_g > 0 generate
      multiclk_fifo_1 : multiclk_fifo
        generic map(
          re_freq_g    => re_freq_g,
          we_freq_g    => we_freq_g,
          data_width_g => 1 + comm_width_g + data_width_g,
          depth_g      => depth_1_g
          )
        port map(
          clk_re => clk_re,
          clk_we => clk_we,
          rst_n  => rst_n,
 
          data_in   => a_c_d_input_f1,
          we_in     => we_1_in,
          full_out  => full_1_out,
          one_p_out => one_p_1_out,
 
          re_in     => re_mux_f1,
          data_out  => a_c_d_f1_mux,
          one_d_out => one_d_f1_mux,
          empty_out => empty_f1_mux
          );
    end generate Map_Fifo_1;
 
  end generate multi;
 
 
 
 
  gals : if fifo_sel_g = 1 generate
 
    -- GALS basic + multiclk
 
    -- signal assigments needed for asynchronous modes
 
    -- agent writes.
 
    Map_Fifo_0 : if depth_0_g > 0 generate
 
      aif_we_top_0 : aif_we_top
        generic map (
          data_width_g => data_width_g+comm_width_g+1)
        port map (
          tx_clk      => clk_we,
          tx_rst_n    => rst_n,
          tx_we_in    => we_0_in,
          tx_data_in  => a_c_d_input_f0,
          tx_full_out => full_0_out,
 
          rx_clk      => clk_re_pls,
          rx_rst_n    => rst_n,
          rx_full_in  => rx_full_to_we_aif,
          rx_we_out   => rx_we_from_we_aif,
          rx_data_out => rx_data_from_we_aif
          );
 
      multiclk_fifo_0 : multiclk_fifo
        generic map(
          re_freq_g    => re_freq_g,    -- HIBI reading side
          we_freq_g    => we_freq_g,    -- Writing agent OR HIBI synch clk
          data_width_g => 1 + comm_width_g + data_width_g,
          depth_g      => depth_0_g
          )
        port map(
          clk_re => clk_re,
          clk_we => clk_re_pls,         -- HIBI synch clk
          rst_n  => rst_n,
 
          data_in   => rx_data_from_we_aif,
          we_in     => rx_we_from_we_aif,
          full_out  => rx_full_to_we_aif,
          one_p_out => one_p_0_out,     -- ???
 
          re_in     => re_mux_f0,
          data_out  => a_c_d_f0_mux,
          one_d_out => one_d_f0_mux,
          empty_out => empty_f0_mux
          );
    end generate Map_Fifo_0;
 
    Map_Fifo_1 : if depth_1_g > 0 generate
 
      -- agent msg writes.
      aif_we_top_1 : aif_we_top
        generic map (
          data_width_g => data_width_g+comm_width_g+1)
        port map (
          tx_clk      => clk_we,
          tx_rst_n    => rst_n,
          tx_we_in    => we_1_in,
          tx_data_in  => a_c_d_input_f1,
          tx_full_out => full_1_out,
 
          rx_clk      => clk_re_pls,
          rx_rst_n    => rst_n,
          rx_full_in  => rx_msg_full_to_we_aif,
          rx_we_out   => rx_msg_we_from_we_aif,
          rx_data_out => rx_msg_data_from_we_aif
          );
 
      multiclk_fifo_1 : multiclk_fifo
        generic map(
          re_freq_g    => re_freq_g,
          we_freq_g    => we_freq_g,
          data_width_g => 1 + comm_width_g + data_width_g,
          depth_g      => depth_1_g
          )
        port map(
          clk_re => clk_re,
          clk_we => clk_re_pls,
          rst_n  => rst_n,
 
          data_in   => rx_msg_data_from_we_aif,
          we_in     => rx_msg_we_from_we_aif,
          full_out  => rx_msg_full_to_we_aif,
          one_p_out => one_p_1_out,
 
          re_in     => re_mux_f1,
          data_out  => a_c_d_f1_mux,
          one_d_out => one_d_f1_mux,
          empty_out => empty_f1_mux
          );
    end generate Map_Fifo_1;
 
  end generate gals;
 
  gray : if fifo_sel_g = 2 generate
    -- Gray FIFO
 
    Map_Fifo_0 : if depth_0_g > 0 generate
      cdc_fifo_0 : cdc_fifo
        generic map (
          READ_AHEAD_g  => 1,           -- this is the hibi style, look-ahead
          SYNC_CLOCKS_g => 0,           -- we use two flops
          depth_log2_g  => log2(depth_0_g),
          dataw_g       => 1 + comm_width_g + data_width_g
          )
        port map (
          rst_n        => rst_n,
          rd_clk       => clk_re,
          rd_en_in     => re_mux_f0,
          rd_empty_out => empty_f0_mux,
          rd_one_d_out => one_d_f0_mux,
          rd_data_out  => a_c_d_f0_mux,
 
          wr_clk       => clk_we,
          wr_en_in     => we_0_in,
          wr_full_out  => full_0_out,
          wr_one_p_out => one_p_0_out,
          wr_data_in   => a_c_d_input_f0
          );
 
--      one_p_0_out <= '0';
 
    end generate Map_Fifo_0;
 
 
 
    Map_Fifo_1 : if depth_1_g > 0 generate
      cdc_fifo_1 : cdc_fifo
        generic map (
          READ_AHEAD_g  => 1,           -- this is the hibi style, look-ahead
          SYNC_CLOCKS_g => 0,           -- we use two flops
          depth_log2_g  => log2(depth_1_g),
          dataw_g       => 1 + comm_width_g + data_width_g
          )
        port map (
          rst_n        => rst_n,
          rd_clk       => clk_re,
          rd_en_in     => re_mux_f1,
          rd_empty_out => empty_f1_mux,
          rd_one_d_out => one_d_f1_mux,
          rd_data_out  => a_c_d_f1_mux,
 
          wr_clk       => clk_we,
          wr_en_in     => we_1_in,
          wr_full_out  => full_1_out,
          wr_one_p_out => one_p_1_out,
          wr_data_in   => a_c_d_input_f1
          );
 
--      one_p_1_out <= '0';
 
    end generate Map_Fifo_1;
 
  end generate gray;
 
 
  mixed : if fifo_sel_g = 3 generate
 
    Map_Fifo_0 : if depth_0_g > 0 generate
      Mixed_clk_Fifo_0 : mixed_clk_fifo
        generic map(
          re_faster_g  => re_faster_c,
          data_width_g => 1 + comm_width_g + data_width_g,
          depth_g      => depth_0_g
          )
        port map(
          clk_re    => clk_re,
          clk_we    => clk_we,
          clk_ps_we => clk_we_pls,
          clk_ps_re => clk_re_pls,
          rst_n     => rst_n,
 
          data_in   => a_c_d_input_f0,
          we_in     => we_0_in,
          full_out  => full_0_out,
          one_p_out => one_p_0_out,
 
          re_in     => re_mux_f0,
          data_out  => a_c_d_f0_mux,
          one_d_out => one_d_f0_mux,
          empty_out => empty_f0_mux
          );
    end generate Map_Fifo_0;
 
 
    Map_Fifo_1 : if depth_1_g > 0 generate
      Mixed_clk_Fifo_1 : mixed_clk_fifo
        generic map(
          re_faster_g  => re_faster_c,
          data_width_g => 1 + comm_width_g + data_width_g,
          depth_g      => depth_1_g
          )
        port map(
          clk_re    => clk_re,
          clk_we    => clk_we,
          clk_ps_we => clk_we_pls,
          clk_ps_re => clk_re_pls,
          rst_n     => rst_n,
 
          data_in   => a_c_d_input_f1,
          we_in     => we_1_in,
          full_out  => full_1_out,
          one_p_out => one_p_1_out,
 
          re_in     => re_mux_f1,
          data_out  => a_c_d_f1_mux,
          one_d_out => one_d_f1_mux,
          empty_out => empty_f1_mux
          );
    end generate Map_Fifo_1;
 
  end generate mixed;
 
  --
  -- Deactivate signals "coming from fifo" that was not
  -- instantiated (depth=0)
  --
 
  Not_Map_Fifo_0 : if depth_0_g = 0 generate
    -- Fifo #0 does not exist!
    a_c_d_f0_mux <= (others => '0');
    empty_f0_mux <= Tie_High;
    one_d_f0_mux <= Tie_Low;
    full_0_out   <= Tie_High;
    one_p_0_out  <= Tie_Low;
 
    -- Connect the other fifo (#1)straight to the outputs ( =>  FSM)
    av_out    <= av_f1_mux;
    data_out  <= data_f1_mux;
    comm_out  <= comm_f1_mux;
    empty_out <= empty_f1_mux;
    one_d_out <= one_d_f1_mux;
 
    re_mux_f1 <= re_in;                 --15.05
 
  end generate Not_Map_Fifo_0;
 
 
  Not_Map_Fifo_1 : if depth_1_g = 0 generate
    -- Fifo #1 does not exist!
 
    -- Signals fifo#1=> IP
    --     full_1_out  <= Tie_High;
    --     one_p_1_out <= Tie_Low;
 
    -- Signals fifo#1=> FSM
    a_c_d_f1_mux <= (others => '0');
    empty_f1_mux <= Tie_High;
    one_d_f1_mux <= Tie_Low;
 
    -- Connect the other fifo (#0)straight to the outputs ( =>  FSM)
    av_out    <= av_f0_mux;
    data_out  <= data_f0_mux;
    comm_out  <= comm_f0_mux;
    empty_out <= empty_f0_mux;
    one_d_out <= one_d_f0_mux;
 
    re_mux_f0 <= re_in;                 --15.05
 
  end generate Not_Map_Fifo_1;
 
 
  --
  -- Include a special multiplexer if both fifos are present
  --
  Map_mux : if depth_0_g > 0 and depth_1_g > 0 generate
    -- Multiplexer is needed only if two fifos are used
    MUX_01 : fifo_mux_rd
      generic map(
        data_width_g    => data_width_g,
        comm_width_g    => comm_width_g,
        separate_addr_g => separate_addr_g
        )
      port map(
        clk   => clk_re,
        rst_n => rst_n,
 
        av_0_in    => av_f0_mux,
        data_0_in  => data_f0_mux,
        comm_0_in  => comm_f0_mux,
        empty_0_in => empty_f0_mux,
        one_d_0_in => one_d_f0_mux,
        re_0_out   => re_mux_f0,
 
        av_1_in    => av_f1_mux,
        data_1_in  => data_f1_mux,
        comm_1_in  => comm_f1_mux,
        empty_1_in => empty_f1_mux,
        one_d_1_in => one_d_f1_mux,
        re_1_out   => re_mux_f1,
 
        re_in     => re_in,
        av_out    => av_out,
        data_out  => data_out,
        comm_out  => comm_out,
        empty_out => empty_out,
        one_d_out => one_d_out
        );
  end generate Map_mux;
 
 
 
 
 
 
 
 
 
 
end structural;
 
 
 
 

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.