From 9d05cd08e64ceded2b12b31235ac1e9a5b977f76 Mon Sep 17 00:00:00 2001 From: Jan Michel Date: Mon, 11 Sep 2017 13:17:26 +0200 Subject: [PATCH] add experimental double edge detection to monitor design --- base/code/double_edge_detection.vhd | 209 +++++++++++++++++++++++ monitor/config_compile_frankfurt.pl | 2 +- monitor/sim/tb_double_edge_detection.vhd | 80 +++++++++ monitor/trb3_periph_monitor.lpf | 2 + monitor/trb3_periph_monitor.prj | 1 + monitor/trb3_periph_monitor.vhd | 46 ++--- 6 files changed, 319 insertions(+), 21 deletions(-) create mode 100644 base/code/double_edge_detection.vhd create mode 100644 monitor/sim/tb_double_edge_detection.vhd diff --git a/base/code/double_edge_detection.vhd b/base/code/double_edge_detection.vhd new file mode 100644 index 0000000..96207dc --- /dev/null +++ b/base/code/double_edge_detection.vhd @@ -0,0 +1,209 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.trb_net_std.all; + use work.config.all; + +entity double_edge_detection is + generic( + CHANNELS : integer := 32 + ); + port( + CLK : in std_logic; + RESET : in std_logic; + + INP : in std_logic_vector(CHANNELS-1 downto 0); + + --Slowcontrol + BUS_RX : in CTRLBUS_RX; + BUS_TX : out CTRLBUS_TX; + + READOUT_RX : in READOUT_RX; + READOUT_TX : out READOUT_TX; + + DEBUG_OUT : out std_logic_vector(7 downto 0) + + ); +end entity; + + +architecture arch of double_edge_detection is + + signal maxage : unsigned(15 downto 0); + signal waitage : unsigned(15 downto 0); + signal window : unsigned(3 downto 0); + + signal timer : unsigned(27 downto 0); + + type storage_t is array (0 to CHANNELS) of std_logic_vector(31 downto 0); + signal storage : storage_t; + signal clear_storage : std_logic; + + signal data_counter : integer range 0 to 65535; + + type state_t is (IDLE, WAIT_AFTER, WRITE, FINISH, BUSYEND); + signal state : state_t; + + signal found_double : std_logic_vector(CHANNELS-1 downto 0); + + +-- signal reg_INP : std_logic_vector(CHANNELS-1 downto 0); +-- signal INP_low, reg_INP_low, reg2_INP_low : std_logic_vector(CHANNELS-1 downto 0); +-- signal INP_low_long, reg_INP_low_long : std_logic_vector(CHANNELS-1 downto 0); + + signal reg_INP, INP_b, reg2_INP, reg3_INP, INP_long : std_logic_vector(CHANNELS-1 downto 0); + signal INP_low, reg_INP_low, reg2_INP_low : std_logic_vector(CHANNELS-1 downto 0); + signal INP_low_long, reg_INP_low_long : std_logic_vector(CHANNELS-1 downto 0); + signal reset_found : std_logic_vector(CHANNELS-1 downto 0); + + + +begin + +PROC_REGS : process begin + wait until rising_edge(CLK); + BUS_TX.ack <= '0'; + BUS_TX.nack <= '0'; + BUS_TX.unknown <= '0'; + BUS_TX.data <= (others => '0'); + + if BUS_RX.write = '1' then + BUS_TX.ack <= '1'; + case BUS_RX.addr(1 downto 0) is +-- when "00" => maxage <= unsigned(BUS_RX.data(15 downto 0)); -- max age to include in data, not implemented yet + when "01" => waitage <= unsigned(BUS_RX.data(15 downto 0)); -- time after reference time + when "10" => window <= unsigned(BUS_RX.data(3 downto 0)); --clock cycles between rising edges + when others => BUS_TX.ack <= '0'; BUS_TX.unknown <= '1'; + end case; + elsif BUS_RX.read = '1' then + BUS_TX.ack <= '1'; + case BUS_RX.addr(1 downto 0) is +-- when "00" => BUS_TX.data(15 downto 0) <= std_logic_vector(maxage); + when "01" => BUS_TX.data(15 downto 0) <= std_logic_vector(waitage); + when "10" => BUS_TX.data(3 downto 0) <= std_logic_vector(window); + when others => BUS_TX.ack <= '0'; BUS_TX.unknown <= '1'; + end case; + end if; +end process; + + +THE_TIME : process begin + wait until rising_edge(CLK); + timer <= timer + 1; +end process; + + +THE_RDO : process begin + wait until rising_edge(CLK); + READOUT_TX.busy_release <= '0'; + READOUT_TX.data_write <= '0'; + READOUT_TX.data_finished <= '0'; + clear_storage <= '0'; + + case state is + when IDLE => + if READOUT_RX.valid_timing_trg = '1' or READOUT_RX.valid_notiming_trg = '1' then + state <= WAIT_AFTER; + end if; + if READOUT_RX.invalid_trg = '1' then + state <= FINISH; + end if; + data_counter <= 0; + when WAIT_AFTER => + data_counter <= data_counter + 1; + if waitage = 0 or to_unsigned(data_counter,16) = waitage then + state <= WRITE; + data_counter <= 0; + end if; + when WRITE => + READOUT_TX.data <= storage(data_counter); + READOUT_TX.data_write <= '1'; + data_counter <= data_counter + 1; + if data_counter = CHANNELS then + state <= FINISH; + end if; + when FINISH => + state <= BUSYEND; + READOUT_TX.data_finished <= '1'; + clear_storage <= '1'; + when BUSYEND => + state <= IDLE; + READOUT_TX.busy_release <= '1'; + end case; +end process; + + +THE_STORE : process begin + wait until rising_edge(CLK); + for i in 0 to CHANNELS-1 loop + if found_double(i) = '1' then + storage(i+1) <= "1000" & std_logic_vector(timer); + elsif clear_storage = '1' then + storage(i+1) <= (others => '0'); + end if; + end loop; + + if READOUT_RX.valid_timing_trg = '1' then + storage(0) <= "1000" & std_logic_vector(timer); + elsif clear_storage = '1' then + storage(0) <= (others => '0'); + end if; +end process; + + +-- THE_DETECT : process begin +-- wait until rising_edge(CLK); +-- for i in 0 to CHANNELS-1 loop +-- if reg_INP(i) = '1' and reg_INP_low_long(i) = '1' then +-- found_double(i) <= '1'; +-- else +-- found_double(i) <= '0'; +-- end if; +-- end loop; +-- end process; +-- +-- +-- -- INP_b <= INP or INP_b and not reg_INP_b; +-- reg_INP <= INP when rising_edge(CLK); +-- +-- -- reg3_INP_b <= reg2_INP_b when rising_edge(CLK); +-- -- INP_long <= reg3_INP_b or reg2_INP_b or reg_INP_b or INP_b; +-- +-- INP_low <= not INP and reg_INP; +-- +-- reg_INP_low <= INP_low when rising_edge(CLK); +-- reg2_INP_low <= reg_INP_low when rising_edge(CLK); +-- INP_low_long <= INP_low or reg_INP_low or reg2_INP_low; +-- reg_INP_low_long <= INP_low_long when rising_edge(CLK); +-- + + +INP_b <= (INP or INP_b) and not reg_INP; +reg_INP <= INP_b when rising_edge(CLK); +reg2_INP <= reg_INP when rising_edge(CLK); +reg3_INP <= reg2_INP when rising_edge(CLK); +INP_long <= reg3_INP or reg2_INP or reg_INP or INP_b; + +THE_DETECT : process(reset_found, INP) begin + for i in 0 to CHANNELS-1 loop + if reset_found(i) = '1' then + found_double(i) <= '0'; + elsif rising_edge(INP(i)) and INP_long(i) = '1' then + found_double(i) <= '1'; + end if; + end loop; +end process; + +reset_found <= found_double when rising_edge(CLK); + + + + +DEBUG_OUT <= "0000" & found_double(0) & INP_low_long(0) & INP_low(0) & INP(0); + +end architecture; + + + diff --git a/monitor/config_compile_frankfurt.pl b/monitor/config_compile_frankfurt.pl index 5fee652..c5df875 100644 --- a/monitor/config_compile_frankfurt.pl +++ b/monitor/config_compile_frankfurt.pl @@ -21,4 +21,4 @@ twr_number_of_errors => 20, Familyname => 'LatticeECP3', Devicename => 'LFE3-150EA', Package => 'FPBGA672', -Speedgrade => '8', \ No newline at end of file +Speedgrade => '8', diff --git a/monitor/sim/tb_double_edge_detection.vhd b/monitor/sim/tb_double_edge_detection.vhd new file mode 100644 index 0000000..fb31fa5 --- /dev/null +++ b/monitor/sim/tb_double_edge_detection.vhd @@ -0,0 +1,80 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + + +entity double_edge_detection is +end entity; + + + +architecture arch of double_edge_detection is + constant CHANNELS :integer := 1; + + signal CLK : std_logic := '1'; + + signal found_double : std_logic := '0'; + + + signal reg_INP, INP, INP_b, reg2_INP, reg3_INP, INP_long : std_logic := '0'; + signal INP_low, reg_INP_low, reg2_INP_low : std_logic := '0'; + signal INP_low_long, reg_INP_low_long : std_logic := '0'; + signal reset_found : std_logic := '0'; + + +begin + +CLK <= not CLK after 5 ns; + +PROC_STIM : process begin + INP <= '0'; wait for 105.3 ns; + INP <= '1'; wait for 1 ns; + INP <= '0'; wait for 1 ns; + INP <= '1'; wait for 1 ns; + INP <= '0'; + wait for 101 ns; + +end process; + +-- THE_DETECT : process begin +-- wait until rising_edge(CLK); +-- if (reg_INP = '1') and reg_INP_low_long = '1' then +-- found_double <= '1'; +-- else +-- found_double <= '0'; +-- end if; +-- end process; +-- +-- +-- +-- INP_b <= (INP or INP_b) and not reg_INP; +-- reg_INP <= INP_b when rising_edge(CLK); +-- reg2_INP <= reg_INP when rising_edge(CLK); +-- -- reg3_INP_b <= reg2_INP_b when rising_edge(CLK); +-- -- INP_long <= reg3_INP_b or reg2_INP_b or reg_INP_b or INP_b; +-- +-- INP_low <= (not INP and reg_INP) or (INP_low and not reg_INP_low); +-- +-- reg_INP_low <= INP_low when rising_edge(CLK); +-- reg2_INP_low <= reg_INP_low when rising_edge(CLK); +-- INP_low_long <= INP_low or reg_INP_low or reg2_INP_low; +-- reg_INP_low_long <= INP_low_long when rising_edge(CLK); +-- + +INP_b <= (INP or INP_b) and not reg_INP; +reg_INP <= INP_b when rising_edge(CLK); +reg2_INP <= reg_INP when rising_edge(CLK); +reg3_INP <= reg2_INP when rising_edge(CLK); +INP_long <= reg3_INP or reg2_INP or reg_INP or INP_b; + +THE_DETECT : process(reset_found, INP) begin + if reset_found = '1' then + found_double <= '0'; + elsif rising_edge(INP) and INP_long = '1' then + found_double <= '1'; + end if; +end process; + +reset_found <= found_double when rising_edge(CLK); + +end architecture; diff --git a/monitor/trb3_periph_monitor.lpf b/monitor/trb3_periph_monitor.lpf index bb534d0..ba318c5 100644 --- a/monitor/trb3_periph_monitor.lpf +++ b/monitor/trb3_periph_monitor.lpf @@ -31,6 +31,8 @@ LOCATE UGROUP "THE_MEDIA_UPLINK/media_interface_group" REGION "MEDIA_UPLI MULTICYCLE TO CELL "THE_SPI_RELOAD_THE_SPI_MASTER_THE_SPI_SLIM_tx_sreg_oregio*" 20 ns; +PROHIBIT PRIMARY NET "INP"; +PROHIBIT SECONDARY NET "INP"; ################################################################# # Clocks diff --git a/monitor/trb3_periph_monitor.prj b/monitor/trb3_periph_monitor.prj index 05a6aa7..c0daae2 100644 --- a/monitor/trb3_periph_monitor.prj +++ b/monitor/trb3_periph_monitor.prj @@ -156,6 +156,7 @@ add_file -vhdl -lib work "../../trb3sc/code/spi_master_generic.vhd" add_file -vhdl -lib work "../base/code/input_to_trigger_logic_record.vhd" add_file -vhdl -lib work "../base/code/input_statistics.vhd" add_file -vhdl -lib work "../base/code/sedcheck.vhd" +add_file -vhdl -lib work "../base/code/double_edge_detection.vhd" add_file -vhdl -lib work "trb3_periph_monitor.vhd" diff --git a/monitor/trb3_periph_monitor.vhd b/monitor/trb3_periph_monitor.vhd index fa60f15..6dd5169 100644 --- a/monitor/trb3_periph_monitor.vhd +++ b/monitor/trb3_periph_monitor.vhd @@ -117,6 +117,8 @@ architecture arch of trb3_periph_monitor is signal serdes_i : std_logic_vector(3 downto 0); attribute nopad : string; attribute nopad of serdes_i : signal is "true"; + + signal debug_double_edge : std_logic_vector(7 downto 0); begin --------------------------------------------------------------------------- @@ -370,30 +372,34 @@ THE_ENDPOINT : entity work.trb_net16_endpoint_hades_full_handler_record --------------------------------------------------------------------------- -- Test Connector - Additional Features --------------------------------------------------------------------------- - TEST_LINE <= feature_outputs_i; +-- TEST_LINE <= feature_outputs_i; +TEST_LINE(7 downto 0) <= debug_double_edge; ------------------------------------------------------------------------------- -- Your logic ------------------------------------------------------------------------------- --- THE_Logic : entity work.XXXXX --- port map ( --- RESET => reset_i, --- CLK => clk_100_i, --- REFERENCE_TIME => timing_trg_received_i, -- Reference time input --- --Inputs from AddOn and trigger signal to CTS (4 lines) --- SIGNAL_IN => INP, --- TRIGGER_OUT => trig_gen_out_i, --- -- Trigger signals from handler & readout data --- BUSRDO_RX => readout_rx, --- BUSRDO_TX => readout_tx(0), --- -- Slow control bus --- BUS_RX => busrdo_rx, --- BUS_TX => busrdo_tx --- --- ); -readout_tx(0).data_finished <= '1'; -readout_tx(0).data_write <= '0'; -readout_tx(0).busy_release <= '1'; +THE_DOUBLE_EDGE_DETECTOR : entity work.double_edge_detection + generic map( + CHANNELS => 32 + ) + port map( + CLK => clk_100_i, + RESET => reset_i, + + INP => INP(31 downto 0), + + -- Trigger signals from handler & readout data + READOUT_RX => readout_rx, + READOUT_TX => readout_tx(0), + + -- Slow control bus + BUS_RX => busrdo_rx, + BUS_TX => busrdo_tx, + + DEBUG_OUT => debug_double_edge + + ); + end architecture; -- 2.43.0