-- 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: TODO
--
-- 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;
use PoC.net.all;
entity [docs]mac_RX_DestMAC_Switch is
generic (
DEBUG : boolean := FALSE;
MAC_ADDRESSES : T_NET_MAC_ADDRESS_VECTOR := (0 => C_NET_MAC_ADDRESS_EMPTY);
MAC_ADDRESSE_MASKS : T_NET_MAC_ADDRESS_VECTOR := (0 => C_NET_MAC_MASK_DEFAULT)
);
port (
Clock : in std_logic;
Reset : in std_logic;
In_Valid : in std_logic;
In_Data : in T_SLV_8;
In_SOF : in std_logic;
In_EOF : in std_logic;
In_Ack : out std_logic;
Out_Valid : out std_logic_vector(MAC_ADDRESSES'length - 1 downto 0);
Out_Data : out T_SLVV_8(MAC_ADDRESSES'length - 1 downto 0);
Out_SOF : out std_logic_vector(MAC_ADDRESSES'length - 1 downto 0);
Out_EOF : out std_logic_vector(MAC_ADDRESSES'length - 1 downto 0);
Out_Ack : in std_logic_vector(MAC_ADDRESSES'length - 1 downto 0);
Out_Meta_DestMACAddress_rst : in std_logic_vector(MAC_ADDRESSES'length - 1 downto 0);
Out_Meta_DestMACAddress_nxt : in std_logic_vector(MAC_ADDRESSES'length - 1 downto 0);
Out_Meta_DestMACAddress_Data : out T_SLVV_8(MAC_ADDRESSES'length - 1 downto 0)
);
end entity;
architecture [docs]rtl of mac_RX_DestMAC_Switch is
attribute FSM_ENCODING : string;
constant PORTS : positive := MAC_ADDRESSES'length;
constant MAC_ADDRESSES_I : T_NET_MAC_ADDRESS_VECTOR(0 to PORTS - 1) := MAC_ADDRESSES;
constant MAC_ADDRESSE_MASKS_I : T_NET_MAC_ADDRESS_VECTOR(0 to PORTS - 1) := MAC_ADDRESSE_MASKS;
type T_STATE is (
ST_IDLE,
ST_DEST_MAC_1,
ST_DEST_MAC_2,
ST_DEST_MAC_3,
ST_DEST_MAC_4,
ST_DEST_MAC_5,
ST_PAYLOAD_1,
ST_PAYLOAD_N,
ST_DISCARD_FRAME
);
subtype T_MAC_BYTEINDEX is natural range 0 to 5;
signal State : T_STATE := ST_IDLE;
signal NextState : T_STATE;
attribute FSM_ENCODING of State : signal is ite(DEBUG, "gray", ite((VENDOR = VENDOR_XILINX), "auto", "default"));
signal In_Ack_i : std_logic;
signal Is_DataFlow : std_logic;
signal Is_SOF : std_logic;
signal Is_EOF : std_logic;
signal New_Valid_i : std_logic;
signal New_SOF_i : std_logic;
signal Out_Ack_i : std_logic;
signal MAC_ByteIndex : T_MAC_BYTEINDEX;
signal CompareRegister_rst : std_logic;
signal CompareRegister_init : std_logic;
signal CompareRegister_clear : std_logic;
signal CompareRegister_en : std_logic;
signal CompareRegister_d : std_logic_vector(PORTS - 1 downto 0) := (others => '1');
signal NoHits : std_logic;
constant MAC_ADDRESS_LENGTH : positive := 6; -- MAC -> 6 bytes
constant READER_COUNTER_BITS : positive := log2ceilnz(MAC_ADDRESS_LENGTH);
signal Reader_Counter_rst : std_logic;
signal Reader_Counter_en : std_logic;
signal Reader_Counter_us : unsigned(READER_COUNTER_BITS - 1 downto 0) := (others => '0');
signal DestinationMAC_rst : std_logic;
signal DestinationMAC_en : std_logic;
signal DestinationMAC_sel : T_MAC_BYTEINDEX;
signal DestinationMAC_d : T_NET_MAC_ADDRESS := C_NET_MAC_ADDRESS_EMPTY;
signal Out_Meta_DestMACAddress_rst_i : std_logic;
signal Out_Meta_DestMACAddress_nxt_i : std_logic;
begin
assert FALSE report "RX_DestMAC_Switch: ports=" & integer'image(PORTS) severity NOTE;
In_Ack <= In_Ack_i;
Is_DataFlow <= In_Valid and In_Ack_i;
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, Is_DataFlow, Is_SOF, Is_EOF, In_Valid, NoHits, Out_Ack_i)
begin
NextState <= State;
In_Ack_i <= '0';
New_Valid_i <= '0';
New_SOF_i <= '0';
CompareRegister_en <= '0';
CompareRegister_rst <= '0';
CompareRegister_init <= Is_SOF;
CompareRegister_clear <= Is_EOF;
MAC_ByteIndex <= 0;
DestinationMAC_rst <= '0';
DestinationMAC_en <= '0';
case State is
when ST_IDLE =>
MAC_ByteIndex <= 5;
DestinationMAC_en <= In_Valid;
if (Is_SOF = '1') then
In_Ack_i <= '1';
if (Is_EOF = '0') then
NextState <= ST_DEST_MAC_1;
else
NextState <= ST_IDLE;
end if;
end if;
when ST_DEST_MAC_1 =>
MAC_ByteIndex <= 4;
CompareRegister_en <= In_Valid;
DestinationMAC_en <= In_Valid;
if (In_Valid = '1') then
In_Ack_i <= '1';
if (Is_EOF = '0') then
NextState <= ST_DEST_MAC_2;
else
NextState <= ST_IDLE;
end if;
end if;
when ST_DEST_MAC_2 =>
MAC_ByteIndex <= 3;
CompareRegister_en <= In_Valid;
DestinationMAC_en <= In_Valid;
if (In_Valid = '1') then
In_Ack_i <= '1';
if (Is_EOF = '0') then
NextState <= ST_DEST_MAC_3;
else
NextState <= ST_IDLE;
end if;
end if;
when ST_DEST_MAC_3 =>
MAC_ByteIndex <= 2;
CompareRegister_en <= In_Valid;
DestinationMAC_en <= In_Valid;
if (In_Valid = '1') then
In_Ack_i <= '1';
if (Is_EOF = '0') then
NextState <= ST_DEST_MAC_4;
else
NextState <= ST_IDLE;
end if;
end if;
when ST_DEST_MAC_4 =>
MAC_ByteIndex <= 1;
CompareRegister_en <= In_Valid;
DestinationMAC_en <= In_Valid;
if (In_Valid = '1') then
In_Ack_i <= '1';
if (Is_EOF = '0') then
NextState <= ST_DEST_MAC_5;
else
NextState <= ST_IDLE;
end if;
end if;
when ST_DEST_MAC_5 =>
MAC_ByteIndex <= 0;
CompareRegister_en <= In_Valid;
DestinationMAC_en <= In_Valid;
if (In_Valid = '1') then
In_Ack_i <= '1';
if (Is_EOF = '0') then
NextState <= ST_PAYLOAD_1;
else
NextState <= ST_IDLE;
end if;
end if;
when ST_PAYLOAD_1 =>
if (NoHits = '1') then
if (Is_EOF = '0') then
In_Ack_i <= '1';
NextState <= ST_DISCARD_FRAME;
else
NextState <= ST_IDLE;
end if;
else
In_Ack_i <= Out_Ack_i;
New_Valid_i <= In_Valid;
New_SOF_i <= '1';
if (Is_DataFlow = '1') then
if (Is_EOF = '0') then
NextState <= ST_PAYLOAD_N;
else
NextState <= ST_IDLE;
end if;
end if;
end if;
when ST_PAYLOAD_N =>
In_Ack_i <= Out_Ack_i;
New_Valid_i <= In_Valid;
if ((Is_DataFlow and Is_EOF) = '1') then
NextState <= ST_IDLE;
end if;
when ST_DISCARD_FRAME =>
In_Ack_i <= '1';
if ((Is_DataFlow and Is_EOF) = '1') then
NextState <= ST_IDLE;
end if;
end case;
end process;
gen0 : for i in 0 to PORTS - 1 generate
signal Hit : std_logic;
begin
Hit <= to_sl((In_Data and MAC_ADDRESSE_MASKS_I(i)(MAC_ByteIndex)) = (MAC_ADDRESSES_I(i)(MAC_ByteIndex) and MAC_ADDRESSE_MASKS_I(i)(MAC_ByteIndex)));
process(Clock)
begin
if rising_edge(Clock) then
if ((Reset or CompareRegister_rst) = '1') then
CompareRegister_d(i) <= '0';
elsif (CompareRegister_init = '1') then
CompareRegister_d(i) <= Hit;
elsif (CompareRegister_clear = '1') then
CompareRegister_d(i) <= '0';
elsif (CompareRegister_en = '1') then
CompareRegister_d(i) <= CompareRegister_d(i) and Hit;
end if;
end if;
end process;
end generate;
NoHits <= slv_nor(CompareRegister_d);
DestinationMAC_sel <= MAC_ByteIndex;
process(Clock)
begin
if rising_edge(Clock) then
if ((Reset or DestinationMAC_rst) = '1') then
DestinationMAC_d <= C_NET_MAC_ADDRESS_EMPTY;
elsif (DestinationMAC_en = '1') then
DestinationMAC_d(DestinationMAC_sel) <= In_Data;
end if;
end if;
end process;
Reader_Counter_rst <= Out_Meta_DestMACAddress_rst_i;
Reader_Counter_en <= Out_Meta_DestMACAddress_nxt_i;
process(Clock)
begin
if rising_edge(Clock) then
if ((Reset or Reader_Counter_rst) = '1') then
Reader_Counter_us <= to_unsigned(T_MAC_BYTEINDEX'high, Reader_Counter_us'length);
elsif (Reader_Counter_en = '1') then
Reader_Counter_us <= Reader_Counter_us - 1;
end if;
end if;
end process;
Out_Valid <= (Out_Valid'range => New_Valid_i) and CompareRegister_d;
Out_Data <= (Out_Data'range => In_Data);
Out_SOF <= (Out_SOF'range => New_SOF_i);
Out_EOF <= (Out_EOF'range => In_EOF);
Out_Ack_i <= slv_or(Out_Ack and CompareRegister_d);
Out_Meta_DestMACAddress_rst_i <= slv_or(Out_Meta_DestMACAddress_rst and CompareRegister_d);
Out_Meta_DestMACAddress_nxt_i <= slv_or(Out_Meta_DestMACAddress_nxt and CompareRegister_d);
Out_Meta_DestMACAddress_Data <= (Out_Data'range => DestinationMAC_d(to_index(Reader_Counter_us, DestinationMAC_d'high)));
end architecture;