------------------------------------------------------ -- encapsulate the data/ack/init for Opt Link -- -- Ver 1.00 -- -- Dominique Gigi Feb 2012 ------------------------------------------------------ -- -- -- -- ------------------------------------------------------ LIBRARY ieee; -- LIBRARY altera_mf; -- LIBRARY altera; USE ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; -- LIBRARY lpm; -- USE lpm.lpm_components.all; -- USE altera_mf.altera_mf_components.all; -- USE altera.altera_primitives_components.all; entity build_pckt_s is port ( reset_CLK : in std_logic; Greset_CLK : in std_logic; clock : in std_logic; start_pckt : in std_logic; -- trigger the packet send init_pckt : in std_logic; -- indicates that the packet is a Init packet ack_pckt : in std_logic; -- indicates that the packet is a acknoldge packet data_pckt : in std_logic; -- indicates that the packet is a data packet data_evt : in std_logic_vector(63 downto 0); -- data for data packet status : in std_logic_vector(63 downto 0); -- status data for acknowledge packet card_ID : in std_logic_vector(15 downto 0); -- CARD_ID Seq_nb : in std_logic_vector(30 downto 0); -- sequence number len_pckt : in std_logic_vector(15 downto 0); -- length of the packet (for data packet only) other 0 cmd : in std_logic_vector(63 downto 0); -- command bit for data packet only error_gen : in std_logic_vector(3 downto 0); rd_dt : out std_logic; -- request data for data packet only end_pckt : out std_logic; datao : out std_logic_vector(31 downto 0); --- data and K bit send to SERDES k_byte : out std_logic_vector( 3 downto 0); idle_state : out std_logic; status_state : out std_logic_vector(31 downto 0); cnt_pckt_snd : out std_logic_vector(31 downto 0) ); end build_pckt_s; architecture behavioral of build_pckt_s is type packet_type is ( idle, start_of_frame, seq_number, ID_len, status0, status1, command0, command1, data0, data1, CRC_end_frame, wait_crc, gap0, gap1, gap2, gap3 ); signal packet,packetNext:packet_type; component crc_gen_usb_32to16 PORT( clock : IN STD_LOGIC; reset : IN STD_LOGIC; data : IN STD_LOGIC_VECTOR(31 DOWNTO 0); data_valid : IN STD_LOGIC; eoc : IN STD_LOGIC; crc : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); crc_valid : OUT STD_LOGIC ); end component; signal cmp_crc : std_logic; signal val_crc : std_logic_vector(15 downto 0); signal crc_valid : std_logic; signal end_crc : std_logic; signal pckt_type : std_logic_vector(2 downto 0); signal seqnb_mem : std_logic_vector(31 downto 0); signal len_mem : std_logic_vector(15 downto 0); signal cmd_mem : std_logic_vector(63 downto 0); signal del_crc : std_logic_vector(2 downto 0); signal pipe_dta : std_logic_vector(31 downto 0); signal pipe_dtb : std_logic_vector(31 downto 0); signal pipe_dtc : std_logic_vector(31 downto 0); signal pipe_ka : std_logic_vector( 3 downto 0); signal pipe_kb : std_logic_vector( 3 downto 0); signal pipe_kc : std_logic_vector( 3 downto 0); signal nxt_dt : std_logic; signal wc_val : std_logic_vector(15 downto 0); signal mem_error :std_logic_vector(3 downto 0); signal mem_error_gen :std_logic_vector(3 downto 0); signal cnt_pck : std_logic_vector(31 downto 0); --******************************************************* --************** BEGIN ******************************** --******************************************************* begin --***************** error gen **************** -- 0 error on wc -- 1 error on crc -- 2 error on seq number -- 3 error on frame process(Greset_CLK,clock) begin if Greset_CLK = '0' then mem_error <= (others => '0'); mem_error_gen <= (others => '0'); elsif rising_edge(clock) then if error_gen /= "0000" then mem_error <= error_gen; elsif start_pckt = '1' and data_pckt = '1' then mem_error <= (others => '0'); end if; if start_pckt = '1' and data_pckt = '1' then mem_error_gen <= mem_error ; elsif del_crc(1) = '1' and data_pckt = '1' then mem_error_gen <= (others => '0'); end if; end if; end process; --******************************************** --Initiatlize some values -- Sequence number insert in the packet --length of the packet --bit ACK on (1) or OFF (0) --Packet type (001) INIT packet -- (010) data packet -- (100) ack packet process(reset_CLK,clock) begin if reset_CLK = '0' then pckt_type <= (others => '0'); elsif rising_edge(clock) then if start_pckt = '1' then pckt_type <= "000"; seqnb_mem(30 downto 0) <= Seq_nb; seqnb_mem(31) <= '0'; len_mem <= len_pckt; cmd_mem <= cmd; if init_pckt = '1' then pckt_type(0) <= '1'; seqnb_mem <= (others => '0'); len_mem <= (others => '0'); elsif ack_pckt = '1' then pckt_type(2) <= '1'; seqnb_mem(31) <= '1'; len_mem <= (others => '0'); elsif data_pckt = '1' then pckt_type(1) <= '1'; end if; end if; end if; end process; -- compute the CRC on fly (32 bit data => result in 16 bit) CRC_engine:crc_gen_usb_32to16 PORT MAP( clock => clock, reset => start_pckt, data => pipe_dta, data_valid => cmp_crc, eoc => end_crc, crc => val_crc, crc_valid => crc_valid ); --Clock for state machine state_clk:process(reset_CLK,clock) begin if reset_CLK = '0' then packet <= idle; elsif rising_edge(clock) then packet <= packetNext; end if; end process; state_step:process(packet,start_pckt,pckt_type,wc_val,crc_valid) begin packetNext <= packet; end_crc <= '0'; status_state(15 downto 0) <= (others => '0'); Case packet is -- wait for a packet to send when idle => if start_pckt = '1' then status_state(0) <= '1'; packetNext <= start_of_frame; end if; -- start the frame with a "START FRAME" when start_of_frame => status_state(1) <= '1'; packetNext <= seq_number; -- continu with the SEQUENCE number when seq_number => status_state(2) <= '1'; packetNext <= ID_len; -- add the identifier when ID_len => status_state(3) <= '1'; if pckt_type(0) = '1' then -- init packetNext <= CRC_end_frame; elsif pckt_type(1) = '1' then -- data packetNext <= command0; elsif pckt_type(2) = '1' then -- ack packetNext <= status0; end if; -- In case of a ACK include the STATUS low part when status0 => status_state(4) <= '1'; packetNext <= status1; -- In case of a ACK include the STATUS high part when status1 => status_state(5) <= '1'; packetNext <= CRC_end_frame; -- In case of a DATA include the COMMAND low part when command0 => status_state(6) <= '1'; packetNext <= command1; -- In case of a DATA include the COMMAND high part when command1 => status_state(7) <= '1'; packetNext <= data0; -- In case of a DATA include the DATA0 when data0 => status_state(8) <= '1'; packetNext <= data1; -- In case of a DATA include the DATAx until WC = 0 when data1 => status_state(9) <= '1'; if wc_val = x"0000" then packetNext <= CRC_end_frame; else packetNext <= data0; end if; -- conclude by the CRC when CRC_end_frame => status_state(10) <= '1'; end_crc <= '1'; packetNext <= wait_crc; -- the CRC will arrive in a deterministic number of clock -- wait is not the real case, but avoid to put multiple state between CEC_END_FRAME and WAIT_CRC when wait_crc => status_state(11) <= '1'; if crc_valid = '1' then packetNext <= gap0; end if; -- include some gap between packet like in ETHERNET when gap0 => status_state(12) <= '1'; packetNext <= gap1; when gap1 => status_state(13) <= '1'; packetNext <= gap2; when gap2 => status_state(14) <= '1'; packetNext <= gap3; when gap3 => status_state(15) <= '1'; packetNext <= idle; when others => packetNext <= idle; end case; end process; --generate the pulse to read data to include in the packet process(reset_CLK,clock) begin if reset_CLK = '0' then nxt_dt <= '0'; elsif rising_edge(clock) then nxt_dt <= '0'; if packet = data1 or packet = command1 then nxt_dt <= '1'; end if; end if; end process; rd_dt <= nxt_dt; -- count down starting from len_pckt (latch at the request "start_pckt") process(Greset_CLK,clock) begin if Greset_CLK = '0' then wc_val <= (others => '0'); elsif rising_edge(clock) then if start_pckt = '1' then wc_val <= len_pckt; elsif nxt_dt = '1' then wc_val <= std_logic_vector( TO_SIGNED ( TO_INTEGER ( UNSIGNED (wc_val) - 1),16) ); end if; end if; end process; -- MULTIPLEXER of values (SATRT_FRAME,Seq#,ID, DATA, Command,...) to create the packet process(reset_CLK,clock) begin if reset_CLK = '0' then pipe_ka <= "1111"; pipe_dta <= x"7CBCDC1C"; --IDLE STATE cmp_crc <= '0'; elsif rising_edge(clock) then pipe_ka <= "1111"; pipe_dta <= x"7CBCDC1C"; --IDLE STATE if packet = start_of_frame then pipe_ka <= "1101"; pipe_dta <= x"7CBC00FB"; --START FRAME pipe_dta(0) <= '1' xor mem_error_gen(3); -- error gen elsif packet = seq_number then cmp_crc <= '1'; pipe_ka <= "0000"; pipe_dta <= Seqnb_mem; pipe_dta(13) <= Seqnb_mem(13) xor mem_error_gen(2); -- error gen elsif packet = ID_len then pipe_ka <= "0000"; pipe_dta(31 downto 16) <= card_ID; pipe_dta(15 downto 0) <= len_mem; pipe_dta(5) <= len_mem(5) xor mem_error_gen(0); -- error gen elsif packet = status0 then pipe_ka <= "0000"; pipe_dta <= status(63 downto 32); elsif packet = status1 then pipe_ka <= "0000"; pipe_dta <= status(31 downto 0); elsif packet = command0 then pipe_ka <= "0000"; pipe_dta <= cmd_mem(63 downto 32); elsif packet = command1 then pipe_ka <= "0000"; pipe_dta <= cmd_mem(31 downto 0); elsif packet = data0 then pipe_ka <= "0000"; pipe_dta <= data_evt(63 downto 32); elsif packet = data1 then pipe_ka <= "0000"; pipe_dta <= data_evt(31 downto 0); elsif packet = CRC_end_frame then cmp_crc <= '0'; pipe_ka <= "0010"; pipe_dta(15 downto 0) <= x"FD00"; -- STOP FRAME end if; end if; end process; -- create a delay to iintroduce the CRC result process(clock) begin if rising_edge(clock) then del_crc(2 downto 1) <= del_crc(1 downto 0); del_crc(0) <= '0'; if packet = CRC_end_frame then del_crc(0) <= '1'; end if; end if; end process; --pipe packet value until the CRC is ready process(clock) begin if rising_edge(clock) then pipe_kc <= pipe_kb; pipe_kb <= pipe_ka; pipe_dtc <= pipe_dtb; pipe_dtb <= pipe_dta; if del_crc(1) = '1' then pipe_dtc(31 downto 16) <= val_crc; pipe_dtc(25) <= val_crc(9) xor mem_error_gen(1); -- error gen end if; end if; end process; -- generate the end of packet create process(reset_CLK,clock) begin if reset_CLK = '0' then end_pckt <= '0'; elsif rising_edge(clock) then end_pckt <= '0'; if end_crc = '1' and pckt_type(1) = '1' then end_pckt <= '1'; end if; end if; end process; process(Greset_CLK,clock) begin if Greset_CLK = '0' then cnt_pck <= (others => '0'); elsif rising_edge(clock) then if end_crc = '1' and pckt_type(1) = '1' then cnt_pck <= cnt_pck + '1'; end if; end if; end process; idle_state <= '1' when packet = idle else '0'; datao <= pipe_dtc; k_byte <= pipe_kc; cnt_pckt_snd <= cnt_pck; status_state(31 downto 16) <= (others => '0'); end behavioral;