-- 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: Patrick Lehmann
--
-- Entity: A generic buffer module for the PoC.Stream protocol.
--
-- Description:
--
-- This module implements a generic buffer (FIFO) for the
-- :doc:`PoC.Stream </Interfaces/Stream>` protocol. It is generic in
-- ``DATA_BITS`` and in ``META_BITS`` as well as in FIFO depths for data and
-- meta information.
--
-- License:
-- =============================================================================
-- Copyright 2007-2015 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;
use IEEE.NUMERIC_STD.all;
library PoC;
use PoC.config.all;
use PoC.utils.all;
use PoC.vectors.all;
entity [docs]stream_Buffer is
generic (
FRAMES : positive := 2;
DATA_BITS : positive := 8;
DATA_FIFO_DEPTH : positive := 8;
META_BITS : T_POSVEC := (0 => 8);
META_FIFO_DEPTH : T_POSVEC := (0 => 16)
);
port (
Clock : in std_logic;
Reset : in std_logic;
-- IN Port
In_Valid : in std_logic;
In_Data : in std_logic_vector(DATA_BITS - 1 downto 0);
In_SOF : in std_logic;
In_EOF : in std_logic;
In_Ack : out std_logic;
In_Meta_rst : out std_logic;
In_Meta_nxt : out std_logic_vector(META_BITS'length - 1 downto 0);
In_Meta_Data : in std_logic_vector(isum(META_BITS) - 1 downto 0);
-- OUT Port
Out_Valid : out std_logic;
Out_Data : out std_logic_vector(DATA_BITS - 1 downto 0);
Out_SOF : out std_logic;
Out_EOF : out std_logic;
Out_Ack : in std_logic;
Out_Meta_rst : in std_logic;
Out_Meta_nxt : in std_logic_vector(META_BITS'length - 1 downto 0);
Out_Meta_Data : out std_logic_vector(isum(META_BITS) - 1 downto 0)
);
end entity;
architecture [docs]rtl of stream_Buffer is
attribute FSM_ENCODING : string;
constant META_STREAMS : positive := META_BITS'length;
type T_WRITER_STATE is (ST_IDLE, ST_FRAME);
type T_READER_STATE is (ST_IDLE, ST_FRAME);
signal Writer_State : T_WRITER_STATE := ST_IDLE;
signal Writer_NextState : T_WRITER_STATE;
signal Reader_State : T_READER_STATE := ST_IDLE;
signal Reader_NextState : T_READER_STATE;
constant EOF_BIT : natural := DATA_BITS;
signal DataFIFO_put : std_logic;
signal DataFIFO_DataIn : std_logic_vector(DATA_BITS downto 0);
signal DataFIFO_Full : std_logic;
signal DataFIFO_got : std_logic;
signal DataFIFO_DataOut : std_logic_vector(DataFIFO_DataIn'range);
signal DataFIFO_Valid : std_logic;
signal FrameCommit : std_logic;
signal Meta_rst : std_logic_vector(META_BITS'length - 1 downto 0);
begin
assert (META_BITS'length = META_FIFO_DEPTH'length) report "META_BITS'length /= META_FIFO_DEPTH'length" severity FAILURE;
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
Writer_State <= ST_IDLE;
Reader_State <= ST_IDLE;
else
Writer_State <= Writer_NextState;
Reader_State <= Reader_NextState;
end if;
end if;
end process;
[docs]process(Writer_State,
In_Valid, In_Data, In_SOF, In_EOF,
DataFIFO_Full)
begin
Writer_NextState <= Writer_State;
In_Ack <= '0';
DataFIFO_put <= '0';
DataFIFO_DataIn(In_Data'range) <= In_Data;
DataFIFO_DataIn(EOF_BIT) <= In_EOF;
case Writer_State is
when ST_IDLE =>
In_Ack <= not DataFIFO_Full;
DataFIFO_put <= In_Valid;
if ((In_Valid and In_SOF and not In_EOF) = '1') then
Writer_NextState <= ST_FRAME;
end if;
when ST_FRAME =>
In_Ack <= not DataFIFO_Full;
DataFIFO_put <= In_Valid;
if ((In_Valid and In_EOF and not DataFIFO_Full) = '1') then
Writer_NextState <= ST_IDLE;
end if;
end case;
end process;
[docs]process(Reader_State,
Out_Ack,
DataFIFO_Valid, DataFIFO_DataOut)
begin
Reader_NextState <= Reader_State;
Out_Valid <= '0';
Out_Data <= DataFIFO_DataOut(Out_Data'range);
Out_SOF <= '0';
Out_EOF <= DataFIFO_DataOut(EOF_BIT);
DataFIFO_got <= '0';
case Reader_State is
when ST_IDLE =>
Out_Valid <= DataFIFO_Valid;
Out_SOF <= '1';
DataFIFO_got <= Out_Ack;
if ((DataFIFO_Valid and not DataFIFO_DataOut(EOF_BIT) and Out_Ack) = '1') then
Reader_NextState <= ST_FRAME;
end if;
when ST_FRAME =>
Out_Valid <= DataFIFO_Valid;
DataFIFO_got <= Out_Ack;
if ((DataFIFO_Valid and DataFIFO_DataOut(EOF_BIT) and Out_Ack) = '1') then
Reader_NextState <= ST_IDLE;
end if;
end case;
end process;
DataFIFO : entity PoC.fifo_cc_got
generic map (
D_BITS => DATA_BITS + 1, -- Data Width
MIN_DEPTH => (DATA_FIFO_DEPTH * FRAMES), -- Minimum FIFO Depth
DATA_REG => ((DATA_FIFO_DEPTH * FRAMES) <= 128), -- Store Data Content in Registers
STATE_REG => TRUE, -- Registered Full/Empty Indicators
OUTPUT_REG => FALSE, -- Registered FIFO Output
ESTATE_WR_BITS => 0, -- Empty State Bits
FSTATE_RD_BITS => 0 -- Full State Bits
)
port map (
-- Global Reset and Clock
clk => Clock,
rst => Reset,
-- Writing Interface
put => DataFIFO_put,
din => DataFIFO_DataIn,
full => DataFIFO_Full,
estate_wr => open,
-- Reading Interface
got => DataFIFO_got,
dout => DataFIFO_DataOut,
valid => DataFIFO_Valid,
fstate_rd => open
);
FrameCommit <= DataFIFO_Valid and DataFIFO_DataOut(EOF_BIT) and Out_Ack;
In_Meta_rst <= slv_and(Meta_rst);
genMeta : for i in 0 to META_BITS'length - 1 generate
begin
genReg : if META_FIFO_DEPTH(i) = 1 generate
signal MetaReg_DataIn : std_logic_vector(META_BITS(i) - 1 downto 0);
signal MetaReg_d : std_logic_vector(META_BITS(i) - 1 downto 0) := (others => '0');
signal MetaReg_DataOut : std_logic_vector(META_BITS(i) - 1 downto 0);
begin
MetaReg_DataIn <= In_Meta_Data(high(META_BITS, i) downto low(META_BITS, i));
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
MetaReg_d <= (others => '0');
elsif ((In_Valid and In_SOF) = '1') then
MetaReg_d <= MetaReg_DataIn;
end if;
end if;
end process;
MetaReg_DataOut <= MetaReg_d;
Out_Meta_Data(high(META_BITS, i) downto low(META_BITS, i)) <= MetaReg_DataOut;
end generate; -- META_FIFO_DEPTH(i) = 1
genFIFO : if META_FIFO_DEPTH(i) > 1 generate
signal MetaFIFO_put : std_logic;
signal MetaFIFO_DataIn : std_logic_vector(META_BITS(i) - 1 downto 0);
signal MetaFIFO_Full : std_logic;
signal MetaFIFO_Commit : std_logic;
signal MetaFIFO_Rollback : std_logic;
signal MetaFIFO_got : std_logic;
signal MetaFIFO_DataOut : std_logic_vector(MetaFIFO_DataIn'range);
signal MetaFIFO_Valid : std_logic;
signal Writer_CounterControl : std_logic := '0';
signal Writer_Counter_en : std_logic;
signal Writer_Counter_us : unsigned(log2ceilnz(META_FIFO_DEPTH(i)) - 1 downto 0) := (others => '0');
begin
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
Writer_CounterControl <= '0';
elsif ((In_Valid and In_SOF) = '1') then
Writer_CounterControl <= '1';
elsif Writer_Counter_us = (META_FIFO_DEPTH(i) - 1) then
Writer_CounterControl <= '0';
end if;
end if;
end process;
Writer_Counter_en <= (In_Valid and In_SOF) or Writer_CounterControl;
process(Clock)
begin
if rising_edge(Clock) then
if (Writer_Counter_en = '0') then
Writer_Counter_us <= (others => '0');
else
Writer_Counter_us <= Writer_Counter_us + 1;
end if;
end if;
end process;
Meta_rst(i) <= not Writer_Counter_en;
In_Meta_nxt(i) <= Writer_Counter_en;
MetaFIFO_put <= Writer_Counter_en;
MetaFIFO_DataIn <= In_Meta_Data(high(META_BITS, i) downto low(META_BITS, i));
MetaFIFO : entity PoC.fifo_cc_got_tempgot
generic map (
D_BITS => META_BITS(i), -- Data Width
MIN_DEPTH => (META_FIFO_DEPTH(i) * FRAMES), -- Minimum FIFO Depth
DATA_REG => TRUE, -- Store Data Content in Registers
STATE_REG => FALSE, -- Registered Full/Empty Indicators
OUTPUT_REG => FALSE, -- Registered FIFO Output
ESTATE_WR_BITS => 0, -- Empty State Bits
FSTATE_RD_BITS => 0 -- Full State Bits
)
port map (
-- Global Reset and Clock
clk => Clock,
rst => Reset,
-- Writing Interface
put => MetaFIFO_put,
din => MetaFIFO_DataIn,
full => MetaFIFO_Full,
estate_wr => open,
-- Reading Interface
got => MetaFIFO_got,
dout => MetaFIFO_DataOut,
valid => MetaFIFO_Valid,
fstate_rd => open,
commit => MetaFIFO_Commit,
rollback => MetaFIFO_Rollback
);
MetaFIFO_got <= Out_Meta_nxt(i);
MetaFIFO_Commit <= FrameCommit;
MetaFIFO_Rollback <= Out_Meta_rst;
Out_Meta_Data(high(META_BITS, i) downto low(META_BITS, i)) <= MetaFIFO_DataOut;
end generate; -- (META_FIFO_DEPTH(i) > 1)
end generate;
end architecture;