-- -- Network Packet Formatter -- -- adds headers and sorts out data width problems -- to get data into locallink fifo -- -- Mods -- 2011-06-30 Added defaults data_o=0x2468 - this should become the CRC for now library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library utils; use utils.pkg_types.all; library hsio; use hsio.pkg_core_globals.all; entity net_tx_pktfmt16 is port( --alt_dest_type_en_i : in std_logic; --*** alt_dest_mac_en_i : in std_logic; --*** mac_alt_dest_i : in std_logic_vector (47 downto 0); -- input interface data_i : in std_logic_vector (15 downto 0); sof_i : in std_logic; eof_i : in std_logic; dst_rdy_o : out std_logic; src_rdy_i : in std_logic; --data_length_i : in std_logic_vector (15 downto 0); -- HSIO length field mac_dest_i : in std_logic_vector (47 downto 0); mac_source_i : in std_logic_vector (47 downto 0); -- net client side (output) interface ll_data_o : out std_logic_vector (15 downto 0); --(7 downto 0); -- Erdem ll_sof_o : out std_logic; ll_eof_o : out std_logic; ll_dst_rdy_i : in std_logic; ll_src_rdy_o : out std_logic; clk : in std_logic; rst : in std_logic ); -- Declarations end net_tx_pktfmt16 ; architecture rtl of net_tx_pktfmt16 is signal pkt_header : slv16_array(9 downto 0); -- should be 19, but sim eeerg. signal bcount : integer range 0 to 31; -- 63 -- Erdem signal bcount_en : std_logic; signal bcount_clr : std_logic; signal bcount_inc : std_logic; signal data_len : std_logic_vector(15 downto 0); type states is (HeaderSOF, HeaderOC, Header2, OCData0, OCData1, OCData2, Payload, AddCRC, PadEnd, Idle ); signal state, nstate : states; signal ll_src_rdy : std_logic; signal ll_sof : std_logic; signal ll_eof : std_logic; signal ll_data : slv16; signal net_seq_id : slv16; signal dbg_state_change : std_logic; signal oc_store : slv16_array(3 downto 0); -- should be 2, but sim eeerg. signal oc_store_offs10 : slv16_array(13 downto 10); signal oc_store_en : std_logic; signal opcodepl : slv16; signal net_seq_id_inc : std_logic; signal crc : slv16; --*** signal ad_mac_en : std_logic; --signal ad_type_en : std_logic; --signal ad_opcode_valid : std_logic; signal rx_oc_port : slv4; -- polynomial: (0 5 12 16) -- data width: 16 function CRC16_D16 (Data : std_logic_vector(15 downto 0); CRC : std_logic_vector(15 downto 0)) return std_logic_vector is variable D : std_logic_vector(15 downto 0); variable C : std_logic_vector(15 downto 0); variable NewCRC : std_logic_vector(15 downto 0); begin D := Data; C := CRC; NewCRC(0) := D(12) xor D(11) xor D(8) xor D(4) xor D(0) xor C(0) xor C(4) xor C(8) xor C(11) xor C(12); NewCRC(1) := D(13) xor D(12) xor D(9) xor D(5) xor D(1) xor C(1) xor C(5) xor C(9) xor C(12) xor C(13); NewCRC(2) := D(14) xor D(13) xor D(10) xor D(6) xor D(2) xor C(2) xor C(6) xor C(10) xor C(13) xor C(14); NewCRC(3) := D(15) xor D(14) xor D(11) xor D(7) xor D(3) xor C(3) xor C(7) xor C(11) xor C(14) xor C(15); NewCRC(4) := D(15) xor D(12) xor D(8) xor D(4) xor C(4) xor C(8) xor C(12) xor C(15); NewCRC(5) := D(13) xor D(12) xor D(11) xor D(9) xor D(8) xor D(5) xor D(4) xor D(0) xor C(0) xor C(4) xor C(5) xor C(8) xor C(9) xor C(11) xor C(12) xor C(13); NewCRC(6) := D(14) xor D(13) xor D(12) xor D(10) xor D(9) xor D(6) xor D(5) xor D(1) xor C(1) xor C(5) xor C(6) xor C(9) xor C(10) xor C(12) xor C(13) xor C(14); NewCRC(7) := D(15) xor D(14) xor D(13) xor D(11) xor D(10) xor D(7) xor D(6) xor D(2) xor C(2) xor C(6) xor C(7) xor C(10) xor C(11) xor C(13) xor C(14) xor C(15); NewCRC(8) := D(15) xor D(14) xor D(12) xor D(11) xor D(8) xor D(7) xor D(3) xor C(3) xor C(7) xor C(8) xor C(11) xor C(12) xor C(14) xor C(15); NewCRC(9) := D(15) xor D(13) xor D(12) xor D(9) xor D(8) xor D(4) xor C(4) xor C(8) xor C(9) xor C(12) xor C(13) xor C(15); NewCRC(10) := D(14) xor D(13) xor D(10) xor D(9) xor D(5) xor C(5) xor C(9) xor C(10) xor C(13) xor C(14); NewCRC(11) := D(15) xor D(14) xor D(11) xor D(10) xor D(6) xor C(6) xor C(10) xor C(11) xor C(14) xor C(15); NewCRC(12) := D(15) xor D(8) xor D(7) xor D(4) xor D(0) xor C(0) xor C(4) xor C(7) xor C(8) xor C(15); NewCRC(13) := D(9) xor D(8) xor D(5) xor D(1) xor C(1) xor C(5) xor C(8) xor C(9); NewCRC(14) := D(10) xor D(9) xor D(6) xor D(2) xor C(2) xor C(6) xor C(9) xor C(10); NewCRC(15) := D(11) xor D(10) xor D(7) xor D(3) xor C(3) xor C(7) xor C(10) xor C(11); return NewCRC; end CRC16_D16; begin prc_clk_ll_out : process (clk) begin if rising_edge(clk) then if (ll_dst_rdy_i = '1') then ll_src_rdy_o <= ll_src_rdy; ll_sof_o <= ll_sof; ll_eof_o <= ll_eof; ll_data_o <= ll_data; -- ll_data(7 downto 0) & ll_data (15 downto 8); -- Erdem --Byte swap end if; end if; end process; -- dst_rdy_o <= dst_rdy_out; -- Destination MAC pkt_header(0) <= mac_dest_i(3*16-1 downto 2*16); pkt_header(1) <= mac_dest_i(2*16-1 downto 1*16); pkt_header(2) <= mac_dest_i(1*16-1 downto 0*16); --***pkt_header(0) <= mac_dest_i(3*16-1 downto 2*16) when (ad_mac_en = '0') else mac_alt_dest_i(3*16-1 downto 2*16); --***pkt_header(1) <= mac_dest_i(2*16-1 downto 1*16) when (ad_mac_en = '0') else mac_alt_dest_i(2*16-1 downto 1*16); --***pkt_header(2) <= mac_dest_i(1*16-1 downto 0*16) when (ad_mac_en = '0') else mac_alt_dest_i(1*16-1 downto 0*16); -- Source MAC pkt_header(3) <= mac_source_i(3*16-1 downto 2*16); pkt_header(4) <= mac_source_i(2*16-1 downto 1*16); pkt_header(5) <= mac_source_i(1*16-1 downto 0*16); -- Type (hijacked by HSIO Magic Number) 0x8765) --pkt_header(6) <= x"8765"; -- Erdem --pkt_header(6) <= x"8765" when (ad_type_en = '0') else x"8766"; -- routing only works if using type lsn >7 pkt_header(6) <= x"8765" when (rx_oc_port = x"0") else (x"876" & '1' & rx_oc_port(2 downto 0)); -- HSIO sequence num pkt_header(7) <= net_seq_id(15 downto 0); --data_seqnum_i(15 downto 8); -- HSIO length field data_len <= (oc_store(2) + 16); pkt_header(8) <= data_len(15 downto 0); -- HSIO opcode count field -- always 1 for readout pkt_header(9) <= x"0001"; -- Alternative destination for packets stuff ------------------------------------------------- -- When enabled packets from the I2C opcode will be sent to a different MAC and/or Type --ad_type_en <= alt_dest_type_en_i and ad_opcode_valid; --***ad_mac_en <= alt_dest_mac_en_i and alt_dest_opcode; --ad_opcode_valid <= '1' when (oc_store(0)(15 downto 4) = x"008") else '0'; --==--==--==--==--==--==--==--==--==--==--==--==--==--==--== --== -- SM Clocked --==--==--==--==--==--==--==--==--==--==--==--==--==--==--== --== prc_sm_clocked : process(clk) begin if rising_edge(clk) then if (rst = '1') then state <= Idle; else state <= nstate; end if; end if; end process; -- SM Async ------------------------------------------------------- prc_sm_async : process (state, src_rdy_i, sof_i, eof_i, ll_dst_rdy_i, bcount, pkt_header, data_i, crc, oc_store) begin --defaults nstate <= Idle; ll_sof <= '0'; ll_eof <= '0'; ll_src_rdy <= '1'; dst_rdy_o <= '0'; -- ll_dst_rdy_i; bcount_clr <= '0'; bcount_en <= '1'; ll_data <= x"0000"; dbg_state_change <= '0'; oc_store_en <= '0'; net_seq_id_inc <= '0'; bcount_inc <= '0'; case state is when Idle => nstate <= Idle; dst_rdy_o <= '1'; bcount_clr <= '1'; ll_src_rdy <= '0'; if (sof_i = '1') then --ll_src_rdy <= '1'; -- xil ll ignores sof, srcrdy must be THE START dst_rdy_o <= '0'; nstate <= HeaderSOF; end if; -- Send Header and store incoming opcode header --------------------------------------------------------------- when HeaderSOF => nstate <= HeaderSOF; ll_sof <= '1'; ll_data <= pkt_header(bcount); oc_store_en <= '1'; if (ll_dst_rdy_i = '1') then dst_rdy_o <= '1'; bcount_inc <= '1'; nstate <= HeaderOC; end if; when HeaderOC => -- preload opcode, seq, size nstate <= HeaderOC; ll_data <= pkt_header(bcount); -- Erdem oc_store_en <= '1'; if (ll_dst_rdy_i = '1') then dst_rdy_o <= '1'; bcount_inc <= '1'; if (bcount = 2) then -- Erdem --if (bcount = 1) then nstate <= Header2; end if; end if; when Header2 => nstate <= Header2; ll_data <= pkt_header(bcount); if (ll_dst_rdy_i = '1') then bcount_inc <= '1'; --if (bcount = 19) then -- Erdem if (bcount = 9) then dbg_state_change <= '1'; nstate <= OCData0; end if; end if; --Send Stored Opcode Header ------------------------------------------------------------ when OCData0 => nstate <= OCData0; ll_data <= oc_store(0); if (ll_dst_rdy_i = '1') then bcount_inc <= '1'; nstate <= OCData1; end if; when OCData1 => nstate <= OCData1; ll_data <= oc_store(1); if (ll_dst_rdy_i = '1') then bcount_inc <= '1'; nstate <= OCData2; end if; when OCData2 => nstate <= OCData2; ll_data <= oc_store(2); if (ll_dst_rdy_i = '1') then bcount_inc <= '1'; nstate <= Payload; end if; --Forward data ----------------------------------------------- when Payload => nstate <= Payload; ll_data <= data_i; if (ll_dst_rdy_i = '1') then dst_rdy_o <= '1'; -- Erdem bcount_inc <= '1'; if (eof_i = '1') then -- Erdem nstate <= AddCRC; end if; end if; when AddCRC => nstate <= AddCRC; ll_data <= crc; if (ll_dst_rdy_i = '1') then bcount_inc <= '1'; if (bcount > 30) then net_seq_id_inc <= '1'; nstate <= Idle; ll_eof <= '1'; else nstate <= PadEnd; end if; end if; when PadEnd => nstate <= PadEnd; if (ll_dst_rdy_i = '1') then bcount_inc <= '1'; if (bcount > 30) then -- min-packet size is 60 net_seq_id_inc <= '1'; nstate <= Idle; ll_eof <= '1'; end if; end if; end case; end process; crc_gen : process (clk) begin if rising_edge(clk) then if state = IDLE then crc <= (others => '0'); else if (ll_dst_rdy_i = '1') then if bcount > 5 and bcount <= 9 then crc <= CRC16_D16 (pkt_header (bcount), crc); elsif bcount > 9 and bcount <= 12 then --crc <= CRC16_D16 (oc_store(bcount - 10), crc); -- matt don't like crc <= CRC16_D16 (oc_store_offs10(bcount), crc); -- inline maths ... elsif bcount > 12 then crc <= CRC16_D16 (data_i, crc); else crc <= crc; end if; end if; end if; end if; end process; prc_byte_counter : process (clk) begin if rising_edge(clk) then if (rst = '1') or (bcount_clr = '1') then bcount <= 0; else if (bcount_en = '1') and (bcount < 31) and (bcount_inc = '1') then bcount <= bcount + 1; end if; end if; end if; end process; prc_net_seq_id_counter : process (clk) begin if rising_edge(clk) then if (rst = '1') then net_seq_id <= x"0000"; else if (net_seq_id_inc = '1') then net_seq_id <= net_seq_id + '1'; end if; end if; end if; end process; -- *** kludged to re-insert missing part of the opcode stolen by matt for the -- port stuff opcodepl <= oc_get_opcodepl(data_i); prc_incoming_oc_store : process (clk) begin if rising_edge(clk) then if (oc_store_en = '1') then if (bcount = 0) then if (opcodepl(15 downto 12) = x"A") then oc_store(0) <= x"AA" & opcodepl(7 downto 0); else oc_store(0) <= opcodepl; end if; rx_oc_port <= oc_get_port(data_i); else oc_store(bcount) <= data_i; end if; end if; end if; end process; oc_store_offs10 <= oc_store; end architecture;