-- PROJECT: D0 Run IIb Trigger L1 Calorimeter upgrade -- -- MODULE: RS232 to generic bus converter -- -- ELEMENT: interpret_line -- -- DESCRIPTION: interprets the string of characters received over RS232 -- -- AUTHOR: J.Marquet marquet@efrei.fr -- -- DATE AND HISTORY: -- July 2004: created -- September 2004: reviewed by D. Calvet -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library work; use work.utility_pkg.all; use work.constant_package.all; -------------------------------------------------------------------------------- -- -- Line interpreter -- entity interpret_line is generic ( ADDR_BUS_SIZE : integer := 12; DATA_BUS_SIZE : integer := 8 ); port ( -- -- General control signals -- RESET : in std_logic; -- Asynch. Reset CLK : in std_logic; -- Reference Clock -- -- Signals from character interpreter -- CODE_VALID : in std_logic; -- new input ready CODE : in std_logic_vector(3 downto 0); -- binary value if digit IS_SPACE : in std_logic; -- character is " " IS_I : in std_logic; -- character is "I" IS_R : in std_logic; -- character is "R" IS_W : in std_logic; -- character is "W" IS_Q : in std_logic; -- character is "Q" IS_CR : in std_logic; -- character is carriage return IS_LF : in std_logic; -- character is line feed IS_DIGIT : in std_logic; -- character is 0-9 or A-F IS_ERROR : in std_logic; -- character is none of above -- -- Signals for bus control block -- ERROR : out std_logic; -- syntax error in command NEW_LINE : out std_logic; -- new command ready IS_W_CMD : out std_logic; -- line is write command IS_I_CMD : out std_logic; -- line is init command IS_Q_CMD : out std_logic; -- line is quit command ADDR_CMD : out std_logic_vector(ADDR_BUS_SIZE-1 downto 0); -- address BYTE_SEL : out std_logic_vector(3 downto 0); -- selected byte DATA_CMD : out std_logic_vector(DATA_BUS_SIZE-1 downto 0); -- output data -- -- Signal for RS232 serializer -- ECHO_ON : out std_logic -- active when data received shall be echoed ); end interpret_line; Architecture behavioral of interpret_line is Type ETAT is(Init, space1, Addr, space2 , Oct_selec, space3, Data, cr, Lf); signal etat_c : ETAT; -- state of state machine signal cpt : std_logic_vector(2 downto 0); -- counts the number of characters in the address or data field signal running : std_logic; -- Active when bus interface has been sucessfully configured signal init_cmd : std_logic; -- Active when Init command in progress signal quit_cmd : std_logic; -- Active when Quit command in progress signal cmd_err : std_logic; -- Active when any error in current command signal bus_addr : std_logic_vector(ADDR_BUS_SIZE-1 downto 0); -- address being received in the command line signal bus_data : std_logic_vector(DATA_BUS_SIZE-1 downto 0); -- data being received in the command line begin -- -- Permanent signals -- IS_I_CMD <= init_cmd; IS_Q_CMD <= quit_cmd; ERROR <= cmd_err; ADDR_CMD <= bus_addr; DATA_CMD <= bus_data; -------------------------------------------------------------------------------------------------------------------- -- P0 process is the counter for the size of the address and data bus fields. -- It counts the number of hexadecimal character received to make the address field then the data field. -- It also counts the number of characters in the byte select field, but this is not used so far. -------------------------------------------------------------------------------------------------------------------- P0: process(RESET, CLK) begin if RESET = '1' then cpt <= (others => '0'); elsif rising_edge(CLK) and CODE_VALID = '1' then if etat_c = space1 or etat_c = space2 or etat_c = space3 then cpt <= (others => '0'); else cpt <= cpt + 1; end if; end if; end process P0; ------------------------------------------------------------------------------------------------------------------- -- P1 process records the received address in binary format. The length of the shift register -- is determined by the generic ADDR_BUS_SIZE. ------------------------------------------------------------------------------------------------------------------- P1: process(RESET, CLK) begin if RESET = '1' then bus_addr <= (others => '0'); elsif rising_edge (CLK) then if CODE_VALID = '1' and etat_c = Addr then bus_addr <= bus_addr(ADDR_BUS_SIZE-5 downto 0) & CODE; end if; end if; end process P1; ------------------------------------------------------------------------------------------------------------------ -- P3 process records the received data in binary format. The length of the shift register -- is determined by the generic DATA_BUS_SIZE. ------------------------------------------------------------------------------------------------------------------ P2: process(RESET, CLK) begin if RESET = '1' then bus_data <= (others => '0'); elsif rising_edge(CLK) then if CODE_VALID = '1' and etat_c = Data then bus_data <= bus_data(DATA_BUS_SIZE-5 downto 0) & CODE; end if; end if; end process P2; ----------------------------------------------------------------------------------------------------------------- -- ANALYS_CHAINE process is the state machine of this block. It has nine states. Each state corresponds -- to a field of the command line. ----------------------------------------------------------------------------------------------------------------- ANALYS_CHAINE: process(RESET, CLK) begin if RESET = '1' then etat_c <= Init; running <= '0'; cmd_err <= '0'; init_cmd <= '0'; IS_W_CMD <= '0'; quit_cmd <= '0'; ECHO_ON <= '1'; BYTE_SEL <= (others => '1'); elsif rising_edge(CLK) and CODE_VALID = '1' then case etat_c is when Init => -- waiting for I, R, W or Q ECHO_ON <= '1'; if running = '0' then if IS_I = '1' then etat_c <= space1; cmd_err <= '0'; init_cmd <= '1'; else cmd_err <= '1'; init_cmd <= '0'; ECHO_ON <= '0'; end if; if IS_CR = '1' then etat_c <= lf; cmd_err <= '1'; end if; IS_W_CMD <= '0'; quit_cmd <= '0'; else if IS_I = '1' then etat_c <= space1; cmd_err <= '0'; init_cmd <= '1'; IS_W_CMD <= '0'; else init_cmd <= '0'; end if; if IS_R = '1' then etat_c <= space1; cmd_err <= '0'; IS_W_CMD <= '0'; end if; if IS_W = '1' then etat_c <= space1; cmd_err <= '0'; IS_W_CMD <= '1'; end if; if IS_ERROR = '1' then etat_c <= space1; cmd_err <= '1'; ECHO_ON <= '0'; end if; end if; if IS_Q = '1' then etat_c <= cr; running <= '0'; cmd_err <= '0'; IS_W_CMD <= '0'; quit_cmd <= '1'; ECHO_ON <= '0'; else quit_cmd <= '0'; end if; when space1 => -- waiting for 1 space if IS_SPACE = '0' then cmd_err <= '1'; ECHO_ON <= '0'; end if; if IS_CR = '1' then etat_c <= lf; else etat_c <= Addr; end if; when Addr => -- getting address field characters if IS_DIGIT = '0' then cmd_err <= '1'; ECHO_ON <= '0'; end if; if IS_CR = '1' then etat_c <= lf; else if cpt = Natural_To_Std_Logic_Vector((ADDR_BUS_SIZE/4)-1,3) then etat_c <= space2; end if; end if; when space2 => -- waiting for 1 space if IS_SPACE = '0' then cmd_err <= '1'; ECHO_ON <= '0'; end if; if IS_CR = '1' then etat_c <= lf; else etat_c <= Oct_selec; end if; when Oct_selec => -- getting byte selection character if IS_DIGIT = '1' then BYTE_SEL <= CODE; else cmd_err <= '1'; ECHO_ON <= '0'; end if; if IS_CR = '1' then etat_c <= lf; else etat_c <= space3; end if; when space3 => -- waiting for 1 space if IS_SPACE = '0' then cmd_err <= '1'; ECHO_ON <= '0'; end if; if IS_CR = '1' then etat_c <= lf; else etat_c <= Data; ECHO_ON <= '0'; end if; when Data => -- getting data field characters if IS_DIGIT = '0' then cmd_err <= '1'; ECHO_ON <= '0'; end if; if IS_CR = '1' then etat_c <= lf; else if cpt = Natural_To_Std_Logic_Vector ((DATA_BUS_SIZE/4)-1,3) then etat_c <= Cr; end if; end if; when Cr => -- blocking wait for carriage return if IS_CR = '0' then cmd_err <= '1'; ECHO_ON <= '0'; else etat_c <= lf; end if; when Lf => -- blocking wait for line feed if IS_LF = '0' then cmd_err <= '1'; ECHO_ON <= '0'; else if init_cmd = '1' then if cmd_err = '0' then running <= '1'; else running <= '0'; end if; end if; if quit_cmd = '1' then running <= '0'; end if; etat_c <= Init; ECHO_ON <= '1'; end if; end case; end if; end process ANALYS_CHAINE; ------------------------------------------------------------------------------------------------------- -- Ligne process pulses NEW_LINE when a command line has been completely received ------------------------------------------------------------------------------------------------------- Ligne: process(RESET, CLK) begin if RESET = '1' then NEW_LINE <= '0'; elsif rising_edge(CLK) then if etat_c = Lf and IS_LF = '1' then NEW_LINE <= '1'; else NEW_LINE <= '0'; end if; end if; end process Ligne; end behavioral;