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

Subversion Repositories g729a_codec

[/] [g729a_codec/] [trunk/] [VHDL/] [G729A_asip_regfile_16x16_2w.vhd] - Rev 3

Compare with Previous | Blame | View Log

-----------------------------------------------------------------
--                                                             --
-----------------------------------------------------------------
--                                                             --
-- Copyright (C) 2013 Stefano Tonello                          --
--                                                             --
-- 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         --
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    --
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   --
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        --
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  --
-- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  --
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  --
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         --
-- POSSIBILITY OF SUCH DAMAGE.                                 --
--                                                             --
-----------------------------------------------------------------
 
---------------------------------------------------------------
-- G.729a ASIP 16x16 Register File
---------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
library work;
use work.G729A_ASIP_PKG.all;
 
entity G729A_ASIP_REGFILE_16X16_2W is
  port(
    CLK_i : in std_logic;
    RA0_i : in RID_T;
    RA1_i : in RID_T;
    RA2_i : in RID_T;
    RA3_i : in RID_T;
    WA0_i : in RID_T;
    WA1_i : in RID_T;
    LR0_i : in std_logic;
    LR1_i : in std_logic;
    LR2_i : in std_logic;
    LR3_i : in std_logic;
    LW0_i : in std_logic;
    LW1_i : in std_logic;
    WE0_i : in std_logic;
    WE1_i : in std_logic;
    D0_i : in std_logic_vector(LDLEN-1 downto 0);
    D1_i : in std_logic_vector(LDLEN-1 downto 0);
 
    Q0_o : out std_logic_vector(LDLEN-1 downto 0);
    Q1_o : out std_logic_vector(LDLEN-1 downto 0);
    Q2_o : out std_logic_vector(LDLEN-1 downto 0);
    Q3_o : out std_logic_vector(LDLEN-1 downto 0)
  );
end G729A_ASIP_REGFILE_16X16_2W;
 
architecture ARC of G729A_ASIP_REGFILE_16X16_2W is
 
  constant REGNUM : natural := 16;
 
  subtype WORD_T is std_logic_vector(SDLEN-1 downto 0);
  type MEM_T is array (REGNUM/2-1 downto 0) of WORD_T;
  type RID_VEC_T is array (natural range <>) of RID_T;
  type WORD_VEC_T is array (natural range <>) of WORD_T;
 
  signal REG_EVEN,REG_ODD : MEM_T;
  signal WE0_EVEN,WE0_ODD : std_logic;
  signal WE1_EVEN,WE1_ODD : std_logic;
  signal IWA0,IWA1 : natural range 0 to REGNUM/2-1;
  signal WA0_LSB,WA1_LSB : std_logic;
  signal IRA0,IRA1,IRA2,IRA3 : natural range 0 to REGNUM/2-1;
  signal RA0_LSB,RA1_LSB,RA2_LSB,RA3_LSB : std_logic;
  signal D0_LO,D0_HI : std_logic_vector(SDLEN-1 downto 0);
  signal WE_EVEN,WE_ODD : std_logic_vector(REGNUM/2-1 downto 0); 
  signal D_EVEN,D_ODD : WORD_VEC_T(REGNUM/2-1 downto 0); 
  signal D0_EVEN,D0_ODD : std_logic_vector(SDLEN-1 downto 0);
  signal D1_LO,D1_HI : std_logic_vector(SDLEN-1 downto 0);
  signal D1_EVEN,D1_ODD : std_logic_vector(SDLEN-1 downto 0);
  signal Q0_EVEN,Q1_EVEN : std_logic_vector(SDLEN-1 downto 0);
  signal Q0_ODD,Q1_ODD : std_logic_vector(SDLEN-1 downto 0);
  signal Q2_EVEN,Q3_EVEN : std_logic_vector(SDLEN-1 downto 0);
  signal Q2_ODD,Q3_ODD : std_logic_vector(SDLEN-1 downto 0);
 
  function GET_LSB(N : natural range 0 to 16-1) return std_logic is
    variable U : unsigned(4-1 downto 0);
  begin
    U := to_unsigned(N,4); 
    return(U(0));
  end function;
 
begin
 
  ---------------------------------------------
 
  D0_LO <= D0_i(SDLEN-1 downto 0);
  D0_HI <= D0_i(SDLEN*2-1 downto SDLEN);
 
  D1_LO <= D1_i(SDLEN-1 downto 0);
  D1_HI <= D1_i(SDLEN*2-1 downto SDLEN);
 
  ---------------------------------------------
 
  IWA0 <= WA0_i/2;
  IWA1 <= WA1_i/2;
 
  WA0_LSB <= GET_LSB(WA0_i);
  WA1_LSB <= GET_LSB(WA1_i);
 
  ---------------------------------------------
 
  G0 : for k in 0 to REGNUM/2-1 generate
 
    WE_EVEN(k) <= '1' when (
      (WE0_i = '1' and (IWA0 = k) and (WA0_LSB = '0') and (LW0_i = '0')) or
      (WE1_i = '1' and (IWA1 = k) and (WA1_LSB = '0') and (LW1_i = '0')) or
      (WE0_i = '1' and (IWA0 = k) and (LW0_i = '1')) or
      (WE1_i = '1' and (IWA1 = k) and (LW1_i = '1'))
    ) else '0';
 
    WE_ODD(k) <= '1' when (
      (WE0_i = '1' and (IWA0 = k) and (WA0_LSB = '1') and (LW0_i = '0')) or
      (WE1_i = '1' and (IWA1 = k) and (WA1_LSB = '1') and (LW1_i = '0')) or
      (WE0_i = '1' and (IWA0 = k) and (LW0_i = '1')) or
      (WE1_i = '1' and (IWA1 = k) and (LW1_i = '1'))
    ) else '0';
 
    process(WE0_i,WE1_i,IWA0,IWA1,WA0_LSB,WA1_LSB,LW0_i,LW1_i,
      D0_LO,D0_HI,D1_LO,D1_HI)
      variable S : natural range 0 to 4-1;
    begin
 
      -- Write from port #1 must get higher priority because
      -- instruction #1 is newer than instruction #0.
 
      if(
        (WE1_i = '1') and (IWA1 = k) and
        ((WA1_LSB = '0') or (LW1_i = '1'))
      ) then
        -- write from port #1
        D_EVEN(k) <= D1_LO;
      else
        -- write from port #0
        D_EVEN(k) <= D0_LO;
      end if;
 
      if(
       (WE1_i = '1') and (IWA1 = k) and
       (WA1_LSB = '1') and (LW1_i = '0')
      ) then
        -- word write from port #1
        S := 0;
      elsif(
       (WE1_i = '1') and (IWA1 = k) and
       (LW1_i = '1')
      ) then
        -- long-word write from port #1
        S := 1;
      elsif(
       (WE0_i = '1') and (IWA0 = k) and
       (WA0_LSB = '1') and (LW0_i = '0')
      ) then
        -- word write from port #0
        S := 2;
      else
        -- long-word write from port #0
        S := 3;
      end if;
 
      case S is
        when 0 => D_ODD(k) <= D1_LO;
        when 1 => D_ODD(k) <= D1_HI;
        when 2 => D_ODD(k) <= D0_LO;
        when 3 => D_ODD(k) <= D0_HI;
      end case;
 
    end process;
 
    process(CLK_i)
    begin
      if(CLK_i = '1' and CLK_i'event) then
        if(WE_EVEN(k) = '1') then
          REG_EVEN(k) <= D_EVEN(k);
        end if;
        if(WE_ODD(k) = '1') then
          REG_ODD(k) <= D_ODD(k);
        end if;
      end if;
    end process;
 
  end generate;
 
  ---------------------------------------------
 
  IRA0 <= RA0_i/2;
  IRA1 <= RA1_i/2;
  IRA2 <= RA2_i/2;
  IRA3 <= RA3_i/2;
 
  RA0_LSB <= GET_LSB(RA0_i);
  RA1_LSB <= GET_LSB(RA1_i);
  RA2_LSB <= GET_LSB(RA2_i);
  RA3_LSB <= GET_LSB(RA3_i);
 
  Q0_EVEN <= REG_EVEN(IRA0);
  Q1_EVEN <= REG_EVEN(IRA1);
  Q2_EVEN <= REG_EVEN(IRA2);
  Q3_EVEN <= REG_EVEN(IRA3);
 
  Q0_ODD <= REG_ODD(IRA0);
  Q1_ODD <= REG_ODD(IRA1);
  Q2_ODD <= REG_ODD(IRA2);
  Q3_ODD <= REG_ODD(IRA3);
 
  process(RA0_LSB,LR0_i,Q0_EVEN,Q0_ODD)
  begin
    if(LR0_i = '0' and RA0_LSB = '1') then
      Q0_o(SDLEN-1 downto 0) <= Q0_ODD;
    else
      Q0_o(SDLEN-1 downto 0) <= Q0_EVEN;
    end if;
    if(LR0_i = '0') then
      Q0_o(SDLEN*2-1 downto SDLEN) <= (others => '0');
    else
      Q0_o(SDLEN*2-1 downto SDLEN) <= Q0_ODD;
    end if;
  end process;
 
  process(RA1_LSB,LR1_i,Q1_EVEN,Q1_ODD)
  begin
    if(LR1_i = '0' and RA1_LSB = '1') then
      Q1_o(SDLEN-1 downto 0) <= Q1_ODD;
    else
      Q1_o(SDLEN-1 downto 0) <= Q1_EVEN;
    end if;
    if(LR1_i = '0') then
      Q1_o(SDLEN*2-1 downto SDLEN) <= (others => '0');
    else
      Q1_o(SDLEN*2-1 downto SDLEN) <= Q1_ODD;
    end if;
  end process;
 
  process(RA2_LSB,LR2_i,Q2_EVEN,Q2_ODD)
  begin
    if(LR2_i = '0' and RA2_LSB = '1') then
      Q2_o(SDLEN-1 downto 0) <= Q2_ODD;
    else
      Q2_o(SDLEN-1 downto 0) <= Q2_EVEN;
    end if;
    if(LR2_i = '0') then
      Q2_o(SDLEN*2-1 downto SDLEN) <= (others => '0');
    else
      Q2_o(SDLEN*2-1 downto SDLEN) <= Q2_ODD;
    end if;
  end process;
 
  process(RA3_LSB,LR3_i,Q3_EVEN,Q3_ODD)
  begin
    if(LR3_i = '0' and RA3_LSB = '1') then
      Q3_o(SDLEN-1 downto 0) <= Q3_ODD;
    else
      Q3_o(SDLEN-1 downto 0) <= Q3_EVEN;
    end if;
    if(LR3_i = '0') then
      Q3_o(SDLEN*2-1 downto SDLEN) <= (others => '0');
    else
      Q3_o(SDLEN*2-1 downto SDLEN) <= Q3_ODD;
    end if;
  end process;
 
end ARC;
 

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.