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

Subversion Repositories g729a_codec

[/] [g729a_codec/] [trunk/] [VHDL/] [G729A_asip_ifq.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.                                 --
--                                                             --
-----------------------------------------------------------------
 
---------------------------------------------------------
-- Instruction Fetching Queue
---------------------------------------------------------
 
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_BASIC_PKG.all;
use WORK.G729A_ASIP_ARITH_PKG.all;
use work.G729A_ASIP_IDEC_2W_PKG.all;
 
entity G729A_ASIP_IFQ is
  port(
    CLK_i : in std_logic;
    RST_i : in std_logic;
    ID_HALT_i : in std_logic;
    IX_BJX_i : in std_logic;
    ID_ISSUE_i : in std_logic_vector(2-1 downto 0);
    IF_V_i : in std_logic_vector(2-1 downto 0);
    IF_PC0_i : in unsigned(ALEN-1 downto 0);
    IF_PC1_i : in unsigned(ALEN-1 downto 0);
    IF_INSTR0_i : in std_logic_vector(ILEN-1 downto 0);
    IF_INSTR1_i : in std_logic_vector(ILEN-1 downto 0);
    IF_DEC_INSTR0_i : in DEC_INSTR_T;
    IF_DEC_INSTR1_i : in DEC_INSTR_T;
    IF_IMM0_i : in std_logic;
    IF_IMM1_i : in std_logic;
    IF_OPB0_i : in LDWORD_T;
    IF_OPB1_i : in LDWORD_T;
 
    PSTALL_o : out std_logic;
    ID_V_o : out std_logic_vector(2-1 downto 0);
    ID_PC0_o : out unsigned(ALEN-1 downto 0);
    ID_PC1_o : out unsigned(ALEN-1 downto 0);
    ID_INSTR0_o : out std_logic_vector(ILEN-1 downto 0);
    ID_INSTR1_o : out std_logic_vector(ILEN-1 downto 0);
    ID_DEC_INSTR0_o : out DEC_INSTR_T;
    ID_DEC_INSTR1_o : out DEC_INSTR_T;
    ID_IMM0_o : out std_logic;
    ID_IMM1_o : out std_logic;
    ID_OPB0_o : out LDWORD_T;
    ID_OPB1_o : out LDWORD_T
  );
end G729A_ASIP_IFQ;
 
architecture ARC of G729A_ASIP_IFQ is
 
  constant IFQ_DEPTH : natural := 3;
 
  type IFQ_ENTRY_T is record
    DINSTR : DEC_INSTR_T;
    INSTR : std_logic_vector(ILEN-1 downto 0);
    PC : unsigned(ALEN-1 downto 0);
    IMM : std_logic;
    OPB : LDWORD_T;
  end record;
 
  type IFQ_T is array (natural range<>) of IFQ_ENTRY_T;
 
  signal IFQ_NEW_1,IFQ_NEW_0 : IFQ_ENTRY_T;
  signal IFQ,IFQ_q : IFQ_T(IFQ_DEPTH-1 downto 0);
  signal IFQV,IFQV_q : std_logic_vector(IFQ_DEPTH-1 downto 0);
  signal STALL,UPDT : std_logic;
 
begin
 
  ----------------------------------------------------
  -- Notes:
  -- The queue consists of 3 entries, entry #0 being the
  -- oldest entry and entry #2 being the newest one.
  -- Entries #0,1 act as pipeline registers between
  -- stages IF and ID (so that entries #0,1 are the
  -- currently decoded instructions).
  ----------------------------------------------------
 
  ----------------------------------------------------
  -- Fetch must stall if the number of empty queue
  -- entrie, plus the number of issued instructions
  -- is lower than two. 
  --
  -- Let's put this condition in truth table format:
  --
  -- 210 issue stall
  -- ---------------
  -- 000    00     0
  -- 001    00     0
  -- 001    01     0
  -- 01x    00     1
  -- 01x    01     0
  -- 01x    11     0
  -- 1xx    00     1
  -- 1xx    01     1
  -- 1xx    11     0 
  ----------------------------------------------------
 
  -- fetch stall flag
 
  --STALL <= '1' when (
  --  (IFQV_q(1) = '1' and ID_ISSUE_i = "00") or -- 2 instr. in queue and 0 issue
  --  (IFQV_q(2) = '1' and ID_ISSUE_i = "00") or -- 3 instr. in queue and 0 issue
  --  (IFQV_q(2) = '1' and ID_ISSUE_i = "01")    -- 3 instr. in queue and 1 issue
  --) else '0';
 
  -- ...re-coded to optimize timing
 
  STALL <= IFQV_q(2) when (ID_ISSUE_i = "01") else
    (IFQV_q(2) or IFQV_q(1)) when (ID_ISSUE_i = "00") else '0';
 
  ----------------------------------------------------
  -- Fetch queue data update
  -- 
  -- old       new
  -- 210 issue 210    keep entry
  -- ------------------------
  -- 000    ** 0nn B (keep -)
  -- 001    00 nno A (keep 0)
  -- 001    *1 0nn B (keep -)
  -- 01x    00 ooo - (stall)
  -- 01x    01 nno A (keep 1)
  -- 01x    11 0nn B (keep -)
  -- 1xx    00 ooo - (stall)
  -- 1xx    01 0oo C (stall) <- (*)
  -- 1xx    11 nno A (keep 2)
  --
  -- n = new instruction
  -- o = old instruction
  -- 0 = garbage
 
  -- (*) this is special case: fetch must be stalled because
  -- there's no room for a new instruction pair in the queue,
  -- but queue data must be updated, because one instruction
  -- is issued.
 
  ----------------------------------------------------
 
  -- queue update flag
 
  UPDT <= '0' when (
    (IFQV_q(1) = '1' and ID_ISSUE_i = "00") or -- 2 instr. in queue and 0 issue
    (IFQV_q(2) = '1' and ID_ISSUE_i = "00") -- 3 instr. in queue and 0 issue
  ) else '1';
 
  IFQ_NEW_0 <= (
    IF_DEC_INSTR0_i,
    IF_INSTR0_i,
    IF_PC0_i,
    IF_IMM0_i,
    IF_OPB0_i
  );
 
  IFQ_NEW_1 <= (
    IF_DEC_INSTR1_i,
    IF_INSTR1_i,
    IF_PC1_i,
    IF_IMM1_i,
    IF_OPB1_i
  );
 
  -- fetch queue data update logic
  process(IFQV_q,IFQ_q,IF_V_i,ID_ISSUE_i,IFQ_NEW_1,IFQ_NEW_0)
    variable KEEP : natural range 2 downto 0;
  begin
    case ID_ISSUE_i is
      when "00" => KEEP := 0;
      when "01" => KEEP := 1;
      when others => KEEP := 2;
    end case;
    if(
      (IFQV_q(2 downto 0) = "001" and ID_ISSUE_i = "00") or
      (IFQV_q(2 downto 1) = "01" and ID_ISSUE_i = "01") or
      (IFQV_q(2) = '1' and ID_ISSUE_i = "11")
    ) then
      -- "A" case (1 old instr. in queue)
      IFQV <= IF_V_i & IFQV_q(KEEP);
      IFQ <= (IFQ_NEW_1,IFQ_NEW_0,IFQ_q(KEEP)); 
    elsif(
      (IFQV_q(2 downto 0) = "000") or
      (IFQV_q(2 downto 0) = "001" and ID_ISSUE_i(0) = '1') or
      (IFQV_q(2 downto 1) = "01" and ID_ISSUE_i = "11")
    ) then
      -- "B" case (no old instr. in queue)
      IFQV <= '0' & IF_V_i; 
      IFQ <= (IFQ_q(2),IFQ_NEW_1,IFQ_NEW_0); 
    else -- if(IFQV_q(2) = '1' and ID_ISSUE_i = "01")
      -- "C" case (2 old instr. in queue)
      IFQV <= '0' & IFQV_q(2 downto 1); 
      IFQ <= (IFQ_q(2),IFQ_q(2),IFQ_q(1)); 
    end if;
  end process;
 
  -- fetch queue data registers
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
 
      if(RST_i = '1' or IX_BJX_i = '1') then
        IFQV_q <= (others => '0');
      elsif(UPDT = '1' and ID_HALT_i = '0') then
        IFQV_q <= IFQV;
      elsif(ID_HALT_i = '1') then
        IFQV_q <= (others => '0');
      end if;
 
      if(UPDT = '1') then
        IFQ_q <= IFQ;
      end if;
 
    end if;
  end process;
 
  ----------------------------------------------------
  -- outputs
  ----------------------------------------------------
 
  PSTALL_o <= STALL;
 
  ID_V_o <= IFQV_q(1 downto 0);
  ID_PC0_o <= IFQ_q(0).PC;
  ID_PC1_o <= IFQ_q(1).PC;
  ID_INSTR0_o <= IFQ_q(0).INSTR;
  ID_INSTR1_o <= IFQ_q(1).INSTR;
  ID_DEC_INSTR0_o <= IFQ_q(0).DINSTR;
  ID_DEC_INSTR1_o <= IFQ_q(1).DINSTR;
  ID_IMM0_o <= IFQ_q(0).IMM;
  ID_IMM1_o <= IFQ_q(1).IMM;
  ID_OPB0_o <= IFQ_q(0).OPB;
  ID_OPB1_o <= IFQ_q(1).OPB;
 
end;
 
 

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.