From: Andreas Neiser Date: Tue, 23 Apr 2013 07:46:39 +0000 (+0200) Subject: Using timer_ticks for timeout, and many code "beautification" by emacs vhdl mode... X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=73b03f95a75ff715f8b885dd9ee7a70e77246fad;p=trb3.git Using timer_ticks for timeout, and many code "beautification" by emacs vhdl mode... --- diff --git a/cts/source/cts_pkg.vhd b/cts/source/cts_pkg.vhd index a410e24..2939c2f 100755 --- a/cts/source/cts_pkg.vhd +++ b/cts/source/cts_pkg.vhd @@ -126,24 +126,25 @@ package cts_pkg is ); end component; - component mainz_a2_recv is + component mainz_a2_recv is port ( - CLK : in std_logic; - RESET_IN : in std_logic; - SERIAL_IN : in std_logic; - EXT_TRG_IN : in std_logic; - TRG_ASYNC_OUT : out std_logic; - TRG_SYNC_OUT : out std_logic; - TRIGGER_IN : in std_logic; - DATA_OUT : out std_logic_vector(31 downto 0); - WRITE_OUT : out std_logic; - STATUSBIT_OUT : out std_logic_vector(31 downto 0); - FINISHED_OUT : out std_logic; - CONTROL_REG_IN : in std_logic_vector(31 downto 0); - STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0'); - DEBUG : out std_logic_vector(31 downto 0)); + CLK : in std_logic; + RESET_IN : in std_logic; + TIMER_TICK_1US_IN : in std_logic; + SERIAL_IN : in std_logic; + EXT_TRG_IN : in std_logic; + TRG_ASYNC_OUT : out std_logic; + TRG_SYNC_OUT : out std_logic; + TRIGGER_IN : in std_logic; + DATA_OUT : out std_logic_vector(31 downto 0); + WRITE_OUT : out std_logic; + STATUSBIT_OUT : out std_logic_vector(31 downto 0); + FINISHED_OUT : out std_logic; + CONTROL_REG_IN : in std_logic_vector(31 downto 0); + STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0'); + DEBUG : out std_logic_vector(31 downto 0)); end component mainz_a2_recv; - + component CTS_TRIGGER is generic ( TRIGGER_INPUT_COUNT : integer range 1 to 8 := 4; diff --git a/cts/source/mainz_a2_recv.vhd b/cts/source/mainz_a2_recv.vhd index f637413..5eb5a7b 100644 --- a/cts/source/mainz_a2_recv.vhd +++ b/cts/source/mainz_a2_recv.vhd @@ -8,237 +8,240 @@ use work.trb3_components.all; entity mainz_a2_recv is - port( - CLK : in std_logic; -- must be 100 MHz! - RESET_IN : in std_logic; -- could be used after busy_release to make sure entity is in correct state - - --Module inputs - SERIAL_IN : in std_logic; -- serial raw in, externally clock'ed at 12.5 MHz - EXT_TRG_IN : in std_logic; -- external trigger in, ~10us later - -- the external trigger id is sent on SERIAL_IN - - --trigger outputs - TRG_ASYNC_OUT : out std_logic; -- asynchronous rising edge, length varying, here: approx. 110 ns - TRG_SYNC_OUT : out std_logic; -- sync. to CLK - - --data output for read-out - TRIGGER_IN : in std_logic; - DATA_OUT : out std_logic_vector(31 downto 0); - WRITE_OUT : out std_logic; - STATUSBIT_OUT : out std_logic_vector(31 downto 0); - FINISHED_OUT : out std_logic; - - --Registers / Debug - CONTROL_REG_IN : in std_logic_vector(31 downto 0); - STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0'); - DEBUG : out std_logic_vector(31 downto 0) - ); + port( + CLK : in std_logic; -- must be 100 MHz! + RESET_IN : in std_logic; -- could be used after busy_release to make sure entity is in correct state + TIMER_TICK_1US_IN : in std_logic; -- 1 micro second tick, synchronous to + -- CLK + + --Module inputs + SERIAL_IN : in std_logic; -- serial raw in, externally clock'ed at 12.5 MHz + EXT_TRG_IN : in std_logic; -- external trigger in, ~10us later + -- the external trigger id is sent on SERIAL_IN + + --trigger outputs + TRG_ASYNC_OUT : out std_logic; -- asynchronous rising edge, length varying, here: approx. 110 ns + TRG_SYNC_OUT : out std_logic; -- sync. to CLK + + --data output for read-out + TRIGGER_IN : in std_logic; + DATA_OUT : out std_logic_vector(31 downto 0); + WRITE_OUT : out std_logic; + STATUSBIT_OUT : out std_logic_vector(31 downto 0); + FINISHED_OUT : out std_logic; + + --Registers / Debug + CONTROL_REG_IN : in std_logic_vector(31 downto 0); + STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0'); + DEBUG : out std_logic_vector(31 downto 0) + ); end entity; --A2 trigger format of SERIAL_IN ---Startbit : "1" ---Trig.nr. : 32bit (but only ~20bit used at the moment) ---Paritybit : "0" or "1" +--Startbit : "1" +--Trig.nr. : 32bit (but only ~20bit used at the moment) +--Paritybit : "0" or "1" --Stopbit/Controlbit: "1" --Parity check over trig Nr and parity bit --Data Format of DATA_OUT (goes into DAQ stream) --- Bit 30 - 0 : Trigger Number (Bit 32 is cut off and used for error flag) --- Bit 31 : Error flag (either parity wrong or no stop/control bit seen) +-- Bit 30 - 0 : Trigger Number (Bit 32 is cut off and used for error flag) +-- Bit 31 : Error flag (either parity wrong or no stop/control bit seen) --statusbit 23 of STATUSBIT_OUT is equal to Bit 31 of DATA_OUT architecture arch1 of mainz_a2_recv is - constant timeoutcnt_Max : integer := 50000; -- x 10 ns = 500us maximum - -- time until trigger id can - -- be received; - signal timeoutcnt : integer range 0 to timeoutcnt_Max := timeoutcnt_Max; + -- 500 us ticks + -- time until trigger id can be received; + constant timeoutcnt_Max : integer := 500; + signal timeoutcnt : integer range 0 to timeoutcnt_Max := timeoutcnt_Max; + signal timer_tick_1us : std_logic; signal shift_reg : std_logic_vector(34 downto 0); - signal bitcnt : integer range 0 to shift_reg'length; - - + signal bitcnt : integer range 0 to shift_reg'length; - --signal first_bits_fast : std_logic; - --signal first_bits_slow : std_logic; - signal reg_SERIAL_IN : std_logic; - signal done : std_logic; - --signal done_slow : std_logic; - signal number_reg : std_logic_vector(30 downto 0); - --signal status_reg : std_logic_vector(1 downto 0); - signal error_reg : std_logic; - signal trg_async : std_logic; - signal trg_sync : std_logic; + --signal first_bits_fast : std_logic; + --signal first_bits_slow : std_logic; + signal reg_SERIAL_IN : std_logic; + signal done : std_logic; + --signal done_slow : std_logic; - type state_t is (IDLE, WAIT_FOR_STARTBIT, WAIT1, WAIT2, WAIT3, READ_BIT, - WAIT5, WAIT6, WAIT7, WAIT8, NO_TRG_ID_RECV, FINISH); - signal state : state_t := IDLE; + signal number_reg : std_logic_vector(30 downto 0); + --signal status_reg : std_logic_vector(1 downto 0); + signal error_reg : std_logic; - type rdo_state_t is (RDO_IDLE, RDO_WAIT, RDO_WRITE, RDO_FINISH); - signal rdostate : rdo_state_t := RDO_IDLE; + signal trg_async : std_logic; + signal trg_sync : std_logic; - signal config_rdo_disable_i : std_logic; + type state_t is (IDLE, WAIT_FOR_STARTBIT, WAIT1, WAIT2, WAIT3, READ_BIT, + WAIT5, WAIT6, WAIT7, WAIT8, NO_TRG_ID_RECV, FINISH); + signal state : state_t := IDLE; -begin + type rdo_state_t is (RDO_IDLE, RDO_WAIT, RDO_WRITE, RDO_FINISH); + signal rdostate : rdo_state_t := RDO_IDLE; + signal config_rdo_disable_i : std_logic; - reg_SERIAL_IN <= SERIAL_IN when rising_edge(CLK); - - --PROC_FIRST_BITS : process - --begin - -- wait until rising_edge(CLK_200); - -- if bitcnt > 32 and RESET_IN = '0' then - -- first_bits_fast <= '1'; - -- else - -- first_bits_fast <= '0'; - -- end if; - --end process; - - --first_bits_slow <= first_bits_fast when rising_edge(CLK); - - --trg_async <= (not MBS_IN or trg_async) when first_bits_fast = '1' else '0'; - --trg_sync <= (not reg_MBS_IN or trg_sync) and first_bits_slow when rising_edge(CLK); - trg_async <= EXT_TRG_IN; - trg_sync <= EXT_TRG_IN when rising_edge(CLK); -- do we need another register - -- here? - - TRG_ASYNC_OUT <= trg_async; - TRG_SYNC_OUT <= trg_sync when rising_edge(CLK); - - -- since CLK runs at 100MHz, we sample at 12.5MHz due to 8 WAIT states - PROC_FSM : process - begin - wait until rising_edge(CLK); - case state is - - when IDLE => - done <= '1'; - if trg_sync = '1' then - done <= '0'; - timeoutcnt <= timeoutcnt_Max; - state <= WAIT_FOR_STARTBIT; - end if; - - when WAIT_FOR_STARTBIT => - - if reg_SERIAL_IN = '1' then - bitcnt <= shift_reg'length; - state <= WAIT1; - elsif timeoutcnt = 0 then - state <= NO_TRG_ID_RECV; - else - timeoutcnt <= timeoutcnt-1; - end if; - - - when WAIT1 => - state <= WAIT2; - when WAIT2 => - state <= WAIT3; - when WAIT3 => - state <= READ_BIT; - - - when READ_BIT => -- actually WAIT4, but we read here, in the middle of - -- the serial line communication - bitcnt <= bitcnt - 1; - -- we fill the shift_reg LSB first since this way the trg id arrives - shift_reg <= reg_SERIAL_IN & shift_reg(shift_reg'high downto 1); - state <= WAIT5; - - when WAIT5 => - -- check if we're done reading - if bitcnt = 0 then - state <= FINISH; - else - state <= WAIT6; - end if; - - when WAIT6 => - state <= WAIT7; - when WAIT7 => - state <= WAIT8; - when WAIT8 => - state <= WAIT1; - - when NO_TRG_ID_RECV => - -- we received no id after a trigger within the timeout, so - -- set bogus trigger id and no control bit (forces error flag set!) - shift_reg <= b"00" & x"ffffffff" & b"1"; - state <= FINISH; - - when FINISH => - -- wait until serial line is idle again - if reg_SERIAL_IN = '0' then - state <= IDLE; - end if; - done <= '1'; - end case; - - if RESET_IN = '1' then - state <= IDLE; - done <= '0'; - end if; - end process; - - --done_slow <= done when rising_edge(CLK); - - PROC_REG_INFO : process - begin - wait until rising_edge(CLK); - if done = '1' then - -- here we cut off the highest bit of the received trigger id - -- so shift_reg(32) is discarded (but used for checksum) - number_reg <= shift_reg(31 downto 1); - --status_reg <= shift_reg(7 downto 6); - - -- check if start and control bit is 1 and parity is okay - if shift_reg(34) = '1' and shift_reg(0) = '1' - and xor_all(shift_reg(33 downto 1)) = '0' then - error_reg <= '0'; - else - error_reg <= '1'; - end if; - end if; - end process; - - - PROC_RDO : process - begin - wait until rising_edge(CLK); - WRITE_OUT <= '0'; - FINISHED_OUT <= config_rdo_disable_i; - STATUSBIT_OUT <= (23 => error_reg, others => '0'); - case rdostate is - when RDO_IDLE => - if TRIGGER_IN = '1' and config_rdo_disable_i = '0' then - if done = '0' then - rdostate <= RDO_WAIT; - else - rdostate <= RDO_WRITE; - end if; - end if; - when RDO_WAIT => - if done = '1' then - rdostate <= RDO_WRITE; - end if; - when RDO_WRITE => - rdostate <= RDO_FINISH; - DATA_OUT <= error_reg & number_reg; - WRITE_OUT <= '1'; - - when RDO_FINISH => - FINISHED_OUT <= '1'; - rdostate <= RDO_IDLE; - end case; - end process; - - config_rdo_disable_i <= CONTROL_REG_IN(0); - - STATUS_REG_OUT <= error_reg & std_logic_vector(to_unsigned(bitcnt, 6)) & number_reg(24 downto 0); - DEBUG <= x"00000000"; -- & done & '0' & shift_reg(13 downto 0); +begin + timer_tick_1us <= TIMER_TICK_1US_IN; + + reg_SERIAL_IN <= SERIAL_IN when rising_edge(CLK); + + --PROC_FIRST_BITS : process + --begin + -- wait until rising_edge(CLK_200); + -- if bitcnt > 32 and RESET_IN = '0' then + -- first_bits_fast <= '1'; + -- else + -- first_bits_fast <= '0'; + -- end if; + --end process; + + --first_bits_slow <= first_bits_fast when rising_edge(CLK); + + --trg_async <= (not MBS_IN or trg_async) when first_bits_fast = '1' else '0'; + --trg_sync <= (not reg_MBS_IN or trg_sync) and first_bits_slow when rising_edge(CLK); + trg_async <= EXT_TRG_IN; + -- do we need another register here? + trg_sync <= EXT_TRG_IN when rising_edge(CLK); + + TRG_ASYNC_OUT <= trg_async; + TRG_SYNC_OUT <= trg_sync when rising_edge(CLK); + + -- since CLK runs at 100MHz, we sample at 12.5MHz due to 8 WAIT states + PROC_FSM : process + begin + wait until rising_edge(CLK); + case state is + + when IDLE => + done <= '1'; + if trg_sync = '1' then + done <= '0'; + timeoutcnt <= timeoutcnt_Max; + state <= WAIT_FOR_STARTBIT; + end if; + + when WAIT_FOR_STARTBIT => + + if reg_SERIAL_IN = '1' then + bitcnt <= shift_reg'length; + state <= WAIT1; + elsif timeoutcnt = 0 then + state <= NO_TRG_ID_RECV; + elsif timer_tick_1us = '1' then + timeoutcnt <= timeoutcnt-1; + end if; + + + when WAIT1 => + state <= WAIT2; + when WAIT2 => + state <= WAIT3; + when WAIT3 => + state <= READ_BIT; + + + when READ_BIT => -- actually WAIT4, but we read here, in the middle of + -- the serial line communication + bitcnt <= bitcnt - 1; + -- we fill the shift_reg LSB first since this way the trg id arrives + shift_reg <= reg_SERIAL_IN & shift_reg(shift_reg'high downto 1); + state <= WAIT5; + + when WAIT5 => + -- check if we're done reading + if bitcnt = 0 then + state <= FINISH; + else + state <= WAIT6; + end if; + + when WAIT6 => + state <= WAIT7; + when WAIT7 => + state <= WAIT8; + when WAIT8 => + state <= WAIT1; + + when NO_TRG_ID_RECV => + -- we received no id after a trigger within the timeout, so + -- set bogus trigger id and no control bit (forces error flag set!) + shift_reg <= b"00" & x"ffffffff" & b"1"; + state <= FINISH; + + when FINISH => + -- wait until serial line is idle again + if reg_SERIAL_IN = '0' then + state <= IDLE; + end if; + done <= '1'; + end case; + + if RESET_IN = '1' then + state <= IDLE; + done <= '0'; + end if; + end process; + + --done_slow <= done when rising_edge(CLK); + + PROC_REG_INFO : process + begin + wait until rising_edge(CLK); + if done = '1' then + -- here we cut off the highest bit of the received trigger id + -- so shift_reg(32) is discarded (but used for checksum) + number_reg <= shift_reg(31 downto 1); + --status_reg <= shift_reg(7 downto 6); + + -- check if start and control bit is 1 and parity is okay + if shift_reg(34) = '1' and shift_reg(0) = '1' + and xor_all(shift_reg(33 downto 1)) = '0' then + error_reg <= '0'; + else + error_reg <= '1'; + end if; + end if; + end process; + + + PROC_RDO : process + begin + wait until rising_edge(CLK); + WRITE_OUT <= '0'; + FINISHED_OUT <= config_rdo_disable_i; + STATUSBIT_OUT <= (23 => error_reg, others => '0'); + case rdostate is + when RDO_IDLE => + if TRIGGER_IN = '1' and config_rdo_disable_i = '0' then + if done = '0' then + rdostate <= RDO_WAIT; + else + rdostate <= RDO_WRITE; + end if; + end if; + when RDO_WAIT => + if done = '1' then + rdostate <= RDO_WRITE; + end if; + when RDO_WRITE => + rdostate <= RDO_FINISH; + DATA_OUT <= error_reg & number_reg; + WRITE_OUT <= '1'; + + when RDO_FINISH => + FINISHED_OUT <= '1'; + rdostate <= RDO_IDLE; + end case; + end process; + + config_rdo_disable_i <= CONTROL_REG_IN(0); + + STATUS_REG_OUT <= error_reg & std_logic_vector(to_unsigned(bitcnt, 6)) & number_reg(24 downto 0); + DEBUG <= x"00000000"; -- & done & '0' & shift_reg(13 downto 0); end architecture; diff --git a/cts/trb3_central.vhd b/cts/trb3_central.vhd index 0a00bd3..d121b44 100644 --- a/cts/trb3_central.vhd +++ b/cts/trb3_central.vhd @@ -344,6 +344,7 @@ architecture trb3_central_arch of trb3_central is signal cts_trigger_out : std_logic; signal external_send_reset : std_logic; + --bit 1 ms-tick, 0 us-tick signal timer_ticks : std_logic_vector(1 downto 0); signal trigger_busy_i : std_logic; @@ -432,11 +433,13 @@ begin ); end generate; +-- Mainz A2 Module gen_mainz_a2_as_etm: if ETM_CHOICE = ETM_CHOICE_MAINZ_A2 generate mainz_a2_recv_1: entity work.mainz_a2_recv port map ( CLK => clk_100_i, RESET_IN => reset_i, + TIMER_TICK_1US_IN => timer_ticks(0), SERIAL_IN => CLK_EXT(3), EXT_TRG_IN => CLK_EXT(4), --TRG_ASYNC_OUT => TRG_ASYNC_OUT,