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

Subversion Repositories g729a_codec

[/] [g729a_codec/] [trunk/] [VHDL/] [G729A_asip_bjxlog.vhd] - Rev 2

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 Branch/Jump eXecute Logic
---------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
library work;
use work.G729A_ASIP_PKG.all;
use work.G729A_ASIP_OP_PKG.all;
 
entity G729A_ASIP_BJXLOG is
  port(
    CLK_i : in std_logic;
    RST_i : in std_logic;
    BJ_OP : in BJ_OP_T;
    PC0P1_i : in unsigned(ALEN-1 downto 0);
    PC1P1_i : in unsigned(ALEN-1 downto 0);
    PC0_i : in unsigned(ALEN-1 downto 0);
    PCSEL_i : in std_logic;
    OPA_i : in LDWORD_T;
    OPB_i : in LDWORD_T;
    OPC_i : in SDWORD_T;
    IV_i : in std_logic;
    LLCRX_i : in std_logic;
    FSTLL_i : in std_logic;
 
    BJX_o : out std_logic;
    BJTA_o : out unsigned(ALEN-1 downto 0)
  );
end G729A_ASIP_BJXLOG;
 
architecture ARC of G729A_ASIP_BJXLOG is
 
  constant SZERO : SDWORD_T := (others => '0');
  constant LZERO : LDWORD_T := (others => '0');
 
  signal BJX : std_logic;
  signal BJTA,BJTA_q : unsigned(SDLEN-1 downto 0);
  signal BJX_q : std_logic;
  signal BJTA1,BJTA2,BJTA3,BJTA4 : unsigned(SDLEN-1 downto 0);
 
  function to_unsigned(S : signed) return unsigned is
    variable U : unsigned(S'HIGH downto S'LOW);
  begin
    for i in S'HIGH downto S'LOW loop
      U(i) := S(i);
    end loop;
    return(U);
  end function;
 
  function to_signed(U : unsigned) return signed is
    variable S : signed(U'HIGH downto U'LOW);
  begin
    for i in U'HIGH downto U'LOW loop
      S(i) := U(i);
    end loop;
    return(S);
  end function;
 
  function qmark(C : std_logic; A,B : std_logic) return std_logic is
  begin
    if(C = '1') then
      return(A);
    else
      return(B);
    end if;
  end function;
 
  function qmark(C : boolean; A,B : std_logic) return std_logic is
  begin
    if(C) then
      return(A);
    else
      return(B);
    end if;
  end function;
 
  function wrap_sum(A,B : unsigned(SDLEN-1 downto 0)) return unsigned is
    variable TMP : unsigned(SDLEN downto 0);
  begin
    -- A is an unsigned value and thus is zero-extended
    -- B has to be instead treated as a signed value and thus is sign-extended
    TMP := ('0' & A) + (B(SDLEN-1) & B);
    -- result is TMP with MSb removed (wrap-up)
    return(TMP(SDLEN-1 downto 0));
  end function;
 
begin 
 
  -- Note:
  -- llcr and llcri instructions are treated ad unconditional
  -- jumps to address PC+1. This is needed to insure that
  -- a possible loop closing instruction located at PC+1 or
  -- PC+2 is properly handled (such instruction would leave
  -- IF stage before llcr* instruction is executed). The
  -- "ad-hoc" jump to PC+1 essentially re-fetches the two
  -- instructions at risk.
 
  -- Pre-calculate all possible target addresses
 
  -- TA for LLCRX "unconditional jump"
  BJTA1 <= PC0P1_i when PCSEL_i = '0' else PC1P1_i;
 
  -- TA for beq/bne
  BJTA2 <= wrap_sum(PC0_i,to_unsigned(OPC_i));
 
  -- TA for branches
  BJTA3 <= wrap_sum(PC0_i,to_unsigned(OPB_i(SDLEN-1 downto 0)));
 
  -- TA for jumps
  BJTA4 <= to_unsigned(OPA_i(SDLEN-1 downto 0))
    when ((BJ_OP = BJ_JR) or (BJ_OP = BJ_JRL))
    else to_unsigned(OPB_i(SDLEN-1 downto 0));
 
  -- Select target address
 
  process(LLCRX_i,BJ_OP,BJTA1,BJTA2,BJTA3,BJTA4)
  begin
    if(LLCRX_i = '1') then
      BJTA <= BJTA1;
    elsif((BJ_OP = BJ_BEQ) or (BJ_OP = BJ_BNE)) then
      BJTA <= BJTA2;
    elsif((BJ_OP /= BJ_JI) and (BJ_OP /= BJ_JIL) and (BJ_OP /= BJ_JR) and (BJ_OP /= BJ_JRL)) then
      BJTA <= BJTA3;
    else
      BJTA <= BJTA4;
    end if;
  end process;
 
  -- Set branch/jump execute flag
 
  process(BJ_OP,OPA_i,OPB_i,OPC_i,LLCRX_i)
    variable OPA_LO : SDWORD_T;
    variable OPB_LO : SDWORD_T;
    variable AEQB_S : std_logic;
    variable AEQ0_S : std_logic;
    variable ALT0_S : std_logic;
    variable AEQ0_L : std_logic;
    variable ALT0_L : std_logic;
  begin
 
    OPA_LO := OPA_i(SDLEN-1 downto 0);
    OPB_LO := OPB_i(SDLEN-1 downto 0);
 
    -- Generate comparison flags
 
    AEQB_S := qmark(OPA_LO = OPB_LO,'1','0'); 
 
    AEQ0_S := qmark(OPA_LO = 0,'1','0'); 
 
    ALT0_S := OPA_LO(SDLEN-1); 
 
    AEQ0_L := qmark(OPA_i = 0,'1','0'); 
 
    ALT0_L := OPA_i(LDLEN-1);
 
    -- B/J instructions involving comparison of long-type data
    -- (LBLEZ or LBGTZ) or between two non-constant values
    -- (BEQ or BNE) are given priority to improve timing.
 
    if(BJ_OP = BJ_LBLEZ or BJ_OP = BJ_LBGTZ or BJ_OP = BJ_BEQ or BJ_OP = BJ_BNE) then
 
      BJX <=
        qmark(BJ_OP = BJ_LBLEZ,ALT0_L or AEQ0_L,'0') or
        qmark(BJ_OP = BJ_LBGTZ,not(ALT0_L) and not(AEQ0_L),'0') or
        qmark(BJ_OP = BJ_BEQ,AEQB_S,'0') or
        qmark(BJ_OP = BJ_BNE,not(AEQB_S),'0');
 
    else
 
    case BJ_OP is
 
      when BJ_JI|BJ_JIL|BJ_JR|BJ_JRL  =>
        BJX <= '1';
 
      when BJ_BLEZ =>
        BJX <= ALT0_S or AEQ0_S;
 
      when BJ_BGTZ =>
        BJX <= not(ALT0_S) and not(AEQ0_S);
 
      when BJ_BLTZ =>
        BJX <= ALT0_S;
 
      when BJ_BGEZ =>
        BJX <= not(ALT0_S);
 
      when BJ_LBLTZ =>
        BJX <= ALT0_L;
 
      when BJ_LBGEZ =>
        BJX <= not(ALT0_L);
 
      when others =>
        BJX <= LLCRX_i; --'0';
 
    end case;
 
    end if;
 
  end process;
 
  -- B/J execute flag and target address register.
  -- These registers are needed when a B/J is taken
  -- while fecth is stalled: in such condition B/J
  -- must deferred to first un-stalled cycle.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(FSTLL_i = '1') then
        BJTA_q <= BJTA;
      end if;
      if(RST_i = '1' or FSTLL_i = '0') then
        BJX_q <= '0';
      elsif(FSTLL_i = '1') then
        BJX_q <= (BJX and IV_i);
      end if;
    end if;
  end process;
 
  -- A branch/jump is actually executed if:
  -- 1) there's a valid B/J instruction in IX1 stage, OR
  -- 2) there's a pending B/J.
 
  BJX_o <= (BJX and IV_i) or (BJX_q);
 
  BJTA_o <= BJTA_q when (BJX_q = '1') else BJTA;
 
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.