-- 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:
--
-- .. TODO:: No documentation available.
--
-- 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_DeMux is
generic (
PORTS : positive := 2;
DATA_BITS : positive := 8;
META_BITS : natural := 8;
META_REV_BITS : natural := 2
);
port (
Clock : in std_logic;
Reset : in std_logic;
-- Control interface
DeMuxControl : in std_logic_vector(PORTS - 1 downto 0);
-- IN Port
In_Valid : in std_logic;
In_Data : in std_logic_vector(DATA_BITS - 1 downto 0);
In_Meta : in std_logic_vector(META_BITS - 1 downto 0);
In_Meta_rev : out std_logic_vector(META_REV_BITS - 1 downto 0);
In_SOF : in std_logic;
In_EOF : in std_logic;
In_Ack : out std_logic;
-- OUT Ports
Out_Valid : out std_logic_vector(PORTS - 1 downto 0);
Out_Data : out T_SLM(PORTS - 1 downto 0, DATA_BITS - 1 downto 0);
Out_Meta : out T_SLM(PORTS - 1 downto 0, META_BITS - 1 downto 0);
Out_Meta_rev : in T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0);
Out_SOF : out std_logic_vector(PORTS - 1 downto 0);
Out_EOF : out std_logic_vector(PORTS - 1 downto 0);
Out_Ack : in std_logic_vector(PORTS - 1 downto 0)
);
end entity;
architecture [docs]rtl of stream_DeMux is
attribute KEEP : boolean;
attribute FSM_ENCODING : string;
subtype T_CHANNEL_INDEX is natural range 0 to PORTS - 1;
type T_STATE is (ST_IDLE, ST_DATAFLOW, ST_DISCARD_FRAME);
signal State : T_STATE := ST_IDLE;
signal NextState : T_STATE;
signal Is_SOF : std_logic;
signal Is_EOF : std_logic;
signal In_Ack_i : std_logic;
signal Out_Valid_i : std_logic;
signal DiscardFrame : std_logic;
signal ChannelPointer_rst : std_logic;
signal ChannelPointer_en : std_logic;
signal ChannelPointer : std_logic_vector(PORTS - 1 downto 0);
signal ChannelPointer_d : std_logic_vector(PORTS - 1 downto 0) := (others => '0');
signal ChannelPointer_bin : unsigned(log2ceilnz(PORTS) - 1 downto 0);
signal idx : T_CHANNEL_INDEX;
signal Out_Data_i : T_SLM(PORTS - 1 downto 0, DATA_BITS - 1 downto 0) := (others => (others => 'Z')); -- necessary default assignment 'Z' to get correct simulation results (iSIM, vSIM, ghdl/gtkwave)
signal Out_Meta_i : T_SLM(PORTS - 1 downto 0, META_BITS - 1 downto 0) := (others => (others => 'Z')); -- necessary default assignment 'Z' to get correct simulation results (iSIM, vSIM, ghdl/gtkwave)
begin
In_Ack_i <= slv_or(Out_Ack and ChannelPointer);
DiscardFrame <= slv_nor(DeMuxControl);
Is_SOF <= In_Valid and In_SOF;
Is_EOF <= In_Valid and In_EOF;
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
State <= ST_IDLE;
else
State <= NextState;
end if;
end if;
end process;
[docs]process(State, In_Ack_i, In_Valid, Is_SOF, Is_EOF, DiscardFrame, DeMuxControl, ChannelPointer_d)
begin
NextState <= State;
ChannelPointer_rst <= Is_EOF;
ChannelPointer_en <= '0';
ChannelPointer <= ChannelPointer_d;
In_Ack <= '0';
Out_Valid_i <= '0';
case State is
when ST_IDLE =>
ChannelPointer <= DeMuxControl;
if (Is_SOF = '1') then
if (DiscardFrame = '0') then
ChannelPointer_en <= '1';
In_Ack <= In_Ack_i;
Out_Valid_i <= '1';
NextState <= ST_DATAFLOW;
else
In_Ack <= '1';
NextState <= ST_DISCARD_FRAME;
end if;
end if;
when ST_DATAFLOW =>
In_Ack <= In_Ack_i;
Out_Valid_i <= In_Valid;
ChannelPointer <= ChannelPointer_d;
if (Is_EOF = '1') then
NextState <= ST_IDLE;
end if;
when ST_DISCARD_FRAME =>
In_Ack <= '1';
if (Is_EOF = '1') then
NextState <= ST_IDLE;
end if;
end case;
end process;
process(Clock)
begin
if rising_edge(Clock) then
if ((Reset or ChannelPointer_rst) = '1') then
ChannelPointer_d <= (others => '0');
elsif (ChannelPointer_en = '1') then
ChannelPointer_d <= DeMuxControl;
end if;
end if;
end process;
ChannelPointer_bin <= onehot2bin(ChannelPointer_d);
idx <= to_integer(ChannelPointer_bin);
In_Meta_rev <= get_row(Out_Meta_rev, idx);
genOutput : for i in 0 to PORTS - 1 generate
Out_Valid(i) <= Out_Valid_i and ChannelPointer(i);
assign_row(Out_Data_i, In_Data, i);
assign_row(Out_Meta_i, In_Meta, i);
Out_SOF(i) <= In_SOF;
Out_EOF(i) <= In_EOF;
end generate;
Out_Data <= Out_Data_i;
Out_Meta <= Out_Meta_i;
end architecture;