-- 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]arp_BroadCast_Receiver is
generic (
ALLOWED_PROTOCOL_IPV4 : boolean := TRUE;
ALLOWED_PROTOCOL_IPV6 : boolean := FALSE
);
port (
Clock : in std_logic; --
Reset : in std_logic; --
RX_Valid : in std_logic;
RX_Data : in T_SLV_8;
RX_SOF : in std_logic;
RX_EOF : in std_logic;
RX_Ack : out std_logic;
RX_Meta_rst : out std_logic;
RX_Meta_SrcMACAddress_nxt : out std_logic;
RX_Meta_SrcMACAddress_Data : in T_SLV_8;
RX_Meta_DestMACAddress_nxt : out std_logic;
RX_Meta_DestMACAddress_Data : in T_SLV_8;
Clear : in std_logic;
Error : out std_logic;
RequestReceived : out std_logic;
Address_rst : in std_logic;
SenderMACAddress_nxt : in std_logic;
SenderMACAddress_Data : out T_SLV_8;
SenderIPAddress_nxt : in std_logic;
SenderIPAddress_Data : out T_SLV_8;
TargetIPAddress_nxt : in std_logic;
TargetIPAddress_Data : out T_SLV_8
);
end entity;
architecture [docs]rtl of arp_BroadCast_Receiver is
attribute FSM_ENCODING : string;
type T_STATE is (
ST_IDLE,
ST_RECEIVE_HARDWARE_type_1,
ST_RECEIVE_PROTOCOL_type_0, ST_RECEIVE_PROTOCOL_type_1,
ST_RECEIVE_HARDWARE_ADDRESS_LENGTH, ST_RECEIVE_PROTOCOL_ADDRESS_LENGTH,
ST_RECEIVE_OPERATION_0, ST_RECEIVE_OPERATION_1,
ST_RECEIVE_SENDER_MAC, ST_RECEIVE_SENDER_IP,
ST_RECEIVE_TARGET_MAC, ST_RECEIVE_TARGET_IP,
ST_DISCARD_ETHERNET_PADDING_BYTES,
ST_COMPLETE,
ST_DISCARD_FRAME, ST_ERROR
);
signal State : T_STATE := ST_IDLE;
signal NextState : T_STATE;
attribute FSM_ENCODING of State : signal is "gray"; --"speed1";
signal Is_SOF : std_logic;
signal Is_EOF : std_logic;
constant HARDWARE_ADDRESS_LENGTH : positive := 6; -- MAC -> 6 bytes
constant PROTOCOL_IPV4_ADDRESS_LENGTH : positive := 4; -- IPv4 -> 4 bytes
constant PROTOCOL_IPV6_ADDRESS_LENGTH : positive := 16; -- IPv6 -> 16 bytes
constant PROTOCOL_ADDRESS_LENGTH : positive := ite((ALLOWED_PROTOCOL_IPV6 = FALSE), PROTOCOL_IPV4_ADDRESS_LENGTH, PROTOCOL_IPV6_ADDRESS_LENGTH); -- IPv4 -> 4 bytes; IPv6 -> 16 bytes
subtype T_HARDWARE_ADDRESS_INDEX is natural range 0 to HARDWARE_ADDRESS_LENGTH - 1;
subtype T_PROTOCOL_ADDRESS_INDEX is natural range 0 to PROTOCOL_ADDRESS_LENGTH - 1;
signal IsIPv4_set : std_logic;
signal IsIPv4_r : std_logic := '0';
signal IsIPv6_set : std_logic;
signal IsIPv6_r : std_logic := '0';
constant WRITER_COUNTER_BITS : positive := log2ceilnz(imax(HARDWARE_ADDRESS_LENGTH, PROTOCOL_ADDRESS_LENGTH));
signal Writer_Counter_rst : std_logic;
signal Writer_Counter_en : std_logic;
signal Writer_Counter_us : unsigned(WRITER_COUNTER_BITS - 1 downto 0) := (others => '0');
signal Reader_SenderMAC_Counter_rst : std_logic;
signal Reader_SenderMAC_Counter_en : std_logic;
signal Reader_SenderMAC_Counter_us : unsigned(log2ceilnz(HARDWARE_ADDRESS_LENGTH) - 1 downto 0) := (others => '0');
signal Reader_SenderIP_Counter_rst : std_logic;
signal Reader_SenderIP_Counter_en : std_logic;
signal Reader_SenderIP_Counter_us : unsigned(log2ceilnz(PROTOCOL_ADDRESS_LENGTH) - 1 downto 0) := (others => '0');
signal Reader_TargetIP_Counter_rst : std_logic;
signal Reader_TargetIP_Counter_en : std_logic;
signal Reader_TargetIP_Counter_us : unsigned(log2ceilnz(PROTOCOL_ADDRESS_LENGTH) - 1 downto 0) := (others => '0');
-- signal SenderMACAddress_Data_rst : STD_LOGIC;
signal SenderHardwareAddress_en : std_logic;
signal SenderHardwareAddress_us : unsigned(log2ceilnz(HARDWARE_ADDRESS_LENGTH) - 1 downto 0);
signal SenderHardwareAddress_d : T_SLVV_8(HARDWARE_ADDRESS_LENGTH - 1 downto 0) := (others => (others => '0'));
-- signal SenderIPv4Address_Data_rst : STD_LOGIC;
signal SenderProtocolAddress_en : std_logic;
signal SenderProtocolAddress_us : unsigned(log2ceilnz(PROTOCOL_ADDRESS_LENGTH) - 1 downto 0);
signal SenderProtocolAddress_d : T_SLVV_8(PROTOCOL_ADDRESS_LENGTH - 1 downto 0) := (others => (others => '0'));
-- signal TargetIPv4Address_Data_rst : STD_LOGIC;
signal TargetProtocolAddress_en : std_logic;
signal TargetProtocolAddress_us : unsigned(log2ceilnz(PROTOCOL_ADDRESS_LENGTH) - 1 downto 0);
signal TargetProtocolAddress_d : T_SLVV_8(PROTOCOL_ADDRESS_LENGTH - 1 downto 0) := (others => (others => '0'));
begin
assert (ALLOWED_PROTOCOL_IPV4 or ALLOWED_PROTOCOL_IPV6) report "At least one protocol must be selected: IPv4, IPv6" severity FAILURE;
RX_Meta_rst <= '0';
RX_Meta_SrcMACAddress_nxt <= '0';
RX_Meta_DestMACAddress_nxt <= '0';
Is_SOF <= RX_Valid and RX_SOF;
Is_EOF <= RX_Valid and RX_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,
Clear,
RX_Valid, RX_Data, Is_SOF, Is_EOF,
IsIPv4_r, IsIPv6_r, Writer_Counter_us,
Address_rst,
SenderMACAddress_nxt, SenderIPAddress_nxt, TargetIPAddress_nxt)
begin
NextState <= State;
RX_Ack <= '0';
RequestReceived <= '0';
Error <= '0';
IsIPv4_set <= '0';
IsIPv6_set <= '0';
Writer_Counter_rst <= '0';
Writer_Counter_en <= '0';
Reader_SenderMAC_Counter_rst <= Clear or Address_rst;
Reader_SenderMAC_Counter_en <= SenderMACAddress_nxt;
SenderHardwareAddress_en <= '0';
SenderHardwareAddress_us <= Writer_Counter_us(SenderHardwareAddress_us'range);
Reader_SenderIP_Counter_rst <= Clear or Address_rst;
Reader_SenderIP_Counter_en <= SenderIPAddress_nxt;
SenderProtocolAddress_en <= '0';
SenderProtocolAddress_us <= Writer_Counter_us(SenderProtocolAddress_us'range);
Reader_TargetIP_Counter_rst <= Clear or Address_rst;
Reader_TargetIP_Counter_en <= TargetIPAddress_nxt;
TargetProtocolAddress_en <= '0';
TargetProtocolAddress_us <= Writer_Counter_us(TargetProtocolAddress_us'range);
case State is
when ST_IDLE =>
if (Is_SOF = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if (RX_Data = x"00") then
NextState <= ST_RECEIVE_HARDWARE_type_1;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_HARDWARE_type_1 =>
if (RX_Valid = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if (RX_Data = x"01") then
NextState <= ST_RECEIVE_PROTOCOL_type_0;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_PROTOCOL_type_0 =>
if (RX_Valid = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if ((ALLOWED_PROTOCOL_IPV4 = TRUE) and (RX_Data = x"08")) then
IsIPv4_set <= '1';
NextState <= ST_RECEIVE_PROTOCOL_type_1;
elsif ((ALLOWED_PROTOCOL_IPV6 = TRUE) and (RX_Data = x"86")) then
IsIPv6_set <= '1';
NextState <= ST_RECEIVE_PROTOCOL_type_1;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_PROTOCOL_type_1 =>
if (RX_Valid = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if ((IsIPv4_r = '1') and (RX_Data = x"00")) then
NextState <= ST_RECEIVE_HARDWARE_ADDRESS_LENGTH;
elsif ((IsIPv6_r = '1') and (RX_Data = x"66")) then
NextState <= ST_RECEIVE_HARDWARE_ADDRESS_LENGTH;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_HARDWARE_ADDRESS_LENGTH =>
if (RX_Valid = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if (RX_Data = x"06") then
NextState <= ST_RECEIVE_PROTOCOL_ADDRESS_LENGTH;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_PROTOCOL_ADDRESS_LENGTH =>
if (RX_Valid = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if ((IsIPv4_r = '1') and (RX_Data = x"04")) then
NextState <= ST_RECEIVE_OPERATION_0;
elsif ((IsIPv6_r = '1') and (RX_Data = x"10")) then
NextState <= ST_RECEIVE_OPERATION_0;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_OPERATION_0 =>
if (RX_Valid = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if (RX_Data = x"00") then
NextState <= ST_RECEIVE_OPERATION_1;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_OPERATION_1 =>
if (RX_Valid = '1') then
RX_Ack <= '1';
if (Is_EOF = '0') then
if (RX_Data = x"01") then
NextState <= ST_RECEIVE_SENDER_MAC;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_SENDER_MAC =>
if (RX_Valid = '1') then
RX_Ack <= '1';
Writer_Counter_en <= '1';
SenderHardwareAddress_en <= '1';
if (Is_EOF = '0') then
if (Writer_Counter_us = (HARDWARE_ADDRESS_LENGTH - 1)) then
Writer_Counter_rst <= '1';
NextState <= ST_RECEIVE_SENDER_IP;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_SENDER_IP =>
if (RX_Valid = '1') then
RX_Ack <= '1';
Writer_Counter_en <= '1';
SenderProtocolAddress_en <= '1';
if (Is_EOF = '0') then
if ((IsIPv4_r = '1') and (Writer_Counter_us = (PROTOCOL_IPV4_ADDRESS_LENGTH - 1))) then
Writer_Counter_rst <= '1';
NextState <= ST_RECEIVE_TARGET_MAC;
elsif ((IsIPv6_r = '1') and (Writer_Counter_us = (PROTOCOL_IPV6_ADDRESS_LENGTH - 1))) then
Writer_Counter_rst <= '1';
NextState <= ST_RECEIVE_TARGET_MAC;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_TARGET_MAC =>
if (RX_Valid = '1') then
RX_Ack <= '1';
Writer_Counter_en <= '1'; -- needed to count incoming bytes
if (Is_EOF = '0') then
if (RX_Data = x"00") then
if (Writer_Counter_us = (HARDWARE_ADDRESS_LENGTH - 1)) then
Writer_Counter_rst <= '1';
NextState <= ST_RECEIVE_TARGET_IP;
end if;
else
NextState <= ST_DISCARD_FRAME;
end if;
else
NextState <= ST_ERROR;
end if;
end if;
when ST_RECEIVE_TARGET_IP =>
if (RX_Valid = '1') then
RX_Ack <= '1';
Writer_Counter_en <= '1';
TargetProtocolAddress_en <= '1';
if (Is_EOF = '0') then
if ((IsIPv4_r = '1') and (Writer_Counter_us = (PROTOCOL_IPV4_ADDRESS_LENGTH - 1))) then
Writer_Counter_rst <= '1';
NextState <= ST_DISCARD_ETHERNET_PADDING_BYTES;
elsif ((IsIPv6_r = '1') and (Writer_Counter_us = (PROTOCOL_IPV6_ADDRESS_LENGTH - 1))) then
Writer_Counter_rst <= '1';
NextState <= ST_DISCARD_ETHERNET_PADDING_BYTES;
end if;
else
if ((IsIPv4_r = '1') and (Writer_Counter_us = (PROTOCOL_IPV4_ADDRESS_LENGTH - 1))) then
Writer_Counter_rst <= '1';
NextState <= ST_COMPLETE;
elsif ((IsIPv6_r = '1') and (Writer_Counter_us = (PROTOCOL_IPV6_ADDRESS_LENGTH - 1))) then
Writer_Counter_rst <= '1';
NextState <= ST_COMPLETE;
else
NextState <= ST_ERROR;
end if;
end if;
end if;
when ST_DISCARD_ETHERNET_PADDING_BYTES =>
RX_Ack <= '1';
if (Is_EOF = '1') then
NextState <= ST_COMPLETE;
end if;
when ST_COMPLETE =>
RequestReceived <= '1';
if (Clear = '1') then
NextState <= ST_IDLE;
end if;
when ST_DISCARD_FRAME =>
RX_Ack <= '1';
if (Is_EOF = '1') then
NextState <= ST_ERROR;
end if;
when ST_ERROR =>
Error <= '1';
if (Clear = '1') then
NextState <= ST_IDLE;
end if;
end case;
end process;
process(Clock)
begin
if rising_edge(Clock) then
if ((Reset or Clear) = '1') then
IsIPv4_r <= '0';
IsIPv6_r <= '0';
else
if (IsIPv4_set = '1') then
IsIPv4_r <= '1';
end if;
if (IsIPv6_set = '1') then
IsIPv6_r <= '1';
end if;
end if;
end if;
end process;
process(Clock)
begin
if rising_edge(Clock) then
if (Writer_Counter_rst = '1') then
Writer_Counter_us <= (others => '0');
elsif (Writer_Counter_en = '1') then
Writer_Counter_us <= Writer_Counter_us + 1;
end if;
if (Reader_SenderMAC_Counter_rst = '1') then
Reader_SenderMAC_Counter_us <= (others => '0');
elsif (Reader_SenderMAC_Counter_en = '1') then
Reader_SenderMAC_Counter_us <= Reader_SenderMAC_Counter_us + 1;
end if;
if (Reader_SenderIP_Counter_rst = '1') then
Reader_SenderIP_Counter_us <= (others => '0');
elsif (Reader_SenderIP_Counter_en = '1') then
Reader_SenderIP_Counter_us <= Reader_SenderIP_Counter_us + 1;
end if;
if (Reader_TargetIP_Counter_rst = '1') then
Reader_TargetIP_Counter_us <= (others => '0');
elsif (Reader_TargetIP_Counter_en = '1') then
Reader_TargetIP_Counter_us <= Reader_TargetIP_Counter_us + 1;
end if;
end if;
end process;
process(Clock)
begin
if rising_edge(Clock) then
if (SenderHardwareAddress_en = '1') then
SenderHardwareAddress_d(to_integer(SenderHardwareAddress_us)) <= RX_Data;
end if;
if (SenderProtocolAddress_en = '1') then
SenderProtocolAddress_d(to_integer(SenderProtocolAddress_us)) <= RX_Data;
end if;
if (TargetProtocolAddress_en = '1') then
TargetProtocolAddress_d(to_integer(TargetProtocolAddress_us)) <= RX_Data;
end if;
end if;
end process;
SenderMACAddress_Data <= SenderHardwareAddress_d(ite((not SIMULATION), to_integer(Reader_SenderMAC_Counter_us), imin(to_integer(Reader_SenderMAC_Counter_us), 5)));
SenderIPAddress_Data <= SenderProtocolAddress_d(ite((not SIMULATION), to_integer(Reader_SenderIP_Counter_us), imin(to_integer(Reader_SenderIP_Counter_us), 3)));
TargetIPAddress_Data <= TargetProtocolAddress_d(ite((not SIMULATION), to_integer(Reader_TargetIP_Counter_us), imin(to_integer(Reader_TargetIP_Counter_us), 3)));
end architecture;