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/] [fifo_mux_rd.vhd] - Rev 145

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Title      : HIBI fifo mux rd
-- Project    : Nocbench, Funbase
-------------------------------------------------------------------------------
-- File       : fifo_mux_rd.vhd
-- Authors    : Lasse Lehtonen
-- Company    : Tampere University of Technology
-- Created    : 2011-10-25
-- Last update: 2011-11-28
-- Platform   : 
-- Standard   : VHDL'93
-------------------------------------------------------------------------------
-- Description: Read side logic for double fifos
--
-- Makes two fifos look like a single fifo for the reader. Fifo 0 has higher
-- priority. This block adds additional address flits in normal mode
-- (multiplexed address and data) if high and low priority transfers get mixed
-- together. In sad mode (simultaneous addr+data), this does not happen.
-- 
--
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tampere University of Technology
--
-- 
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2010-10-25  1.0      ase     Created
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- 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 work.hibiv3_pkg.all;
 
 
entity fifo_mux_rd is
 
  generic (
    data_width_g    : integer;
    comm_width_g    : integer;
    separate_addr_g : integer;
    debug_g         : integer := 0
    );
  port (
    clk   : in std_logic;
    rst_n : 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);
    av_0_in    : in  std_logic;
    one_d_0_in : in  std_logic;
    empty_0_in : in  std_logic;
    re_0_Out   : out 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);
    av_1_in    : in  std_logic;
    one_d_1_in : in  std_logic;
    empty_1_in : in  std_logic;
    re_1_Out   : out std_logic;
 
    re_in     : in  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);
    av_out    : out std_logic;
    one_d_Out : out std_logic;
    empty_Out : out std_logic
    );
 
end fifo_mux_rd;
 
 
architecture rtl of fifo_mux_rd is
 
  -----------------------------------------------------------------------------
  -- CONSTANTS
  -----------------------------------------------------------------------------
 
  -----------------------------------------------------------------------------
  -- REGISTERS
  -----------------------------------------------------------------------------
  -- Mux must repeat the latest address when the FIFO changes and there is data
  -- coming from the FIFO. This is called addr reinjection.
  --
  -- Last address+comm flits, for reinjection if switching fifos between
  -- transmissions
  signal last_addr_0_r : std_logic_vector(data_width_g-1 downto 0);
  signal last_comm_0_r : std_logic_vector(comm_width_g-1 downto 0);
  signal last_addr_1_r : std_logic_vector(data_width_g-1 downto 0);
  signal last_comm_1_r : std_logic_vector(comm_width_g-1 downto 0);
 
  -- '1' if reinjection of address flit is needed
  signal reinject_0_r : std_logic;
  signal reinject_1_r : std_logic;
 
  -- '1' if only address flit has been sent from the corresponding fifo.
  -- Then, one must wait for data from the same fifo before changing the fifo.
  signal only_addr_read_0_r : std_logic;
  signal only_addr_read_1_r : std_logic;
 
  -- '0' when using fifo_0, '1' otherwise
  signal fifo_select_r : std_logic;
 
  -- '1' when fifo select is locked (because of exclusive data access)
  -- Lock stays on until there is a specific 'release lock' command arrives
  signal excl_locked_r : std_logic;
 
  -----------------------------------------------------------------------------
  -- COMBINATORIAL SIGNALS
  -----------------------------------------------------------------------------
  signal empty_out_s : std_logic;
  signal re_0_out_s  : std_logic;
  signal re_1_out_s  : std_logic;
 
begin  -- rtl
 
  -----------------------------------------------------------------------------
  -- COMMON PART
  -----------------------------------------------------------------------------
  empty_out <= empty_out_s;
  re_0_out  <= re_0_out_s;
  re_1_out  <= re_1_out_s;
 
  -----------------------------------------------------------------------------
  -- MULTIPLEXED ADDRESS AND DATA BUSES
  -----------------------------------------------------------------------------
  normal_mode : if separate_addr_g = 0 generate
 
    --
    -- Decide from which FIFO, the data goes to the reader
    -- 
    main_p : process (clk, rst_n) is
      variable only_addr_read_0_v : std_logic;
      variable only_addr_read_1_v : std_logic;
      variable excl_locked_v      : std_logic;
    begin  -- process main_p
      if rst_n = '0' then               -- asynchronous reset (active low)
 
        fifo_select_r      <= '0';
        --last_addr_0_r      <= (others => '0');
        --last_comm_0_r      <= (others => '0');
        --last_addr_1_r      <= (others => '0');
        --last_comm_1_r      <= (others => '0');
        only_addr_read_0_r <= '0';
        only_addr_read_1_r <= '0';
        reinject_0_r       <= '0';
        reinject_1_r       <= '0';
        excl_locked_r      <= '0';
 
      elsif clk'event and clk = '1' then  -- rising clock edge
 
        -- Latch address flits when available
        if empty_0_in = '0' and av_0_in = '1' then
          last_addr_0_r <= data_0_in;
          last_comm_0_r <= comm_0_in;
        end if;
 
        if empty_1_in = '0' and av_1_in = '1' then
          last_addr_1_r <= data_1_in;
          last_comm_1_r <= comm_1_in;
        end if;
 
 
        -- Check if only address flits have been sent.
        -- One cannot change the input fifo before some data has arrived after
        -- the addr.
        only_addr_read_0_v := only_addr_read_0_r;
        only_addr_read_1_v := only_addr_read_1_r;
 
        if fifo_select_r = '0' then
 
          if reinject_0_r = '1' then
            if re_0_out_s = '1' then
              only_addr_read_0_v := '1';
            end if;
          else
            if av_0_in = '1' and re_0_out_s = '1' and empty_0_in = '0' then
              only_addr_read_0_v := '1';
            elsif av_0_in = '0' and re_0_out_s = '1' then
              only_addr_read_0_v := '0';
            end if;
          end if;
 
        else
 
          if reinject_1_r = '1' then
            if re_1_out_s = '1' then
              only_addr_read_1_v := '1';
            end if;
          else
            if av_1_in = '1' and re_1_out_s = '1' and empty_1_in = '0' then
              only_addr_read_1_v := '1';
            elsif av_1_in = '0' and re_1_out_s = '1' then
              only_addr_read_1_v := '0';
            end if;
          end if;
 
        end if;
 
        only_addr_read_0_r <= only_addr_read_0_v;
        only_addr_read_1_r <= only_addr_read_1_v;
 
        -- Select signal must be locked so that wrong priority data
        -- can't intervene when the right priority fifo is empty
        -- momentarily
        excl_locked_v := excl_locked_r;
 
        if fifo_select_r = '0' then
          if comm_0_in = EXCL_LOCK_c and re_0_out_s = '1' then
            excl_locked_v := '1';
          elsif comm_0_in = EXCL_RELEASE_c and re_0_out_s = '1' then
            excl_locked_v := '0';
          end if;
        end if;
 
        excl_locked_r <= excl_locked_v;
 
        -- Decide which fifo to use
        if excl_locked_v = '0' then
 
          if fifo_select_r = '0' then
 
            if only_addr_read_0_r = '0' and only_addr_read_0_v = '0' and
              ((av_0_in = '1' and one_d_0_in = '1')
               or (empty_0_in = '1'))             
              and empty_1_in = '0'
              and (av_1_in = '0' or one_d_1_in = '0') then
              fifo_select_r <= '1';
            end if;
 
          else
 
            if only_addr_read_1_r = '0' and only_addr_read_1_v = '0'
              and empty_0_in = '0'
              and (av_0_in = '0' or one_d_0_in = '0') then
              fifo_select_r <= '0';
            end if;
 
          end if;
 
        end if;
 
        -- Check the need for reinjection
        if fifo_select_r = '0' then
 
          if empty_1_in = '0' and av_1_in = '0' then
            reinject_1_r <= '1';
          else
            reinject_1_r <= '0';
          end if;
 
          if re_in = '1' then
            reinject_0_r <= '0';
          end if;
 
        else
 
          if empty_0_in = '0' and av_0_in = '0' then
            reinject_0_r <= '1';
          else
            reinject_0_r <= '0';
          end if;
 
          if re_in = '1' then
            reinject_1_r <= '0';
          end if;
 
        end if;
 
 
      end if;
    end process main_p;
 
 
    -- Forward combinatorially the correct data to the reader: either from one
    -- of the FIFOs, or by reinjecting the latest addr again.
    mux_p : process (fifo_select_r, data_0_in, data_1_in, comm_0_in, comm_1_in,
                     av_0_in, av_1_in, one_d_0_in, one_d_1_in, empty_0_in,
                     empty_1_in, re_in, last_addr_0_r, last_addr_1_r,
                     last_comm_0_r, last_comm_1_r, reinject_0_r,
                     reinject_1_r, empty_out_s) is
    begin  -- process mux_p
 
      if fifo_select_r = '0' then
 
        if reinject_0_r = '0' then
          data_out    <= data_0_in;
          comm_out    <= comm_0_in;
          av_out      <= av_0_in;
          one_d_out   <= one_d_0_in and not av_0_in;
          empty_out_s <= empty_0_in or (one_d_0_in and av_0_in);
          re_0_out_s  <= re_in and not (empty_0_in or (one_d_0_in and av_0_in));
          re_1_out_s  <= '0';
        else
          data_out    <= last_addr_0_r;
          comm_out    <= last_comm_0_r;
          av_out      <= '1';
          one_d_out   <= '0';
          empty_out_s <= '0';
          re_0_out_s  <= '0';
          re_1_out_s  <= '0';
        end if;
 
 
      else
 
        if reinject_1_r = '0' then
          data_out    <= data_1_in;
          comm_out    <= comm_1_in;
          av_out      <= av_1_in;
          one_d_out   <= one_d_1_in and not av_1_in;
          empty_out_s <= empty_1_in or (one_d_1_in and av_1_in);
          re_0_out_s  <= '0';
          re_1_out_s  <= re_in and not (empty_1_in or (one_d_1_in and av_1_in));
        else
          data_out    <= last_addr_1_r;
          comm_out    <= last_comm_1_r;
          av_out      <= '1';
          one_d_out   <= '0';
          empty_out_s <= '0';
          re_0_out_s  <= '0';
          re_1_out_s  <= '0';
        end if;
 
      end if;
 
      -- pragma synthesis_off
      -- pragma translate_off
 
      if debug_g > 0 and empty_out_s = '1' then
 
        data_out <= (others => 'X');
        comm_out <= (others => 'X');
 
      end if;
 
      -- pragma translate_on
      -- pragma synthesis_on
 
    end process mux_p;
 
 
  end generate normal_mode;
 
  -----------------------------------------------------------------------------
  -- SEPARATED ADDRESS AND DATA BUSES
  -- Actually, addr and data are concatenated into a wide data bus. This is
  -- much simpler case than above.
  -----------------------------------------------------------------------------
  sad_mode : if separate_addr_g = 1 generate
 
    fifo_sel_p : process (clk, rst_n) is
      variable excl_locked_v : std_logic;
    begin  -- process fifo_sel_p
      if rst_n = '0' then               -- asynchronous reset (active low)
 
        fifo_select_r <= '0';
        excl_locked_r <= '0';
 
      elsif clk'event and clk = '1' then  -- rising clock edge
 
        excl_locked_v := excl_locked_r;
 
        -- Select signal must be locked so that lower priority data
        -- can't intervene when the higher priority fifo is empty
        -- momentarily
        if fifo_select_r = '0' then
          if comm_0_in = EXCL_LOCK_c and re_0_out_s = '1' then
            excl_locked_v := '1';
          elsif comm_0_in = EXCL_RELEASE_c and re_0_out_s = '1' then
            excl_locked_v := '0';
          end if;
        end if;
 
        excl_locked_r <= excl_locked_v;
 
        if excl_locked_v = '0' then
          fifo_select_r <= empty_0_in;
        end if;
 
      end if;
    end process fifo_sel_p;
 
    -- Forward combinatorially the correct data to the reader from one
    -- of the FIFOs.
    mux_p : process (fifo_select_r, data_0_in, data_1_in, comm_0_in, comm_1_in,
                     av_0_in, av_1_in, one_d_0_in, one_d_1_in, empty_0_in,
                     empty_1_in, re_in, empty_out_s) is
    begin  -- process mux_p
 
      if fifo_select_r = '0' then
 
        data_out    <= data_0_in;
        comm_out    <= comm_0_in;
        av_out      <= av_0_in;
        one_d_out   <= one_d_0_in;
        empty_out_s <= empty_0_in;
        re_0_out_s  <= re_in and not empty_0_in;
        re_1_out_s  <= '0';
 
      else
 
        data_out    <= data_1_in;
        comm_out    <= comm_1_in;
        av_out      <= av_1_in;
        one_d_out   <= one_d_1_in;
        empty_out_s <= empty_1_in;
        re_0_out_s  <= '0';
        re_1_out_s  <= re_in and not empty_1_in;
 
      end if;
 
      -- pragma synthesis_off
      -- pragma translate_off
 
      if debug_g > 0 and empty_out_s = '1' then
 
        data_out <= (others => 'X');
        comm_out <= (others => 'X');
 
      end if;
 
      -- pragma translate_on
      -- pragma synthesis_on
 
    end process mux_p;
 
  end generate sad_mode;
 
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.