-- -- Transition Radiation Detector -- -- MCM Control Unit - Configuration Network -- -- -- -- $Id$ -- -- Robin Gareus, Kirchhoff Institute for Physics, Heidelberg -- rgareus@kip.uni-heidelberg.de -- ------------------------------------------------------------ -- -- Bittiming Unit -- Reciever Part of DLL: generates a data and strobe signal -- out of the data signal from physical layer. -- -- After a startbit(1) is detected on the physical layer (data in) -- a state machine takes over flushing the input buffer, -- starting timers, initializing the destuffing unit,... -- States: -- state_reset : reset! introducing this state should reduce ammount of logic. -- idle : wait for startbit to arrive. reset and disable timer. -- recv_init : wait for startbit to end, initialize destuffing unit. -- : and flush the input-buffer. -- recv_data : wait for (next) databit to be recieved. (wait for timer event) -- recv_timerst : restart timer, since databit on wire has changed. -- recv_strobe : timer event. -- : strobe data through destuffing unit to input-buffer. -- finish_init : reset timer. -- finish_wait : wait for timer-event. There has to be at least 1/2 bitlength -- : time to separate frames. -- : maybe we should increase this time, since this is the -- : minimum time of data beeing held in the input-buffer. -- -- Generics: -- timing_count_range: This defines the speed of trasmission. -- Set the number of internal clocks to count -- after recieving a bit until the -- next bit will arrive. -- value must be > 2! (include the 0!) -- if set to 3, the network speed is 1/4 of -- the internal clock frequency. -- -- timing_recv_on : specifiy an timing offset. -- when detecting a signal-edge of the databit on the wire -- the counter is restarted. -- the data that is buffered, is the data read -- from the wire (1 + 'timing_recv_on') internal clocks -- after the timer restart. -- needs to be < ('timing_count_range'-2) -- -- stuff_length : specifies how many identical bits can be recieved -- before removing a stuff bit. -- this is forwarded to the destuffing unit -------------------------------------------------- -- standard includes, library definitions. -------------------------------------------------- library ieee,work; use ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.std_logic_unsigned.all; use work.mcm_nw_timer; use work.mcm_nw_destuffing; -------------------------------------------------- -- ENTITY -------------------------------------------------- entity mcm_nw_bittiming is generic ( timing_count_range : integer := 7; timing_recv_on : integer := 2; stuff_length : integer := 4; sync_len : integer := 7; sync_bits : integer := 2 ); port( -- Signals from phyiscal layer d_fr_pl : in std_logic ; -- Signals to/from inputbuffer data_out : out std_logic; -- data to be strobed strobe_out : out std_logic; -- write enable. buffer_full : in std_logic; -- go to idle state buffer_flush_n : out std_logic; -- clear buffer. reset_n : in std_logic; clk : in std_logic ); end mcm_nw_bittiming; -------------------------------------------------- -- ARCHITECTURE -------------------------------------------------- architecture structural of mcm_nw_bittiming is -------------------------------------------------- -- internal signals -------------------------------------------------- subtype state_type is std_logic_vector(3 downto 0); constant state_reset : state_type := "0000"; constant idle : state_type := "0001"; constant recv_init : state_type := "0010"; constant recv_data : state_type := "0011"; constant recv_timerst : state_type := "0100"; constant recv_strobe : state_type := "0101"; constant finish_init : state_type := "0110"; constant finish_wait : state_type := "0111"; constant recv_strtme : state_type := "1000"; SIGNAL current_state,next_state : state_type; SIGNAL d_buff : std_logic; --internal data buffer SIGNAL time_in_reset_n,time_in_event,time_in_enable,time_in_hotreset_n,time_in_twofwd_n : std_logic; -- timer. SIGNAL ds_reset_n,ds_err,s_to_ds,d_to_ds : std_logic; -- destuffing. SIGNAL sync_counter : std_logic_vector(sync_bits downto 0); -- destuffing. SIGNAL sync_en,sync_debug : std_logic; -------------------------------------------------- -- components -------------------------------------------------- COMPONENT hamm_reg generic(Nbits : Integer := 4; Init_value : Integer := 0); port (clk, rst_n : in std_logic; data_in : in std_logic_vector(Nbits-1 downto 0); data_out : out std_logic_vector(Nbits-1 downto 0) ); END COMPONENT; COMPONENT mcm_nw_timer generic (count_range,event_on : integer ); port( clk,enable,reset_n,hotreset_n,twofwd_n : IN std_logic; event,event_async : OUT std_logic ); END COMPONENT; COMPONENT mcm_nw_destuffing generic ( stuff_length : integer := 4); port( data_in : in std_logic; strobe_in : in std_logic; data_out : out std_logic; strobe_out : out std_logic; stuff_err : out std_logic; stuff_reset_n : in std_logic; clk : in std_logic ); END COMPONENT; -------------------------------------------------- -- port maps -------------------------------------------------- begin timer_in: mcm_nw_timer generic map( count_range => timing_count_range, event_on => timing_recv_on) port map ( reset_n => time_in_reset_n, hotreset_n => time_in_hotreset_n, twofwd_n => time_in_twofwd_n, enable => time_in_enable, clk => clk, event_async => time_in_event -- in ); destuff_in: mcm_nw_destuffing generic map( stuff_length => stuff_length ) port map ( clk => clk, strobe_in => s_to_ds, data_in => d_to_ds, stuff_reset_n => ds_reset_n, strobe_out => strobe_out, data_out => data_out, stuff_err => ds_err ); --ds_err <= '0'; --data_out <= d_to_ds; --strobe_out <= s_to_ds; d_to_ds<= d_fr_pl; -------------------------------------------------- -- processes -------------------------------------------------- -- calculate next state of the state machine: nextstate: process ( current_state, time_in_event, d_fr_pl, ds_err, buffer_full, d_buff, sync_en ) begin next_state <= current_state; case current_state is when state_reset => next_state <= idle; when idle => if ( d_fr_pl = '1') then next_state <= recv_init; end if; when recv_init => if ( time_in_event = '1') then next_state <= recv_strobe; -- if ( time_in_event = '1' and timing_recv_on = timing_count_range) then next_state <= recv_strobe; -- elsif ( time_in_event = '1') then next_state <= recv_data; -- if ( time_in_event = '1') then next_state <= recv_data; ---- elsif ( d_fr_pl = '0') then next_state <= recv_timerst; end if; when recv_data => if ( ds_err = '1' or buffer_full = '1') then next_state <= finish_init; -- -- elsif ( d_fr_pl = not d_buff and time_in_event = '1' and sync_en = '1') then next_state <= recv_strtme; elsif ( time_in_event = '1') then next_state <= recv_strobe; -- -- ---- elsif ( d_fr_pl = not d_buff and sync_en = '1') then next_state <= recv_timerst; elsif ( d_fr_pl = not d_buff and sync_en = '1') then next_state <= recv_strtme; -- end if; when recv_strobe => if ( ds_err = '1' or buffer_full = '1') then next_state <= finish_init; ---- elsif ( d_fr_pl = not d_buff and sync_en = '1') then next_state <= recv_timerst; elsif ( d_fr_pl = not d_buff and sync_en = '1') then next_state <= recv_timerst; -- -- elsif ( time_in_event = '1' and sync_en = '1') then next_state <= recv_strobe; -- else next_state <= recv_data; end if; when recv_strtme => if ( ds_err = '1' or buffer_full = '1') then next_state <= finish_init; else next_state <= recv_data; end if; when recv_timerst => if ( ds_err = '1' or buffer_full = '1') then next_state <= finish_init; -- -- elsif ( time_in_event = '1') then next_state <= recv_strobe; -- else next_state <= recv_data; end if; when finish_init => next_state <= finish_wait; when finish_wait => if ( time_in_event = '1') then next_state <= idle; end if; when OTHERS => next_state <= idle; -- THIS SHOULD NEVER HAPPEN!! end case; end process nextstate; -- state machine: enter next state. and buffer data pc: process (clk,reset_n) begin if reset_n = '0' then d_buff <= '-'; elsif ( clk'event and clk = '1') then d_buff <= d_fr_pl; case current_state is when state_reset => sync_counter <= (others => '0'); when recv_init => sync_counter <= (others => '0'); when recv_strobe => if (sync_counter > 0) then sync_counter<=sync_counter-1; end if; when recv_strtme => sync_counter <= std_logic_vector(conv_unsigned(sync_len,(sync_bits+1)) ); when recv_timerst => sync_counter <= std_logic_vector(conv_unsigned(sync_len,(sync_bits+1)) ); when OTHERS => sync_counter <= sync_counter; end case; end if; end process pc; h1: hamm_reg generic map(Nbits => 4, Init_value => 0) port map ( clk => clk, rst_n => reset_n, data_in => next_state, data_out => current_state); -- set sync enable sync_en <= '1' WHEN (sync_counter = 0 ) ELSE '0'; sync_debug <= '1' WHEN ( d_fr_pl = not d_buff ) ELSE '0'; -- set output values according to current_state. setoutput: process(current_state,d_buff) begin time_in_enable <= '0'; time_in_reset_n <= '1'; time_in_hotreset_n <= '1'; time_in_twofwd_n <= '1'; ds_reset_n <= '1'; s_to_ds <= '0'; buffer_flush_n <= '1'; case current_state is when state_reset => time_in_reset_n <= '0'; ds_reset_n <= '0'; buffer_flush_n <= '0'; when idle => -- time_in_reset_n <= '0'; time_in_hotreset_n <= '0'; when recv_init => time_in_enable <= '1'; ds_reset_n <= '0'; buffer_flush_n <= '0'; when recv_data => time_in_enable <= '1'; when recv_strobe => time_in_enable <= '1'; s_to_ds <= '1'; when recv_timerst => time_in_enable <= '0'; -- time_in_hotreset_n <= '0'; -- time_in_twofwd_n <= '0'; when finish_init => time_in_enable <= '1'; time_in_hotreset_n <= '0'; when finish_wait => time_in_enable <= '1'; when recv_strtme => time_in_enable <= '1'; s_to_ds <= '1'; -- time_in_reset_n <= '0'; time_in_twofwd_n <= '0'; when OTHERS => NULL; end case; end process setoutput; end structural; -------------------------------------------------- -- CONFIGURATION -------------------------------------------------- -- synopsys translate_off CONFIGURATION mcm_nw_bittiming_CFG of mcm_nw_bittiming is for structural for ALL : mcm_nw_timer use configuration WORK.mcm_nw_timer_CFG; end for; for ALL : mcm_nw_destuffing use configuration WORK.mcm_nw_destuffing_CFG; end for; end for; end mcm_nw_bittiming_CFG; -- synopsys translate_on