-- $Source: /evtfs/home/tres/vhdl/play/RCS/stack.vhd,v $
-- Revision  : $Revision: 1.5 $
-- Register Stack Example
-- Mike Treseler                        Tue Jul  3 13:00:45 2007
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package stack_pkg is
   constant reg_len_c    : positive := 32;
   constant array_len_c  : positive := 32;
   subtype reg_t is std_logic_vector(reg_len_c-1 downto 0);   
   type regs_t is array (0 to array_len_c-1) of reg_t;
   constant reg_init_c : reg_t    := (others => '0');
end package stack_pkg;

-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.stack_pkg.all;

entity stack is
   port (
      clock : in  std_ulogic;
      reset : in  std_ulogic;
      push  : in  std_ulogic;
      pop   : in  std_ulogic;
      d     : in  reg_t;
      q     : out reg_t
      );
end entity stack;

architecture synth of stack is
begin
   main : process(reset, clock) is
-------------------------------------------------------------------------------
-- Process declarations
-------------------------------------------------------------------------------
      variable regs_v     : regs_t;
      variable out_v      : reg_t;
-------------------------------------------------------------------------------
-- Template Procedures: Always same three names. Contents varies.
-------------------------------------------------------------------------------
      procedure init_regs is
      begin  -- procedure init
         out_v  := reg_init_c;
         regs_v := (others => reg_init_c);
      end procedure init_regs;
-------------------------------------------------------------------------------
      procedure update_regs is   -- distilled functional description
      begin
         if
            pop = '0' and push = '1'
         then
            regs_v := d & regs_v(0 to array_len_c-2);  -- push D into r0
         elsif
            pop = '1' and push = '0'
         then
            out_v := regs_v(0);     -- save r0 before popping.
                                    -- copy r1 into r0, r2 into r1, etc. 
            regs_v(0 to array_len_c-2) := regs_v (1 to array_len_c-1);

         end if;
      end procedure update_regs;
-------------------------------------------------------------------------------
      procedure update_ports is         -- wire register variables out to port
      begin
         q <= out_v;
      end procedure update_ports;
-------------------------------------------------------------------------------
-- Process Template -- Always exactly the same:
-------------------------------------------------------------------------------
   begin  -- process template
      if reset = '1' then  
         init_regs;        
      elsif rising_edge(clock) then
         update_regs;      
      end if;  
      update_ports;         
   end process main;  
end architecture synth;
-------------------------------------------------------------------------------