Commit 547a3cff authored by gilsoriano's avatar gilsoriano

Basic trigger: core for the basic repetition functionality improved to allow low-jitter operation.

parent 9c48eb1b
...@@ -334,22 +334,22 @@ NET "manual_rst_n_o" LOC = T22; ...@@ -334,22 +334,22 @@ NET "manual_rst_n_o" LOC = T22;
NET "fpga_o_en" IOSTANDARD = "LVCMOS33"; NET "fpga_o_en" IOSTANDARD = "LVCMOS33";
NET "fpga_o_en" DRIVE = "4"; NET "fpga_o_en" DRIVE = "4";
NET "fpga_o_en" SLEW = "QUIETIO"; NET "fpga_o_en" SLEW = "QUIETIO";
NET "fpga_o_en" PULLDOWN; ## NET "fpga_o_en" PULLDOWN;
NET "fpga_o_blo_en" LOC = N3; NET "fpga_o_blo_en" LOC = N3;
NET "fpga_o_blo_en" IOSTANDARD = "LVCMOS33"; NET "fpga_o_blo_en" IOSTANDARD = "LVCMOS33";
NET "fpga_o_blo_en" DRIVE = "4"; NET "fpga_o_blo_en" DRIVE = "4";
NET "fpga_o_blo_en" SLEW = "QUIETIO"; NET "fpga_o_blo_en" SLEW = "QUIETIO";
NET "fpga_o_blo_en" PULLDOWN; ## NET "fpga_o_blo_en" PULLDOWN;
NET "fpga_o_ttl_en" LOC = M3; NET "fpga_o_ttl_en" LOC = M3;
NET "fpga_o_ttl_en" IOSTANDARD = "LVCMOS33"; NET "fpga_o_ttl_en" IOSTANDARD = "LVCMOS33";
NET "fpga_o_ttl_en" DRIVE = "4"; NET "fpga_o_ttl_en" DRIVE = "4";
NET "fpga_o_ttl_en" SLEW = "QUIETIO"; NET "fpga_o_ttl_en" SLEW = "QUIETIO";
NET "fpga_o_ttl_en" PULLDOWN; ## NET "fpga_o_ttl_en" PULLDOWN;
NET "fpga_o_inv_en" LOC = P3; NET "fpga_o_inv_en" LOC = P3;
NET "fpga_o_inv_en" IOSTANDARD = "LVCMOS33"; NET "fpga_o_inv_en" IOSTANDARD = "LVCMOS33";
NET "fpga_o_inv_en" DRIVE = "4"; NET "fpga_o_inv_en" DRIVE = "4";
NET "fpga_o_inv_en" SLEW = "QUIETIO"; NET "fpga_o_inv_en" SLEW = "QUIETIO";
NET "fpga_o_inv_en" PULLDOWN; ## NET "fpga_o_inv_en" PULLDOWN;
##------------------- ##-------------------
##-- Motherboard and piggyback IDs ##-- Motherboard and piggyback IDs
##-- ##--
......
...@@ -25,16 +25,16 @@ use work.ctdah_pkg.ALL; ...@@ -25,16 +25,16 @@ use work.ctdah_pkg.ALL;
entity basic_trigger_core is entity basic_trigger_core is
port ( port (
wb_rst_i : in STD_LOGIC; wb_rst_i : in STD_LOGIC;
wb_clk_i : in STD_LOGIC; wb_clk_i : in STD_LOGIC;
pulse_i : in STD_LOGIC; pulse_i : in STD_LOGIC;
pulse_o : out STD_LOGIC; pulse_o : out STD_LOGIC;
pulse_n_o : out STD_LOGIC; pulse_n_o : out STD_LOGIC;
led_o : out STD_LOGIC; crop_o : out STD_LOGIC;
level_i : in STD_LOGIC --! 0 here means ttl led_o : out STD_LOGIC
); );
end basic_trigger_core; end basic_trigger_core;
...@@ -45,11 +45,12 @@ architecture Behavioral of basic_trigger_core is ...@@ -45,11 +45,12 @@ architecture Behavioral of basic_trigger_core is
signal s_deglitched_pulse : STD_LOGIC; signal s_deglitched_pulse : STD_LOGIC;
signal s_deglitched_pulse_d0 : STD_LOGIC; signal s_deglitched_pulse_d0 : STD_LOGIC;
signal s_pulse_parity : STD_LOGIC;
signal s_monostable : STD_LOGIC;
begin begin
s_pulse <= pulse_i;
s_pulse <= pulse_i;
inst_debo: gc_debouncer inst_debo: gc_debouncer
generic map( g_LENGTH => 2) generic map( g_LENGTH => 2)
...@@ -60,7 +61,8 @@ begin ...@@ -60,7 +61,8 @@ begin
glitch_mask => "11"); glitch_mask => "11");
pulse_monostable : gc_simple_monostable pulse_monostable : gc_simple_monostable
generic map (g_PULSE_LENGTH => 20) generic map (g_PULSE_LENGTH => 16) --! We remove the stages of deglitching
--! to produce 1us sharp at the output
port map (rst => wb_rst_i, port map (rst => wb_rst_i,
clk => wb_clk_i, clk => wb_clk_i,
input => s_deglitched_pulse, input => s_deglitched_pulse,
...@@ -68,7 +70,7 @@ begin ...@@ -68,7 +70,7 @@ begin
output_n => pulse_n_o); output_n => pulse_n_o);
led_monostable : gc_simple_monostable led_monostable : gc_simple_monostable
generic map (g_PULSE_LENGTH => 100000000) --! 500ms generic map (g_PULSE_LENGTH => 2000000) --! 500ms
port map ( port map (
rst => wb_rst_i, rst => wb_rst_i,
clk => wb_clk_i, clk => wb_clk_i,
...@@ -76,4 +78,5 @@ begin ...@@ -76,4 +78,5 @@ begin
output => led_o); output => led_o);
--output_n not connected --output_n not connected
end Behavioral; end Behavioral;
...@@ -65,33 +65,40 @@ end basic_trigger_top; ...@@ -65,33 +65,40 @@ end basic_trigger_top;
architecture Behavioral of basic_trigger_top is architecture Behavioral of basic_trigger_top is
signal s_pulse_i : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); signal s_pulse_i : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_pulse_i_rear : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); signal s_pulse_i_rear : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_pulse_i_front : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); signal s_pulse_i_front : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_pulse_o : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); signal s_pulse_o_front : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_pulse_n_o : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); signal s_pulse_o : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_led : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); signal s_pulse_o_d0 : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_pulse_n_o : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_led : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_level : STD_LOGIC; signal s_crop : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1) := (others => '0');
signal s_fpga_o_en : STD_LOGIC; signal s_level : STD_LOGIC;
signal s_fpga_o_ttl_en : STD_LOGIC;
signal s_fpga_o_inv_en : STD_LOGIC;
signal s_fpga_o_blo_en : STD_LOGIC;
signal s_rst : STD_LOGIC_VECTOR(7 downto 0) := (others => '1'); signal s_fpga_o_en : STD_LOGIC;
signal s_fpga_o_ttl_en : STD_LOGIC;
signal s_fpga_o_inv_en : STD_LOGIC;
signal s_fpga_o_blo_en : STD_LOGIC;
component basic_trigger_core is signal s_rst : STD_LOGIC_VECTOR(7 downto 0) := (others => '1');
port (wb_rst_i : in STD_LOGIC;
wb_clk_i : in STD_LOGIC; type delay_array is array (g_NUMBER_OF_CHANNELS downto 1)
of STD_LOGIC_VECTOR(3 downto 0);
pulse_i : in STD_LOGIC; signal s_pulse_i_reg : delay_array;
pulse_o : out STD_LOGIC;
pulse_n_o : out STD_LOGIC;
led_o : out STD_LOGIC; component basic_trigger_core is
port (wb_rst_i : in STD_LOGIC;
wb_clk_i : in STD_LOGIC;
level_i : in STD_LOGIC); pulse_i : in STD_LOGIC;
pulse_o : out STD_LOGIC;
pulse_n_o : out STD_LOGIC;
led_o : out STD_LOGIC);
end component; end component;
begin begin
...@@ -100,15 +107,16 @@ begin ...@@ -100,15 +107,16 @@ begin
led_pw_o <= '0'; led_pw_o <= '0';
led_err_o <= '1'; led_err_o <= '1';
led_ttl_o <= s_level; led_ttl_o <= not(s_level);
led_link_up_o <= '1'; led_link_up_o <= '1';
led_pps_o <= '1'; led_pps_o <= '1';
led_wr_ok_o <= '1'; led_wr_ok_o <= '1';
s_pulse_i_front <= pulse_i_front when s_level = '0' else not(pulse_i_front); --! s_level '1' means TTL input, as we have one inverter in the board we
--! invert here.
s_pulse_i <= s_pulse_i_front or pulse_i_rear; s_pulse_i_front <= not(pulse_i_front) when s_level = '1' else pulse_i_front;
s_pulse_i <= s_pulse_i_front or not(pulse_i_rear);
fpga_o_en <= s_fpga_o_en when switch_i = '1' else '0'; fpga_o_en <= s_fpga_o_en when switch_i = '1' else '0';
...@@ -119,12 +127,11 @@ begin ...@@ -119,12 +127,11 @@ begin
led_o_front <= not(s_led);--! No need of accurate sync, hence we place led_o_front <= not(s_led);--! No need of accurate sync, hence we place
led_o_rear <= not(s_led);--! some combinatorial here. led_o_rear <= not(s_led);--! some combinatorial here.
inv_o <= inv_i;--! As we have one Schmitt inverter in the input, inv_o(4 downto 3) <= inv_i(4 downto 3);--! As we have one Schmitt inverter in the input,
--! and a buffer in the output, there's no need --! and a buffer in the output, there's no need
--! of invert here. --! of invert here.
i_repetitors: for i in 1 to g_NUMBER_OF_CHANNELS generate i_repetitors: for i in 1 to g_NUMBER_OF_CHANNELS generate
begin begin
trigger: basic_trigger_core trigger: basic_trigger_core
...@@ -136,11 +143,23 @@ begin ...@@ -136,11 +143,23 @@ begin
pulse_o => s_pulse_o(i), pulse_o => s_pulse_o(i),
pulse_n_o => s_pulse_n_o(i), pulse_n_o => s_pulse_n_o(i),
led_o => s_led(i), -- pulse_parity_o => s_pulse_parity(i),
led_o => s_led(i));
level_i => '0');
end generate i_repetitors; end generate i_repetitors;
gen_delays : for j in 1 to g_NUMBER_OF_CHANNELS generate
p_delays : process(clk_i) is
begin
if rising_edge(clk_i) then
s_pulse_o_d0 <= s_pulse_o;
-- s_pulse_parity_d0 <= s_pulse_parity;
s_pulse_i_reg(j)(0) <= s_pulse_i(j);
for i in 1 to 3 loop
s_pulse_i_reg(j)(i) <= s_pulse_i_reg(j)(i-1); --!Another one to improve meta
end loop;
end if;
end process;
end generate;
p_reset_chain : process(clk_i) is p_reset_chain : process(clk_i) is
begin begin
...@@ -170,28 +189,63 @@ begin ...@@ -170,28 +189,63 @@ begin
end if; end if;
end process p_reset_chain; end process p_reset_chain;
pulse_o_front <= s_pulse_o_front when level = '1'
else not(s_pulse_o_front);
--! We register the outputs for better synchronization of the outputs inv_o(2) <= s_crop(2);
p_reg_output : process(clk_i) is inv_o(1) <= s_crop(1);
gen_crop : for i in 1 to g_NUMBER_OF_CHANNELS generate
begin begin
if rising_edge(clk_i) then p_reg_crop : process (clk_i) is
if s_rst(7) = '1' then begin
pulse_o_rear <= (others => '0'); if rising_edge(clk_i) then
if s_level = '0' then if s_pulse_o(i) = '0' then
pulse_o_front <= (others => '0'); s_crop(i) <= '1';
else if s_pulse_i_reg(i)(3) = '0' then --! This should be working one clock
pulse_o_front <= (others => '1'); --! below s_pulse_o
s_crop(i) <= '0'; --! See gen_output to see the match
end if;
if s_pulse_i(i) = '0' then --! Sharp crop. Metastability
s_crop(i) <= '0'; --! problems?
end if;
end if; end if;
else
pulse_o_rear <= s_pulse_o;
case s_level is
when '0' =>
pulse_o_front <= s_pulse_o;
when others =>
pulse_o_front <= s_pulse_n_o;
end case;
end if; end if;
end if; end process;
end process; end generate;
--! We register the outputs for better synchronization of the outputs
gen_output : for i in 1 to g_NUMBER_OF_CHANNELS generate
begin
p_comb_output : process(s_pulse_i(i),
s_pulse_o(i)) is
begin
pulse_o_rear(i) <= '0';
s_pulse_o_front(i) <= '0';
case s_pulse_o(i) is
when '0' =>
--! We just have just finished the pulse and must be cropped.
--! In this case, we assume that the both input sources have an
--! RC filter, so we can improve jitter performance of the
--! first edge by bypassing the signal (no clocking).
if s_pulse_i(i) = '1' then
-- pulse_o_rear(i) <= '1';
if s_crop(i) = '0' then
--! However, glitches of n[DEGLITCHING]*clk length can happen.
s_pulse_o_front(i) <= '1';
else
s_pulse_o_front(i) <= '0';
end if;
else
end if;
when others =>
--! In this other case, we should keep on outputing the pulse
-- pulse_o_rear(i) <= '1';
s_pulse_o_front(i) <= '1';
end case;
end process;
end generate;
end Behavioral; end Behavioral;
...@@ -58,27 +58,27 @@ ARCHITECTURE behavior OF trigger_top_tb IS ...@@ -58,27 +58,27 @@ ARCHITECTURE behavior OF trigger_top_tb IS
fpga_o_blo_en : out STD_LOGIC; fpga_o_blo_en : out STD_LOGIC;
level_i : in STD_LOGIC; level : in STD_LOGIC;
switch_i : in STD_LOGIC; --! General enable switch_i : in STD_LOGIC; --! General enable
manual_rst_n_o : out STD_LOGIC; --! It allows power sequencing of the manual_rst_n_o : out STD_LOGIC; --! It allows power sequencing of the
--! 24V rail after a security given --! 24V rail after a security given
--! delay --! delay
pulse_i_front : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS - 1 downto 0); pulse_i_front : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS - 1 downto 0); pulse_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_i_rear : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS - 1 downto 0); pulse_i_rear : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS - 1 downto 0); pulse_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
led_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS - 1 downto 0); led_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
led_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS - 1 downto 0); led_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
--! WR LEDs not to let them ON --! WR LEDs not to let them ON
led_link_up_o : out STD_LOGIC; led_link_up_o : out STD_LOGIC;
led_pps_o : out STD_LOGIC; led_pps_o : out STD_LOGIC;
led_wr_ok_o : out STD_LOGIC; led_wr_ok_o : out STD_LOGIC;
inv_i : in STD_LOGIC_VECTOR(3 downto 0); inv_i : in STD_LOGIC_VECTOR(4 downto 1);
inv_o : out STD_LOGIC_VECTOR(3 downto 0)); inv_o : out STD_LOGIC_VECTOR(4 downto 1));
end component; end component;
...@@ -88,6 +88,7 @@ ARCHITECTURE behavior OF trigger_top_tb IS ...@@ -88,6 +88,7 @@ ARCHITECTURE behavior OF trigger_top_tb IS
begin begin
uut: basic_trigger_top uut: basic_trigger_top
generic map(g_NUMBER_OF_CHANNELS => 6)
port map( port map(
clk_i => s_clk, clk_i => s_clk,
-- rst_i => s_rst, -- rst_i => s_rst,
...@@ -101,7 +102,7 @@ begin ...@@ -101,7 +102,7 @@ begin
fpga_o_inv_en => fpga_o_inv_en, fpga_o_inv_en => fpga_o_inv_en,
fpga_o_blo_en => fpga_o_blo_en, fpga_o_blo_en => fpga_o_blo_en,
level_i => level_i, level => level_i,
switch_i => switch_i, switch_i => switch_i,
manual_rst_n_o => manual_rst_n_o , manual_rst_n_o => manual_rst_n_o ,
...@@ -137,11 +138,11 @@ begin ...@@ -137,11 +138,11 @@ begin
procedure initial_cond(level : STD_LOGIC) is procedure initial_cond(level : STD_LOGIC) is
begin begin
-- s_rst <= '1'; -- s_rst <= '1';
switch_i <= '0'; level_i <= level;
switch_i <= '1';
inv_i <= (others => '0'); inv_i <= (others => '0');
pulse_i_front <= (others => level); pulse_i_front <= (others => not(level));
pulse_i_rear <= (others => '0'); pulse_i_rear <= (others => '0');
level_i <= level;
wait for CLK_PERIOD*50; wait for CLK_PERIOD*50;
-- s_rst <= '0'; -- s_rst <= '0';
wait for CLK_PERIOD*2; wait for CLK_PERIOD*2;
...@@ -155,23 +156,22 @@ begin ...@@ -155,23 +156,22 @@ begin
level : STD_LOGIC) is level : STD_LOGIC) is
variable v_pulse : STD_LOGIC := level; variable v_pulse : STD_LOGIC := level;
begin begin
pulse(channel) <= level;
wait until rising_edge(s_clk);
pulse(channel) <= not(level); pulse(channel) <= not(level);
wait for length; wait until rising_edge(s_clk);
pulse(channel) <= level; pulse(channel) <= level;
wait for length;
pulse(channel) <= not(level);
wait until rising_edge(s_clk); wait until rising_edge(s_clk);
end; end;
procedure input_front_pulse (length : time; channel : NATURAL; procedure input_front_pulse (length : time; channel : NATURAL) is
level : STD_LOGIC) is
begin begin
input_pulse (pulse_i_front, channel, length, level); input_pulse (pulse_i_front, channel, length, level_i);
end; end;
procedure input_rear_pulse (length : time; channel : NATURAL) is procedure input_rear_pulse (length : time; channel : NATURAL) is
begin begin
input_pulse (pulse_i_rear, channel, length, '0'); input_pulse (pulse_i_rear, channel, length, '1');
end; end;
procedure input_two_pulses (channel : NATURAL; level : STD_LOGIC; procedure input_two_pulses (channel : NATURAL; level : STD_LOGIC;
...@@ -202,18 +202,18 @@ begin ...@@ -202,18 +202,18 @@ begin
--! First we put one pulse from the Blocking part, then we wait one-clock --! First we put one pulse from the Blocking part, then we wait one-clock
--! and lastly we put another clock from the TTL input --! and lastly we put another clock from the TTL input
initial_cond('0'); initial_cond('1');
input_rear_pulse (1200 ns, 0); input_rear_pulse (1200 ns, 0);
wait until rising_edge(s_clk); wait until rising_edge(s_clk);
input_front_pulse (1200 ns, 0, level_i); input_front_pulse (1200 ns, 0);
wait for 40*CLK_PERIOD; wait for 40*CLK_PERIOD;
--! We reboot the machine and change the switch to indicate level_i is --! We reboot the machine and change the switch to indicate level_i is
--! TTL_N --! TTL_N
initial_cond('1'); initial_cond('0');
input_rear_pulse (1200 ns, 0); input_rear_pulse (1200 ns, 0);
wait until rising_edge(s_clk); wait until rising_edge(s_clk);
input_front_pulse (1200 ns, 0, level_i); input_front_pulse (1200 ns, 0);
input_two_pulses(0, '1', input_two_pulses(0, '1',
1000 ns, 1000 ns,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment