-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- =============================================================================
-- Authors: Jens Voss
--
-- Entity: Stack (LIFO)
--
-- Description:
--
-- Implements a stack, a LIFO storage abstraction.
--
-- License:
-- =============================================================================
-- Copyright 2007-2016 Technische Universitaet Dresden - Germany
-- Chair of VLSI-Design, Diagnostics and Architecture
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- =============================================================================
library IEEE;
use IEEE.std_logic_1164.all;
entity [docs]dstruct_stack is
generic (
D_BITS : positive; -- Data Width
MIN_DEPTH : positive -- Minimum Stack Depth
);
port (
-- INPUTS
clk, rst : in std_logic;
-- Write Ports
din : in std_logic_vector(D_BITS-1 downto 0); -- Data Input
put : in std_logic; -- 0 -> pop, 1 -> push
full : out std_logic;
-- Read Ports
got : in std_logic;
dout : out std_logic_vector(D_BITS-1 downto 0);
valid : out std_logic
);
end entity dstruct_stack;
library IEEE;
use IEEE.numeric_std.all;
library PoC;
use PoC.config.all;
use PoC.utils.all;
use PoC.ocram.all;
architecture [docs]rtl of dstruct_stack is
-- Constants
constant A_BITS : natural := log2ceil(MIN_DEPTH);
-- Signals
signal stackpointer : unsigned(A_BITS-1 downto 0) := (others => '0');
signal we : std_logic := '0';
signal adr : unsigned(A_BITS-1 downto 0) := (others => '0');
signal s_adr : unsigned(A_BITS-1 downto 0) := (others => '0');
signal s_dout : std_logic_vector(D_BITS-1 downto 0) := (others => '0');
signal s_valid : std_logic := '0';
signal s_din : std_logic_vector(D_BITS-1 downto 0) := (others => '0');
-- ctrl signal for stackpointer operations
type ctrl_t is (PUSH, POP, IDLE);
signal ctrl : ctrl_t;
type state is (SEMPTY, NOTFULL, WAITING, SFULL);
signal current_state, next_state : state; -- current and next state
begin
-- Backing Memory
ram : entity poc.ocram_sp
generic map(
A_BITS => A_BITS,
D_BITS => D_BITS,
FILENAME => ""
)
port map(
clk => clk,
ce => '1',
we => we,
a => adr,
d => s_din,
q => s_dout
);
process(clk)
begin
if rising_edge(clk) then
if(rst = '1') then
current_state <= SEMPTY;
else
current_state <= next_state;
end if;
end if;
end process;
[docs]process(current_state, put, stackpointer, got)
begin
ctrl <= IDLE;
we <= '0';
s_adr <= (others =>'0');
valid <= '1';
full <= '0';
case( current_state ) is
when SEMPTY =>
valid <= '0';
next_state <= SEMPTY;
if(put = '1') then
-- push to empty stack!
next_state <= NOTFULL;
ctrl <= PUSH;
we <= '1';
else
-- enable is 0 -> do nothing
ctrl <= IDLE;
end if;
when NOTFULL=>
next_state <= NOTFULL;
s_adr <= stackpointer - 1;
if(got = '1' and put = '0') then
ctrl <= POP;
s_adr <= stackpointer - 2;
if stackpointer = 1 then
-- last value popped from stack -> empty
next_state <= SEMPTY;
end if;
elsif (got = '0' and put = '1') then
-- push to Stack
ctrl <= PUSH;
s_adr <= stackpointer;
we <= '1';
if stackpointer = (MIN_DEPTH - 1) then
next_state <= SFULL;
end if;
elsif (got = '1' and put = '1') then
-- overwrite ToS
we <= '1';
ctrl <= IDLE;
else
-- do nothing
ctrl <= IDLE;
end if;
when SFULL=>
next_state <= SFULL;
full <= '1';
s_adr <= stackpointer-1;
if(got = '1') then
-- pop from Stack
ctrl <= POP;
next_state <= NOTFULL;
s_adr <= stackpointer-2;
else
-- got is 0 -> do nothing
ctrl <= IDLE;
end if;
when others =>
ctrl <= IDLE;
next_state <= SEMPTY;
end case;
end process;
process(clk)
begin
if rising_edge(clk) then
case( ctrl ) is
when IDLE =>
stackpointer <= stackpointer;
when PUSH =>
stackpointer <= stackpointer + 1;
when POP =>
stackpointer <= stackpointer - 1;
when others =>
stackpointer <= stackpointer;
end case;
end if;
end process;
s_din <= din;
dout <= s_dout;
-- map local signals to ports
adr <= s_adr;
end rtl;