Финальная версия выглядит следующим образом.
Код
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity ip_header is
generic
(
-- ADD USER GENERICS BELOW THIS LINE ---------------
--USER generics added here
C_HEADER_LENGTH : integer := 272;
C_ETH_HEADER : std_logic_vector := X"0021856DBF4B001377AFCEC60800"; -- 14 байт
C_IP_HEADER : std_logic_vector := X"0500000000000000000000FF"; -- 12 байт
C_IP_ADDR_SRC : std_logic_vector := X"ac1e69bf";
C_IP_ADDR_DST : std_logic_vector := X"ac1e6964"
-- ADD USER GENERICS ABOVE THIS LINE ---------------
);
port
(
-- ADD USER PORTS BELOW THIS LINE ------------------
--USER ports added here
-- From rocket
WFF_WR_CLK_IN : in std_logic; -- По этой частоте происходит запись в компонент, в который пишется пакет с заголовком
WFF_DATA_IN : in std_logic_vector(0 to 31);
WFF_WR_REQ_IN : in std_logic;
-- From emac
WFF_FULL_IN : in std_logic;
-- From emac
RFF_WR_CLK_IN : in std_logic; -- По этой частоте происходит запись в компонент, в который пишется пакет без заголовка
RFF_DATA_IN : in std_logic_vector(0 to 31);
RFF_WR_REQ_IN : in std_logic;
-- To emac
WFF_DATA_OUT : out std_logic_vector(0 to 31);
WFF_WR_REQ_OUT : out std_logic;
-- To rocket
RFF_DATA_OUT : out std_logic_vector(0 to 31);
RFF_WR_REQ_OUT : out std_logic;
RFF_FULL_OUT : out std_logic;
-- ADD USER PORTS ABOVE THIS LINE ------------------
);
end entity ip_header;
------------------------------------------------------------------------------
-- Architecture section
------------------------------------------------------------------------------
architecture IMP of ip_header is
------------------------------------------------
-- User signals
------------------------------------------------
signal Header : std_logic_vector(0 to C_HEADER_LENGTH-1) := C_ETH_HEADER & C_IP_HEADER & C_IP_ADDR_SRC & C_IP_ADDR_DST;
signal Header_Copy : std_logic_vector(0 to 271);
signal header_wr : std_logic;
signal bytes35_cnt : std_logic_vector(0 to 34);
signal remove_cnt : std_logic_vector(0 to 5);
signal ip_addr_dst : std_logic_vector(0 to 31);
signal ip_src_wrong : std_logic;
--------------------------------------------------
-- Signals for C2R FIFO
--------------------------------------------------
signal IP2FIFO_C2R_RdReq : std_logic;
signal IP2FIFO_C2R_WrReq : std_logic;
signal C2R_FIFO2IP_Data : std_logic_vector (0 to 31);
signal C2R_FIFO2IP_Empty : std_logic;
signal C2R_FIFO2IP_Full : std_logic;
signal C2R_FIFO2IP_RdAck : std_logic;
signal C2R_FIFO2IP_WrAck : std_logic;
signal write_packet : std_logic;
signal addr_cmp : boolean;
signal addr_cmp_cnt : boolean;
signal remove24 : boolean;
signal remove33 : std_logic;
signal remove34 : std_logic;
begin
FIFO_INST_C2R : entity ip_header_v1_00_a.fifo_generator_v4_3
port map
(
din => WFF_DATA_IN,
rd_clk => WFF_WR_CLK_IN,
rd_en => IP2FIFO_C2R_RdReq,
rst => ipif_Bus2IP_Reset,
wr_clk => WFF_WR_CLK_IN,
wr_en => WFF_WR_REQ_IN,
almost_empty => open,
almost_full => open,
dout => C2R_FIFO2IP_Data,
empty => C2R_FIFO2IP_Empty,
full => C2R_FIFO2IP_Full,
valid => C2R_FIFO2IP_RdAck,
rd_data_count => open,
wr_ack => C2R_FIFO2IP_WrAck,
wr_data_count => open );
RFF_FULL_OUT <= C2R_FIFO2IP_Full;
IP2FIFO_C2R_RdReq <= ( not ( C2R_FIFO2IP_Empty ) and not ( WFF_FULL_IN ) and not ( C2R_FIFO2IP_Data(20) ) ) or bytes35_cnt(34);
header_wr <= C2R_FIFO2IP_Data(20) and ( not bytes35_cnt(34) );
WFF_WR_REQ_OUT <= ( C2R_FIFO2IP_RdAck and not ( C2R_FIFO2IP_Data(20) ) ) or header_wr or bytes35_cnt(34);
process( WFF_WR_CLK_IN )
begin
if ( WFF_WR_CLK_IN'event and WFF_WR_CLK_IN='1' ) then
if ( header_wr='1' ) then
Header_Copy <= Header_Copy(8 to 271) & Header_Copy(0 to 7);
bytes35_cnt <= '0' & bytes35_cnt(0 to 33);
else
Header_Copy <= Header;
bytes35_cnt <= "100" & X"00000000";
end if;
end if;
end process;
WFF_DATA_OUT <= C2R_FIFO2IP_Data when ( C2R_FIFO2IP_RdAck and ( not C2R_FIFO2IP_Data(20) ) ) = '1' else
X"000008" & Header_Copy ( 0 to 7 ) when ( header_wr and bytes35_cnt(0) ) = '1' else
X"000000" & Header_Copy ( 0 to 7 ) when ( header_wr ) = '1' else
X"000000" & C2R_FIFO2IP_Data(24 to 31) when ( bytes35_cnt(34) = '1' ) else
X"00000000";
RFF_DATA_OUT <= X"000008" & RFF_DATA_IN(24 to 31) when ( remove33 ) = '1' else
X"00000" & RFF_DATA_IN(20 to 31) when ( write_packet ) = '1' else
X"00000000";
RFF_WR_REQ_OUT <= ( write_packet or remove33 ) and ( not ip_src_wrong );
write_packet <= ( write_packet or remove34 ) and ( not RFF_DATA_IN(20) );
process( RFF_WR_CLK_IN )
begin
if ( RFF_WR_CLK_IN='1' and RFF_WR_CLK_IN'event ) then
if ( RFF_DATA_IN(20)='1' and RFF_WR_REQ_IN='1' ) then
remove_cnt <= (others => '0');
elsif ( RFF_WR_REQ_IN='1' and remove_cnt < X"24" ) then
remove_cnt <= remove_cnt + '1';
else
remove_cnt <= remove_cnt;
end if;
if ( addr_cmp_cnt ) then
ip_addr_dst <= ip_addr_dst(8 to 31) & ip_addr_dst(0 to 7);
elsif ( remove24 ) then
ip_addr_dst <= C_IP_ADDR_DST;
else
ip_addr_dst <= ip_addr_dst;
end if;
if ( addr_cmp_cnt and addr_cmp ) then
ip_src_wrong <= '1';
elsif ( remove24 ) then
ip_src_wrong <= '0';
else
ip_src_wrong <= ip_src_wrong;
end if;
end if;
end process;
process ( RFF_DATA_IN, ip_addr_dst, remove_cnt )
begin
addr_cmp <= ip_addr_dst(0 to 7) /= RFF_DATA_IN(24 to 31);
addr_cmp_cnt <= ( ( remove_cnt = "011001" ) or ( remove_cnt = "011010" ) ) or ( ( remove_cnt = "011011" ) or ( remove_cnt = "011100" ) );
remove24 <= ( remove_cnt = "011000" );
end process;
remove33 <= '1' when ( remove_cnt = "100001" ) else '0';
remove34 <= '1' when ( remove_cnt = "100010" ) else '0';
end IMP;
Нелегко оказаться на верном пути, но куда труднее его пройти.
(с) Уилл Роджерс