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

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_stack.vhd] - Rev 2

Compare with Previous | Blame | View Log

-----------------------------------------------------------------
--                                                             --
-----------------------------------------------------------------
--                                                             --
-- Copyright (C) 2017 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.                                 --
--                                                             --
-----------------------------------------------------------------
 
---------------------------------------------------------------
-- RV01 Stack
---------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all; 
use IEEE.numeric_std.all;
 
library WORK;
use WORK.RV01_CONSTS_PKG.all;
use WORK.RV01_TYPES_PKG.all;
use WORK.RV01_ARITH_PKG.all;
 
entity RV01_STACK is
  generic(
    DEPTH : natural := 4;
    WIDTH : natural := 32
  );
  port(
    CLK_i : in std_logic;
    RST_i : in std_logic;
    CLR_i : in std_logic;
    PUSH_i : in std_logic;
    POP_i : in std_logic;
    D_i : in std_logic_vector(WIDTH-1 downto 0);
 
    SE_o : out std_logic;
    SF_o : out std_logic;
    Q_o : out std_logic_vector(WIDTH-1 downto 0)
  );
end RV01_STACK;
 
architecture ARC of RV01_STACK is
 
  subtype STACK_ENTRY_T is std_logic_vector(WIDTH-1 downto 0);
  type STACK_ENTRY_VEC_T is array (natural range<>) of STACK_ENTRY_T;
 
  signal TP : integer range -1 to DEPTH+1;
  signal TP_q : integer range 0 to DEPTH;
  signal Q,Q_q : STACK_ENTRY_VEC_T(DEPTH-1 downto 0);
  signal SE,SE_q : std_logic;
  signal SF,SF_q : std_logic;
 
begin
 
  ----------------------------------------------------
  -- Notes
  ----------------------------------------------------
 
  -- The Stack holds up to DEPTH entries, a new data
  -- word is added at the lowest empty entry when
  -- PUSH_i = '1', the oldest data word is removed
  -- from bottom entry when POP_i = '1' (shifting other
  -- entries down by one position).
  -- When the stack is empty, TP_q = 0.
  -- When the stack is full, TP_q = DEPTH.
  -- If PUSH_i = '1' when the stack if full, the bottom
  -- data word is discarded, and the new data word is
  -- stored into the top entry.
  -- If POP_i = '1' when the stack is empty, nothing
  -- happens.
  -- Stack supports push-ing and pop-ing in the same
  -- cycle (when this occurs, the tail pointer remains
  -- unchanged, unless stack is empty).
 
  ----------------------------------------------------
  -- Tail pointer
  ----------------------------------------------------
 
  -- The tail pointer always points at the stack lowest 
  -- empty entry.
 
  -- Tail pointer updating logic
 
  process(TP_q,PUSH_i,POP_i,SE_q,SF_q)
    variable TMP : std_logic_vector(4-1 downto 0);
  begin
    TMP := SE_q & SF_q & PUSH_i & POP_i;
    case TMP is
      -- regular case (stack is neither empty or full)
      when "0000" => TP <= TP_q;
      when "0001" => TP <= TP_q - 1;
      when "0010" => TP <= TP_q + 1;
      when "0011" => TP <= TP_q;
      -- stack full (PUSH discards bottom entry)
      when "0100" => TP <= TP_q;
      when "0101" => TP <= TP_q - 1;
      when "0110" => TP <= TP_q;
      when "0111" => TP <= TP_q;
      -- stack empty (POP is ignored)
      when "1000" => TP <= TP_q;
      when "1001" => TP <= TP_q;
      when "1010" => TP <= TP_q + 1;
      when "1011" => TP <= TP_q + 1;
      -- 
      when others => TP <= TP_q;
    end case;
 
  end process;
 
  -- Tail pointer register
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1' or CLR_i = '1') then
        TP_q <= 0;
      else
        TP_q <= TP;
      end if;
    end if;
  end process;
 
  ----------------------------------------------------
  -- Stack empty flag register
  ----------------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1' or CLR_i = '1') then
        SE_q <= '0';
      elsif(
        (TP_q = 0 and PUSH_i = '0') or
        (TP_q = 1 and POP_i = '1')
      ) then
        SE_q <= '1';
      else
        SE_q <= '0';
      end if;
    end if;
  end process;
 
  ----------------------------------------------------
  -- Stack full flag register
  ----------------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1' or CLR_i = '1') then
        SF_q <= '0';
      elsif(
        (TP_q = DEPTH-1 and PUSH_i = '1') or
        (TP_q = DEPTH and POP_i = '0')
      ) then
        SF_q <= '1';
      else
        SF_q <= '0';
      end if;
    end if;
  end process;
 
  ----------------------------------------------------
  -- Stack data updating logic
  ----------------------------------------------------
 
  process(Q_q,SF_q,PUSH_i,POP_i,D_i)
  begin
    for k in DEPTH-1 downto 0 loop
      if(k = 0) then
        -- bottom entry
        if(PUSH_i = '1') then
          Q(k) <= D_i;
        elsif(POP_i = '1' and PUSH_i = '0') then
          Q(k) <= Q_q(k+1);
        else
          Q(k) <= Q_q(k);
        end if;
      elsif(k = DEPTH-1) then
        -- top entry
        if(PUSH_i = '1' and POP_i = '0') then
          Q(k) <= Q_q(k-1);
        else
          Q(k) <= Q_q(k);
        end if;
      else
        -- intermediate entry
        if(PUSH_i = '1' and POP_i = '0') then
          Q(k) <= Q_q(k-1);
        elsif(POP_i = '1' and PUSH_i = '0') then
          --Q(DEPTH-k-1) <= Q_q(DEPTH-k);
          Q(k) <= Q_q(k+1);
        else
          Q(k) <= Q_q(k);
        end if;
      end if;
    end loop;
  end process;
 
  ----------------------------------------------------
  -- Stack data registers
  ----------------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      for k in 0 to DEPTH-1 loop
        Q_q(k) <= Q(k);
      end loop;
    end if;
  end process;
 
  ----------------------------------------------------
  -- Outputs
  ----------------------------------------------------
 
  Q_o <= Q_q(0);
 
  SE_o <= SE_q;
 
  SF_o <= SF_q;
 
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.