-- -- Transition Radiation Detector -- -- MCM Control Unit - Configuration Network -- -- -- -- $Id: mcm_nw_nwsl.vhd,v 1.5 2002/10/18 00:41:22 rgareus Exp $ -- -- Robin Gareus, Kirchhoff Institute for Physics, Heidelberg -- rgareus@kip.uni-heidelberg.de -- ------------------------------------------------------------ -- -- Network Sub-Layer -- -- This part implements the network protocol. The Frame-Header is analyzed here -- If the frame is to be processed at this MCM a request to the upper layer is -- sent, and a reply generated. Else the frame is being forwarded. -- The hop counter is increased here. -- -- The ports/interfaces are described in detail in -- .../report_2/main.ps . There are short summaries in the header of -- the counterparts of this layer : mcm_nw_apl.vhd as well as in mcm_nw_dll.vhd -- -- -- The states are -- -- idle : no (new) data in input buffer to be processed. -- analyze_frame: decide how to handle frame (forward,drop,error,process) -- : this can't be done directly from idle-state since -- : we first have to increase the hop-counter and -- : have to be sure that this frame has not been -- : processed before (if the input-buffer has not changed -- : -> see also dirty-flag) -- process_frame: send request to application layer. wait for reply -- : reply is directly written to output-buffer -- forward_frame: forward frame to output-buffer -- send_init : initiate sending of the data in the output-buffer -- send_wait : wait until output-buffer is flushed. -- : FIXME: can't we go back to idle state directly? -- : i think this state was once needed when -- : the bridge functionality was still in NWL. mmh. -- send_err : This state is a queued error. Before we start -- : sending an error, we have to be sure that -- : a queued bridge-(re)set is executed. So wait until -- : a possibly queued bridge-command has finished. -- ready_to_send_err: wait until output-buffer becomed writeable -- : then write error-frame to buffer. -- send_err_pending : start sending, and wait until send starts. -- send_err_clear : wait until error frame sent out. -- : do not go into idle state before! -------------------------------------------------- -- standard includes, library definitions. -------------------------------------------------- library ieee,work; use ieee.std_logic_1164.all; use IEEE.std_logic_unsigned.all; -------------------------------------------------- -- ENTITY -------------------------------------------------- entity mcm_nw_nwsl is port( -- Signals from Data Link Layer (recv) d_fr_dll : in std_logic_vector(68 downto 0); s_fr_dll : in std_logic; -- strobe : d_fr_dll valid d_buffer_half : in std_logic; -- inbuf is almost full d_buf_err : in std_logic; -- recieved frame with invalid CRC -- Signals to Data Link Layer (send) d_buffer_ready : in std_logic; -- data may be written to buffer d_to_dll : out std_logic_vector(68 downto 0); -- send data d_we : out std_logic; -- store data in buffer d_initiate_send : out std_logic; -- start sending the buffered data -- Signals to Application Layer request : out std_logic_vector(52 downto 0); request_valid : out std_logic; -- Signals from Application Layer reply : in std_logic_vector(52 downto 0); reply_valid : in std_logic; altered_frame : in std_logic; -- Signal for bridge-synchrinsation wait_for_bridge : in std_logic; -- do not start sending. bridge : in std_logic; -- current bridge state reset_n : in std_logic; clk_buf_dis : out std_logic; clk : in std_logic ); end mcm_nw_nwsl; -------------------------------------------------- -- ARCHITECTURE -------------------------------------------------- architecture structural of mcm_nw_nwsl is -------------------------------------------------- -- internal signals -------------------------------------------------- subtype state_type is std_logic_vector(3 downto 0); constant idle : state_type := "0000"; constant analyze_frame : state_type := "0001"; constant process_frame : state_type := "0010"; constant forward_frame : state_type := "0011"; constant send_init : state_type := "0100"; constant send_wait : state_type := "0101"; constant send_err : state_type := "0110"; constant ready_to_send_err : state_type := "0111"; constant send_err_pending : state_type := "1000"; constant send_err_clear : state_type := "1001"; SIGNAL current_state,next_state : state_type; SIGNAL process_buffer : std_logic_vector(52 downto 0); SIGNAL forward_buffer : std_logic_vector(68 downto 0); SIGNAL send_buffer : std_logic_vector(68 downto 0); SIGNAL address : std_logic_vector(6 downto 0); SIGNAL src_dst : std_logic; SIGNAL hopcounter : std_logic_vector(7 downto 0); SIGNAL b_dirty : std_logic; SIGNAL msb,msb_inc,lsb_inc :std_logic_vector(7 downto 0); -------------------------------------------------- -- components -------------------------------------------------- COMPONENT hamm_reg is 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; -------------------------------------------------- -- processes -------------------------------------------------- begin -- This process keeps track if data has already been processed, changed,... -- buffer is dirty : data in buffer has not been (started beeing) processed. checkdirty: process(clk,reset_n) begin if (reset_n = '0') then b_dirty <='1'; clk_buf_dis <= '1'; elsif (clk'event and clk='1') then if ( b_dirty = '0' and ( d_buf_err or s_fr_dll) = '0' ) then b_dirty <= '1'; elsif ( b_dirty = '1' and ( d_buf_err or s_fr_dll) = '1' and (current_state = analyze_frame) ) then b_dirty <= '0'; end if; if current_state = idle then clk_buf_dis <= '1'; else clk_buf_dis <= '0'; end if; end if; end process checkdirty; -- calculate the next state of the state-machine nextstate: process ( current_state, s_fr_dll, d_buf_err, d_buffer_half, d_buffer_ready, reply_valid, src_dst, address, hopcounter, wait_for_bridge, b_dirty ) begin next_state <= current_state; case current_state is when idle => if ( ( d_buf_err or s_fr_dll ) = '1' and b_dirty = '1' and wait_for_bridge = '0' ) then next_state <= analyze_frame; end if; when analyze_frame => if ( d_buf_err = '1' ) then next_state <= send_err; else if (hopcounter(7 downto 0) = "00000000") then next_state <= idle; -- looped frame, drop it else if ( src_dst = '1' and ( address = "1111111" or -- broadcast. address(6 downto 0) = hopcounter(7 downto 1) ) ) then next_state <= process_frame; else next_state <= forward_frame; end if; end if; end if; when process_frame => if ( s_fr_dll = '0' ) then next_state <= send_err; elsif ( reply_valid = '1' and d_buffer_ready = '1' ) then next_state <= send_init; end if; when forward_frame => if ( s_fr_dll = '0' ) then next_state <= send_err; elsif ( d_buffer_ready = '1') then next_state <= send_init; end if; when send_init => if ( s_fr_dll = '0' and d_buffer_half = '1' ) then next_state <= send_err; elsif ( d_buffer_ready = '0') then next_state <= send_wait; end if; when send_wait => if ( s_fr_dll = '0' and d_buffer_half = '1' ) then next_state <= send_err; elsif ( d_buffer_ready = '1') then next_state <= idle; end if; when send_err => if ( wait_for_bridge = '0') then next_state <= ready_to_send_err; end if; when ready_to_send_err => if ( d_buffer_ready = '1') then next_state <= send_err_pending; end if; when send_err_pending => if ( d_buffer_ready = '0') then next_state <= send_err_clear; end if; when send_err_clear => if ( d_buffer_ready = '1') then next_state <= idle; end if; when OTHERS => next_state <= idle; -- THIS SHOULD NEVER HAPPEN!! end case; end process nextstate; -- assign next state to state machine 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); -- If the frame has been altered, we have to reset the hopcounter -- and fill in the SRC address. This is done here. sb: process(address,hopcounter,altered_frame) begin if (altered_frame = '1') then -- send current hop counter as src-address. send_buffer(68 downto 62) <= hopcounter(7 downto 1); send_buffer(60 downto 53) <= (OTHERS => '0'); else -- leave address untouched. send_buffer(68 downto 62) <= address(6 downto 0); send_buffer(60 downto 53) <= hopcounter(7 downto 0); end if; end process sb; -- Set the output values according to the state machine. setoutput: process(current_state,reset_n, forward_buffer,send_buffer,process_buffer) begin d_to_dll <= ( OTHERS => '-' ); d_we <= '0'; d_initiate_send <= '0'; request <= process_buffer;-- Modified by Deyan Atanasov, originally was: ( OTHERS => '-' ); request_valid <= '0'; case current_state is when process_frame => d_to_dll<= send_buffer; d_we <= '1'; request <= process_buffer; request_valid <= '1'; when forward_frame => d_to_dll <= forward_buffer; d_we <= '1'; when send_init => d_initiate_send <= '1'; when ready_to_send_err => d_to_dll <= ( OTHERS => '0' ); -- ERROR FRAME d_we <= '1'; when send_err_pending => d_initiate_send <= '1'; when OTHERS => -- idle,analyze_frame,send_wait,send_err,send_err_clear NULL; end case; end process setoutput; -- -- if you know how to convert LSB to MSB, add 1 and convert back to LSB -- more easily and nice, please tell me. -- LSBtoMSB: for i in 7 downto 0 generate msb (i) <= d_fr_dll(60-i); lsb_inc (i) <= msb_inc(7-i); end generate; msb_inc(7 downto 0) <= (msb(7 downto 0) +1); -- address(6 downto 0) <= d_fr_dll(68 downto 62); src_dst <= d_fr_dll(61); hopcounter(7 downto 0) <= lsb_inc(7 downto 0); process_buffer(52 downto 0) <= d_fr_dll(52 downto 0); forward_buffer(68 downto 62) <= address(6 downto 0); forward_buffer(61) <= src_dst; forward_buffer(60 downto 53) <= hopcounter(7 downto 0); forward_buffer(52 downto 0) <= process_buffer(52 downto 0); -- remove broadcasts when in bridged state only (address = ...) -- check how read broadcasts do here. send_buffer(61) <= '0' when ( altered_frame = '1' or (address = "1111111" and bridge = '1')) ELSE '1'; send_buffer(52 downto 0) <= reply(52 downto 0); end structural; -------------------------------------------------- -- CONFIGURATION -------------------------------------------------- -- synopsys translate_off CONFIGURATION mcm_nw_nwsl_CFG of mcm_nw_nwsl is for structural end for; end mcm_nw_nwsl_CFG; -- synopsys translate_on