Commit 514754e8 authored by gilsoriano@gmail.com's avatar gilsoriano@gmail.com

Added basic_trigger (synchr @200MHz) ready for basic repetition. A combinatorial…

Added basic_trigger (synchr @200MHz) ready for basic repetition. A combinatorial module with low repetition jitter (basic_trigger_async) is added to the repo, as well.
parent 0aa0bdda
......@@ -7,15 +7,15 @@
##----------------------------------------
#
#
NET "clk_i" LOC = E16;
NET "clk_i" IOSTANDARD = "LVCMOS33";
NET "clk_i" TNM_NET = "clk_i";
TIMESPEC TS_clk_i = PERIOD "clk_i" 20 MHz HIGH 50%;
#NET "clk_i" LOC = E16;
# NET "clk_i" IOSTANDARD = "LVCMOS33";
# NET "clk_i" TNM_NET = "clk_i";
# TIMESPEC TS_clk_i = PERIOD "clk_i" 20 MHz HIGH 50%;
#
#NET "FPGA_CLK_N" LOC = G11;
# NET "FPGA_CLK_N" IOSTANDARD = "LVDS_25";
#NET "FPGA_CLK_P" LOC = H12;
# NET "FPGA_CLK_P" IOSTANDARD = "LVDS_25";
NET "FPGA_CLK_N" LOC = G11;
NET "FPGA_CLK_N" IOSTANDARD = "LVDS_25";
NET "FPGA_CLK_P" LOC = H12;
NET "FPGA_CLK_P" IOSTANDARD = "LVDS_25";
#
#NET "FPGA_SYSRESET_N" LOC = L20;
NET "manual_rst_n_o" LOC = T22;
......
......@@ -49,7 +49,6 @@ architecture Behavioral of basic_trigger_core is
begin
s_pulse <= pulse_i;
inst_debo: gc_debouncer
......@@ -61,8 +60,7 @@ begin
glitch_mask => "11");
pulse_monostable : gc_simple_monostable
generic map (g_PULSE_LENGTH => 16) --! We remove the stages of deglitching
--! to produce 1us sharp at the output
generic map (g_PULSE_LENGTH => 195) --! Produce 1us sharp at the output
port map (rst => wb_rst_i,
clk => wb_clk_i,
input => s_deglitched_pulse,
......@@ -70,7 +68,7 @@ begin
output_n => pulse_n_o);
led_monostable : gc_simple_monostable
generic map (g_PULSE_LENGTH => 2000000) --! 500ms
generic map (g_PULSE_LENGTH => 10000000) --! 250ms
port map (
rst => wb_rst_i,
clk => wb_clk_i,
......@@ -78,5 +76,4 @@ begin
output => led_o);
--output_n not connected
end Behavioral;
......@@ -21,14 +21,17 @@
--
----------------------------------------------------------------------------------
library IEEE;
library unisim;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use UNISIM.VCOMPONENTS.ALL;
entity basic_trigger_top is
generic(g_NUMBER_OF_CHANNELS : NATURAL := 6);
port (
clk_i : in STD_LOGIC;
FPGA_CLK_P : in STD_LOGIC;
FPGA_CLK_N : in STD_LOGIC;
led_pw_o : out STD_LOGIC;
led_err_o : out STD_LOGIC;
......@@ -53,8 +56,9 @@ entity basic_trigger_top is
led_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
led_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
--! WR LEDs not to let them ON
--! This LED will show the status of the PLL
led_link_up_o : out STD_LOGIC;
--! WR LEDs not to let them ON
led_pps_o : out STD_LOGIC;
led_wr_ok_o : out STD_LOGIC;
......@@ -66,15 +70,13 @@ end basic_trigger_top;
architecture Behavioral of basic_trigger_top is
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_front : 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_o : 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_crop : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1) := (others => '0');
signal s_crop : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1)
:= (others => '0');
signal s_level : STD_LOGIC;
......@@ -83,12 +85,23 @@ signal s_crop : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1) := (others => '
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_clk_125m_i : STD_LOGIC;
signal s_clk_125m_prebufg : STD_LOGIC;
signal s_clk_125m : STD_LOGIC;
signal s_clk_200m_prebufg : STD_LOGIC;
signal s_clk_200m : STD_LOGIC;
signal s_clk_fb_prebufg : STD_LOGIC;
signal s_clk_fb : STD_LOGIC;
constant c_RST_CLKS : NATURAL := 256; --! @8ns
signal s_rst : STD_LOGIC_VECTOR(c_RST_CLKS - 1 downto 0)
:= (others => '1');
type delay_array is array (g_NUMBER_OF_CHANNELS downto 1)
of STD_LOGIC_VECTOR(3 downto 0);
signal s_pulse_i_reg : delay_array;
signal s_locked : STD_LOGIC;
component basic_trigger_core is
port (wb_rst_i : in STD_LOGIC;
......@@ -98,18 +111,22 @@ signal s_crop : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1) := (others => '
pulse_o : out STD_LOGIC;
pulse_n_o : out STD_LOGIC;
crop_o : out STD_LOGIC;
led_o : out STD_LOGIC);
end component;
begin
--! Level 0 means TTL_N Switch UP
--! 1 means TTL Switch DOWN
s_level <= level;
led_pw_o <= '0';
led_err_o <= '1';
led_ttl_o <= not(s_level);
led_link_up_o <= '1';
led_link_up_o <= not(s_locked);
led_pps_o <= '1';
led_wr_ok_o <= '1';
......@@ -119,7 +136,6 @@ begin
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_ttl_en <= s_fpga_o_ttl_en;
fpga_o_inv_en <= s_fpga_o_inv_en;
fpga_o_blo_en <= s_fpga_o_blo_en;
......@@ -127,50 +143,82 @@ begin
led_o_front <= not(s_led);--! No need of accurate sync, hence we place
led_o_rear <= not(s_led);--! some combinatorial here.
inv_o(4 downto 3) <= inv_i(4 downto 3);--! As we have one Schmitt inverter in the input,
pulse_o_front <= s_pulse_o when level = '1'
else not(s_pulse_o);
pulse_o_rear <= s_pulse_o;
inv_o <= inv_i;--! As we have one Schmitt inverter in the input,
--! and a buffer in the output, there's no need
--! of invert here.
U_Buf_CLK_PLL : IBUFGDS
generic map (DIFF_TERM => TRUE,
IBUF_LOW_PWR => TRUE)
port map (O => s_clk_125m_i, -- Buffer output
I => FPGA_CLK_P,
IB => FPGA_CLK_N);
-- set up the fabric PLL_BASE to drive the BUFPLL
pll_base_inst : PLL_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLK_FEEDBACK => "CLKFBOUT",
COMPENSATION => "SYSTEM_SYNCHRONOUS",
DIVCLK_DIVIDE => 1, CLKFBOUT_MULT => 8, CLKFBOUT_PHASE => 0.000,
CLKOUT0_DIVIDE => 8, CLKOUT0_PHASE => 0.000, CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT1_DIVIDE => 5, CLKOUT1_PHASE => 0.000, CLKOUT1_DUTY_CYCLE => 0.500,
CLKIN_PERIOD => 8.0,
REF_JITTER => 0.010)
port map (
-- Output clocks
CLKFBOUT => s_clk_fb_prebufg,
CLKOUT0 => s_clk_125m_prebufg,
CLKOUT1 => s_clk_200m_prebufg,
CLKOUT2 => open, CLKOUT3 => open,
CLKOUT4 => open, CLKOUT5 => open,
-- Status and control signals
LOCKED => s_locked, RST => s_rst(c_RST_CLKS - 1),
-- Input clock control
CLKFBIN => s_clk_fb,
CLKIN => s_clk_125m_i);
s_clk_125m_bufg : BUFG
port map (O => s_clk_125m, I => s_clk_125m_prebufg);
s_clk_200m_bufg : BUFG
port map (O => s_clk_200m, I => s_clk_200m_prebufg);
s_clk_fb_bufg : BUFG
port map (O => s_clk_fb, I => s_clk_fb_prebufg);
i_repetitors: for i in 1 to g_NUMBER_OF_CHANNELS generate
begin
trigger: basic_trigger_core
port map (
wb_rst_i => s_rst(7),
wb_clk_i => clk_i,
wb_rst_i => s_rst(c_RST_CLKS - 1),
wb_clk_i => s_clk_200m,
pulse_i => s_pulse_i(i),
pulse_o => s_pulse_o(i),
pulse_n_o => s_pulse_n_o(i),
-- pulse_parity_o => s_pulse_parity(i),
led_o => s_led(i));
crop_o => open,
led_o => s_led(i));
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(s_clk_125m_i) is
begin
if rising_edge(clk_i) then
if rising_edge(s_clk_125m_i) then
s_rst(0) <= '0';
for i in 1 to 7 loop
for i in 1 to c_RST_CLKS - 1 loop
s_rst(i) <= s_rst(i-1);
end loop;
if s_rst(7) = '1' then
if s_rst(c_RST_CLKS - 1) = '1' then
--! First we reset the FPGA general output enable
--! Then we let one clock delay for the rest of signals
manual_rst_n_o <= '0';
......@@ -189,63 +237,5 @@ begin
end if;
end process p_reset_chain;
pulse_o_front <= s_pulse_o_front when level = '1'
else not(s_pulse_o_front);
inv_o(2) <= s_crop(2);
inv_o(1) <= s_crop(1);
gen_crop : for i in 1 to g_NUMBER_OF_CHANNELS generate
begin
p_reg_crop : process (clk_i) is
begin
if rising_edge(clk_i) then
if s_pulse_o(i) = '0' then
s_crop(i) <= '1';
if s_pulse_i_reg(i)(3) = '0' then --! This should be working one clock
--! 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;
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;
-- TestBench Template
LIBRARY ieee;
LIBRARY unisim;
library modelsim_lib;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE unisim.vcomponents.ALL;
use modelsim_lib.util.ALL;
ENTITY trigger_top_tb IS
END trigger_top_tb;
......@@ -10,10 +15,12 @@ ENTITY trigger_top_tb IS
ARCHITECTURE behavior OF trigger_top_tb IS
constant c_NUMBER_OF_CHANNELS : NATURAL := 6;
constant CLK_PERIOD : time := 50 ns;
constant CLK_PERIOD : time := 8 ns;
constant CLK_PLL_PERIOD : time := 5 ns;
signal s_clk : STD_LOGIC;
-- signal s_rst : STD_LOGIC;
signal s_clk_125m_p : STD_LOGIC;
signal s_clk_125m_n : STD_LOGIC;
signal led_pw_o : STD_LOGIC;
signal led_err_o : STD_LOGIC;
......@@ -43,10 +50,15 @@ ARCHITECTURE behavior OF trigger_top_tb IS
signal inv_i : STD_LOGIC_VECTOR(3 downto 0);
signal inv_o : STD_LOGIC_VECTOR(3 downto 0);
--! Signal sniffed from basic_trigger_top.vhd
signal s_clk_200m : STD_LOGIC;
component basic_trigger_top is
generic(g_NUMBER_OF_CHANNELS : NATURAL := 6);
port (
clk_i : in STD_LOGIC;
FPGA_CLK_P : in STD_LOGIC;
FPGA_CLK_N : in STD_LOGIC;
led_pw_o : out STD_LOGIC;
led_err_o : out STD_LOGIC;
......@@ -81,17 +93,34 @@ ARCHITECTURE behavior OF trigger_top_tb IS
inv_o : out STD_LOGIC_VECTOR(4 downto 1));
end component;
begin
--! @brief Process to bypass internal signals requiered for correct
--! use of spi_analyser
p_sig_spy : process is
begin
init_signal_spy("/uut/s_clk_200m", "s_clk_200m", 1);
wait;
end process p_sig_spy;
s_clk125m_process :process
begin
s_clk <= '1';
wait for CLK_PERIOD/2;
s_clk <= '0';
wait for CLK_PERIOD/2;
end process;
begin
OBUFDS_inst : OBUFDS
generic map (IOSTANDARD => "DEFAULT")
port map (O => s_clk_125m_p, OB => s_clk_125m_n,
I => s_clk);
uut: basic_trigger_top
generic map(g_NUMBER_OF_CHANNELS => 6)
port map(
clk_i => s_clk,
-- rst_i => s_rst,
FPGA_CLK_P => s_clk_125m_p,
FPGA_CLK_N => s_clk_125m_n,
led_pw_o => led_pw_o,
led_err_o => led_err_o,
......@@ -123,30 +152,27 @@ begin
inv_o => inv_o);
s_clk_process :process
begin
s_clk <= '1';
wait for CLK_PERIOD/2;
s_clk <= '0';
wait for CLK_PERIOD/2;
end process;
tb_proc: process
procedure initial_cond(level : STD_LOGIC) is
procedure initial_cond(level : STD_LOGIC;
wait_link_up : BOOLEAN) is
begin
-- s_rst <= '1';
level_i <= level;
switch_i <= '1';
inv_i <= (others => '0');
pulse_i_front <= (others => not(level));
pulse_i_rear <= (others => '0');
wait for CLK_PERIOD*50;
--! The inputs that go to the FPGA are negated
inv_i <= (others => '1');
--! The inputs that go to the FPGA are negated
pulse_i_front <= (others => level);
--! The inputs that go to the FPGA are negated
pulse_i_rear <= (others => '1');
if wait_link_up = TRUE then
wait until falling_edge(led_link_up_o);
end if;
wait for CLK_PLL_PERIOD*50;
-- s_rst <= '0';
wait for CLK_PERIOD*2;
wait until rising_edge(s_clk);
wait for CLK_PLL_PERIOD*2;
wait until rising_edge(s_clk_200m);
end;
procedure input_pulse (signal pulse : out
......@@ -156,15 +182,18 @@ begin
level : STD_LOGIC) is
variable v_pulse : STD_LOGIC := level;
begin
pulse(channel) <= not(level);
wait until rising_edge(s_clk);
--! As both the read and front are negated in V1 (rear is NOT negated
--! in V2) we place the default signal level of the pulse as 'level'
pulse(channel) <= level;
wait for length;
wait until rising_edge(s_clk_200m);
pulse(channel) <= not(level);
wait until rising_edge(s_clk);
wait for length;
pulse(channel) <= level;
wait until rising_edge(s_clk_200m);
end;
procedure input_front_pulse (length : time; channel : NATURAL) is
procedure input_front_pulse (length : time; channel : NATURAL;
level_i: STD_LOGIC) is
begin
input_pulse (pulse_i_front, channel, length, level_i);
end;
......@@ -181,18 +210,18 @@ begin
begin
pulse_i_front(channel) <= level;
pulse_i_rear(channel) <= '0';
wait until rising_edge(s_clk);
wait until rising_edge(s_clk_200m);
pulse_i_rear(channel) <= '1';
wait for offset;
wait until rising_edge(s_clk);
wait until rising_edge(s_clk_200m);
pulse_i_front(channel) <= not(level);
wait for length1 - offset;
wait until rising_edge(s_clk);
wait until rising_edge(s_clk_200m);
pulse_i_rear(channel) <= '0';
wait for length2 - length1;
wait until rising_edge(s_clk);
wait until rising_edge(s_clk_200m);
pulse_i_front(channel) <= level;
wait until rising_edge(s_clk);
wait until rising_edge(s_clk_200m);
end;
begin
......@@ -202,25 +231,25 @@ begin
--! First we put one pulse from the Blocking part, then we wait one-clock
--! and lastly we put another clock from the TTL input
initial_cond('1');
initial_cond('1', TRUE);
input_rear_pulse (1200 ns, 0);
wait until rising_edge(s_clk);
input_front_pulse (1200 ns, 0);
wait until rising_edge(s_clk_200m);
input_front_pulse (1200 ns, 0, '1');
wait for 40*CLK_PERIOD;
wait for 100*CLK_PLL_PERIOD;
--! We reboot the machine and change the switch to indicate level_i is
--! TTL_N
initial_cond('0');
initial_cond('0', FALSE);
input_rear_pulse (1200 ns, 0);
wait until rising_edge(s_clk);
input_front_pulse (1200 ns, 0);
wait until rising_edge(s_clk_200m);
input_front_pulse (1200 ns, 0, '1');
input_two_pulses(0, '1',
1000 ns,
1000 ns,
212 ns);
wait for 40*CLK_PERIOD;
wait for 40*CLK_PLL_PERIOD;
assert false report "End of test." severity failure;
end process;
......
This diff is collapsed.
---------------------------------------------------------------------------------
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 09:58:06 10/12/2011
-- Design Name: HDL trigger
-- Module Name: trigger - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description: This is the wishbone trigger which receives a debounced input
-- and outputs a trigger signal for the pulse converter
-- Dependencies: none
--
-- Revision:
-- Revision 0.1
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.ctdah_pkg.ALL;
entity basic_trigger_core is
port (
wb_rst_i : in STD_LOGIC;
wb_clk_i : in STD_LOGIC;
pulse_i : in STD_LOGIC;
pulse_o : out STD_LOGIC;
pulse_n_o : out STD_LOGIC;
crop_o : out STD_LOGIC;
led_o : out STD_LOGIC);
end basic_trigger_core;
architecture Behavioral of basic_trigger_core is
signal s_pulse_meta0 : STD_LOGIC;
signal s_pulse : STD_LOGIC;
signal s_pulse_n : STD_LOGIC;
signal s_pulse_o_n : STD_LOGIC;
signal s_pulse_o : STD_LOGIC;
signal s_pulse_i_reg : STD_LOGIC_VECTOR(2 downto 0);
signal s_crop : STD_LOGIC := '0';
begin
pulse_o <= s_pulse_o;
pulse_n_o <= not(s_pulse_o);
crop_o <= s_crop;
inst_ff: gc_ff
port map(Q => s_pulse_meta0,
C => wb_clk_i,
CLR => wb_rst_i,
D => pulse_i);
pulse_monostable : gc_simple_monostable
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,
clk => wb_clk_i,
input => s_pulse_meta0,
output => s_pulse,
output_n => s_pulse_n);
led_monostable : gc_simple_monostable
generic map (g_PULSE_LENGTH => 2000000) --! 500ms
port map (
rst => wb_rst_i,
clk => wb_clk_i,
input => s_pulse_meta0,
output => led_o);
--output_n not connected
p_delays : process(wb_clk_i) is
begin
if rising_edge(wb_clk_i) then
s_pulse_i_reg(0) <= pulse_i;
for i in 1 to 2 loop
s_pulse_i_reg(i) <= s_pulse_i_reg(i-1);
end loop;
end if;
end process;
p_reg_crop : process (wb_clk_i) is
begin
if rising_edge(wb_clk_i) then
if wb_rst_i = '1' then
s_crop <= '0';
else
if s_pulse = '0' then
s_crop <= '1';
if s_pulse_i_reg(2) = '0' then --! Not until three clocks the
s_crop <= '0'; --! signal is valid.
end if;
if pulse_i = '0' then --! Sharp crop. Metastability
s_crop <= '0'; --! problems solved in V2.
end if;
end if;
end if;
end if;
end process;
p_comb_output : process(pulse_i, s_pulse, s_crop) is
begin
s_pulse_o <= '0';
case s_pulse 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 pulse_i = '1' then
if s_crop = '0' then
s_pulse_o <= '1';
else
s_pulse_o <= '0';
end if;
else
end if;
when others =>
--! In this other case, we should keep on outputing the pulse
s_pulse_o <= '1';
end case;
end process;
end Behavioral;
----------------------------------------------------------------------------------
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 09:58:06 10/12/2011
-- Design Name: HDL trigger top
-- Module Name: trigger - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description: This is the wishbone trigger which receives a input
-- and outputs a trigger signal for the pulse converter.
-- It internally debounces the inputs and control the output
-- driver.
-- The registers it has can be modified via wishbone access.
-- Dependencies: none
--
-- Revision:
-- Revision 0.1
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity basic_trigger_top is
generic(g_NUMBER_OF_CHANNELS : NATURAL := 6);
port (
clk_i : in STD_LOGIC;
led_pw_o : out STD_LOGIC;
led_err_o : out STD_LOGIC;
led_ttl_o : out STD_LOGIC;
fpga_o_en : out STD_LOGIC;
fpga_o_ttl_en : out STD_LOGIC;
fpga_o_inv_en : out STD_LOGIC;
fpga_o_blo_en : out STD_LOGIC;
level : in STD_LOGIC;
switch_i : in STD_LOGIC; --! General enable
manual_rst_n_o : out STD_LOGIC; --! It allows power sequencing of the
--! 24V rail after a security given
--! delay
pulse_i_front : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_i_rear : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
led_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
led_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
--! WR LEDs not to let them ON
led_link_up_o : out STD_LOGIC;
led_pps_o : out STD_LOGIC;
led_wr_ok_o : out STD_LOGIC;
inv_i : in STD_LOGIC_VECTOR(4 downto 1);
inv_o : out STD_LOGIC_VECTOR(4 downto 1));
end basic_trigger_top;
architecture Behavioral of basic_trigger_top is
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_front : 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_o : 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_crop : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
signal s_level : STD_LOGIC;
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;
signal s_rst : STD_LOGIC_VECTOR(7 downto 0) := (others => '1');
type delay_array is array (g_NUMBER_OF_CHANNELS downto 1)
of STD_LOGIC_VECTOR(3 downto 0);
signal s_pulse_i_reg : delay_array;
component basic_trigger_core is
port (wb_rst_i : in STD_LOGIC;
wb_clk_i : in STD_LOGIC;
pulse_i : in STD_LOGIC;
pulse_o : out STD_LOGIC;
pulse_n_o : out STD_LOGIC;
crop_o : out STD_LOGIC;
led_o : out STD_LOGIC);
end component;
begin
s_level <= level;
led_pw_o <= '0';
led_err_o <= '1';
led_ttl_o <= not(s_level);
led_link_up_o <= '1';
led_pps_o <= '1';
led_wr_ok_o <= '1';
--! s_level '1' means TTL input, as we have one inverter in the board we
--! invert here.
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_ttl_en <= s_fpga_o_ttl_en;
fpga_o_inv_en <= s_fpga_o_inv_en;
fpga_o_blo_en <= s_fpga_o_blo_en;
led_o_front <= not(s_led);--! No need of accurate sync, hence we place
led_o_rear <= not(s_led);--! some combinatorial here.
pulse_o_front <= s_pulse_o when level = '1'
else not(s_pulse_o);
pulse_o_rear <= s_pulse_o;
inv_o <= inv_i;
--! As we have one Schmitt inverter in the input,
--! and a buffer in the output, there's no need
--! of invert here.
i_repetitors: for i in 1 to g_NUMBER_OF_CHANNELS generate
begin
trigger: basic_trigger_core
port map (
wb_rst_i => s_rst(7),
wb_clk_i => clk_i,
pulse_i => s_pulse_i(i),
pulse_o => s_pulse_o(i),
pulse_n_o => s_pulse_n_o(i),
crop_o => s_crop(i),
led_o => s_led(i));
end generate i_repetitors;
p_reset_chain : process(clk_i) is
begin
if rising_edge(clk_i) then
s_rst(0) <= '0';
for i in 1 to 7 loop
s_rst(i) <= s_rst(i-1);
end loop;
if s_rst(7) = '1' then
--! First we reset the FPGA general output enable
--! Then we let one clock delay for the rest of signals
manual_rst_n_o <= '0';
s_fpga_o_en <= '0';
s_fpga_o_ttl_en <= '0';
s_fpga_o_inv_en <= '0';
s_fpga_o_blo_en <= '0';
else
manual_rst_n_o <= '1';
s_fpga_o_en <= '1';
s_fpga_o_ttl_en <= s_fpga_o_en;
s_fpga_o_inv_en <= s_fpga_o_en;
s_fpga_o_blo_en <= s_fpga_o_en;
end if;
end if;
end process p_reset_chain;
end Behavioral;
-- TestBench Template
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY trigger_top_tb IS
END trigger_top_tb;
ARCHITECTURE behavior OF trigger_top_tb IS
constant c_NUMBER_OF_CHANNELS : NATURAL := 6;
constant CLK_PERIOD : time := 50 ns;
signal s_clk : STD_LOGIC;
-- signal s_rst : STD_LOGIC;
signal led_pw_o : STD_LOGIC;
signal led_err_o : STD_LOGIC;
signal led_ttl_o : STD_LOGIC;
signal fpga_o_en : STD_LOGIC;
signal fpga_o_ttl_en : STD_LOGIC;
signal fpga_o_inv_en : STD_LOGIC;
signal fpga_o_blo_en : STD_LOGIC;
signal level_i : STD_LOGIC;
signal switch_i : STD_LOGIC;
signal manual_rst_n_o : STD_LOGIC;
signal pulse_i_front : STD_LOGIC_VECTOR(c_NUMBER_OF_CHANNELS - 1 downto 0);
signal pulse_o_front : STD_LOGIC_VECTOR(c_NUMBER_OF_CHANNELS - 1 downto 0);
signal pulse_i_rear : STD_LOGIC_VECTOR(c_NUMBER_OF_CHANNELS - 1 downto 0);
signal pulse_o_rear : STD_LOGIC_VECTOR(c_NUMBER_OF_CHANNELS - 1 downto 0);
signal led_o : STD_LOGIC_VECTOR(c_NUMBER_OF_CHANNELS - 1 downto 0);
signal led_link_up_o : STD_LOGIC;
signal led_pps_o : STD_LOGIC;
signal led_wr_ok_o : STD_LOGIC;
signal inv_i : STD_LOGIC_VECTOR(3 downto 0);
signal inv_o : STD_LOGIC_VECTOR(3 downto 0);
component basic_trigger_top is
generic(g_NUMBER_OF_CHANNELS : NATURAL := 6);
port (
clk_i : in STD_LOGIC;
led_pw_o : out STD_LOGIC;
led_err_o : out STD_LOGIC;
led_ttl_o : out STD_LOGIC;
fpga_o_en : out STD_LOGIC;
fpga_o_ttl_en : out STD_LOGIC;
fpga_o_inv_en : out STD_LOGIC;
fpga_o_blo_en : out STD_LOGIC;
level : in STD_LOGIC;
switch_i : in STD_LOGIC; --! General enable
manual_rst_n_o : out STD_LOGIC; --! It allows power sequencing of the
--! 24V rail after a security given
--! delay
pulse_i_front : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_i_rear : in STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
pulse_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
led_o_front : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
led_o_rear : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
--! WR LEDs not to let them ON
led_link_up_o : out STD_LOGIC;
led_pps_o : out STD_LOGIC;
led_wr_ok_o : out STD_LOGIC;
inv_i : in STD_LOGIC_VECTOR(4 downto 1);
inv_o : out STD_LOGIC_VECTOR(4 downto 1));
end component;
begin
uut: basic_trigger_top
generic map(g_NUMBER_OF_CHANNELS => 6)
port map(
clk_i => s_clk,
-- rst_i => s_rst,
led_pw_o => led_pw_o,
led_err_o => led_err_o,
led_ttl_o => led_ttl_o,
fpga_o_en => fpga_o_en,
fpga_o_ttl_en => fpga_o_ttl_en,
fpga_o_inv_en => fpga_o_inv_en,
fpga_o_blo_en => fpga_o_blo_en,
level => level_i,
switch_i => switch_i,
manual_rst_n_o => manual_rst_n_o ,
pulse_i_front => pulse_i_front,
pulse_o_front => pulse_o_front,
pulse_i_rear => pulse_i_rear,
pulse_o_rear => pulse_o_rear,
led_o_front => led_o,
led_o_rear => led_o,
led_link_up_o => led_link_up_o,
led_pps_o => led_pps_o,
led_wr_ok_o => led_wr_ok_o,
inv_i => inv_i,
inv_o => inv_o);
s_clk_process :process
begin
s_clk <= '1';
wait for CLK_PERIOD/2;
s_clk <= '0';
wait for CLK_PERIOD/2;
end process;
tb_proc: process
procedure initial_cond(level : STD_LOGIC) is
begin
-- s_rst <= '1';
level_i <= level;
switch_i <= '1';
inv_i <= (others => '0');
pulse_i_front <= (others => not(level));
pulse_i_rear <= (others => '0');
wait for CLK_PERIOD*50;
-- s_rst <= '0';
wait for CLK_PERIOD*2;
wait until rising_edge(s_clk);
end;
procedure input_pulse (signal pulse : out
STD_LOGIC_VECTOR(c_NUMBER_OF_CHANNELS - 1 downto 0);
channel: NATURAL;
length : time;
level : STD_LOGIC) is
variable v_pulse : STD_LOGIC := level;
begin
pulse(channel) <= not(level);
wait until rising_edge(s_clk);
pulse(channel) <= level;
wait for length;
pulse(channel) <= not(level);
wait until rising_edge(s_clk);
end;
procedure input_front_pulse (length : time; channel : NATURAL) is
begin
input_pulse (pulse_i_front, channel, length, level_i);
end;
procedure input_rear_pulse (length : time; channel : NATURAL) is
begin
input_pulse (pulse_i_rear, channel, length, '1');
end;
procedure input_two_pulses (channel : NATURAL; level : STD_LOGIC;
length1 : time;
length2 : time;
offset : time) is
begin
pulse_i_front(channel) <= level;
pulse_i_rear(channel) <= '0';
wait until rising_edge(s_clk);
pulse_i_rear(channel) <= '1';
wait for offset;
wait until rising_edge(s_clk);
pulse_i_front(channel) <= not(level);
wait for length1 - offset;
wait until rising_edge(s_clk);
pulse_i_rear(channel) <= '0';
wait for length2 - length1;
wait until rising_edge(s_clk);
pulse_i_front(channel) <= level;
wait until rising_edge(s_clk);
end;
begin
-- input_front_pulse (1200 ns, 0, '1');
--! First we put one pulse from the Blocking part, then we wait one-clock
--! and lastly we put another clock from the TTL input
initial_cond('1');
input_rear_pulse (1200 ns, 0);
wait until rising_edge(s_clk);
input_front_pulse (1200 ns, 0);
wait for 40*CLK_PERIOD;
--! We reboot the machine and change the switch to indicate level_i is
--! TTL_N
initial_cond('0');
input_rear_pulse (1200 ns, 0);
wait until rising_edge(s_clk);
input_front_pulse (1200 ns, 0);
input_two_pulses(0, '1',
1000 ns,
1000 ns,
212 ns);
wait for 40*CLK_PERIOD;
assert false report "End of test." severity failure;
end process;
end;
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /trigger_top_tb/s_clk
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_blo_en
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_en
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_inv_en
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_ttl_en
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_blo_en
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_en
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_inv_en
add wave -noupdate -group {Output enable} /trigger_top_tb/fpga_o_ttl_en
add wave -noupdate -group LEDs /trigger_top_tb/led_o
add wave -noupdate -group LEDs /trigger_top_tb/led_pw_o
add wave -noupdate -group LEDs /trigger_top_tb/led_err_o
add wave -noupdate -group LEDs /trigger_top_tb/led_ttl_o
add wave -noupdate -group LEDs /trigger_top_tb/led_o
add wave -noupdate -group LEDs /trigger_top_tb/led_pw_o
add wave -noupdate -group LEDs /trigger_top_tb/led_err_o
add wave -noupdate -group LEDs /trigger_top_tb/led_ttl_o
add wave -noupdate /trigger_top_tb/switch_i
add wave -noupdate /trigger_top_tb/level_i
add wave -noupdate /trigger_top_tb/pulse_i_front(0)
add wave -noupdate /trigger_top_tb/uut/s_pulse_i_front(1)
add wave -noupdate /trigger_top_tb/pulse_i_rear(0)
add wave -noupdate /trigger_top_tb/uut/s_pulse_i(1)
add wave -noupdate /trigger_top_tb/pulse_o_front(0)
add wave -noupdate /trigger_top_tb/pulse_o_rear(0)
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {4692791 ps} 0}
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ps
update
WaveRestoreZoom {0 ps} {16275 ns}
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity gc_RAM is
generic(
g_DATA_WIDTH : INTEGER := 32;
g_ADDR_WIDTH : INTEGER := 8);
port(
clka : in STD_LOGIC;
wea : in STD_LOGIC;
addra : in STD_LOGIC_VECTOR(g_ADDR_WIDTH - 1 downto 0);
dina : in STD_LOGIC_VECTOR(g_DATA_WIDTH - 1 downto 0);
clkb : in STD_LOGIC;
rstb : in STD_LOGIC;
addrb : in STD_LOGIC_VECTOR(g_ADDR_WIDTH - 1 downto 0);
doutb : out STD_LOGIC_VECTOR(g_DATA_WIDTH - 1 downto 0)
);
end gc_RAM;
architecture Behavioural of gc_RAM is
type ram_type is array(2**g_ADDR_WIDTH - 1 downto 0) of STD_LOGIC_VECTOR (g_DATA_WIDTH - 1 downto 0);
signal RAM: ram_type;
begin
write_proc: process (clka)
begin
if rising_edge(clka) then
if rstb = '1' then
erase_loop: for i in 0 to 2**g_ADDR_WIDTH - 1 loop
RAM(i) <= (others => '0');
end loop erase_loop;
else
RAM(conv_integer(addra)) <= dina;
end if;
else
end if;
end process;
read_proc: process (clkb)
begin
if rising_edge(clkb) then
if rstb = '1' then
doutb <= (others => '0');
elsif addrb = addra then
doutb <= dina;
else
doutb <= RAM(conv_integer(addrb));
end if;
else
end if;
end process;
end Behavioural;
----------------------------------------------------------------------------------
-- Company: CERN
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 16:26:32 10/07/2011
-- Design Name: Basic gc_debouncer
-- Module Name: gc_debouncer - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity gc_debouncer is
generic (
g_LENGTH : INTEGER := 6
);
port (
rst : IN std_logic;
clk : IN std_logic;
input : IN std_logic;
output : OUT std_logic;
glitch_mask : IN std_logic_vector(g_LENGTH-1 downto 0)
);
end gc_debouncer;
architecture Behavioral of gc_debouncer is
-- Signals
signal meta_ff1 : std_logic;
signal delay_s : std_logic_vector(g_LENGTH - 1 downto 0);
component gc_ff
port (
Q : out STD_LOGIC;
C : in STD_LOGIC;
CLR : in STD_LOGIC;
D : in STD_LOGIC
);
end component;
begin
ff1: gc_ff
port map(
Q => meta_ff1,
C => clk,
CLR => rst,
D => input
);
ff2: gc_ff
port map(
Q => delay_s(0),
C => clk,
CLR => rst,
D => meta_ff1
);
-- Metastability solved here
delay_line: for i in 1 to g_LENGTH-1 generate
D_Flip_Flop : gc_ff
port map (
Q => delay_s(i),
C => clk,
CLR => rst,
D => delay_s(i-1));
end generate delay_line;
process (clk)
begin
if rising_edge(clk) then
if rst = '1' then
output <= '0';
else
if ( (delay_s and glitch_mask) = glitch_mask) then
output <= '1';
else
output <= '0';
end if;
end if;
end if;
end process;
end Behavioral;
----------------------------------------------------------------------------------
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 16:00:11 10/12/2011
-- Design Name: Basic gc_monostable
-- Module Name: gc_monostable - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description: A basic gc_monostable circuit
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity gc_monostable is
port (
rst : in STD_LOGIC;
clk : in STD_LOGIC;
pulse_len : in STD_LOGIC_VECTOR(31 downto 0);
write_tt_o : out STD_LOGIC;
input : in STD_LOGIC;
output : out STD_LOGIC);
end gc_monostable;
architecture Behavioral of gc_monostable is
type fsm is (S0_WAITING, S1_OK, S2_FORBIDDEN);
signal blo_pulse_fsm : fsm;
signal s_count_max : UNSIGNED (32 downto 0);
signal s_count_max2 : UNSIGNED (32 downto 0);
signal s_count : UNSIGNED (32 downto 0);
signal write_tt_s : STD_LOGIC;
begin
process(clk)
begin
if rising_edge(clk) then
write_tt_o <= write_tt_s;
if (rst = '1') then
output <= '0';
write_tt_s <= '0';
blo_pulse_fsm <= S0_WAITING;
s_count_max <= unsigned('0' & std_logic_vector(pulse_len));
s_count_max2 <= unsigned(std_logic_vector(pulse_len) & '0');
else
case blo_pulse_fsm is
when S0_WAITING =>
if input = '1' then
blo_pulse_fsm <= S1_OK;
s_count_max <= unsigned('0' & std_logic_vector(pulse_len));
s_count_max2 <= unsigned(std_logic_vector(pulse_len) & '0');
s_count(32 downto 1) <= (others => '0');
s_count(0) <= '1';
output <= '1';
write_tt_s <= '1';
else
end if;
when S1_OK =>
s_count <= s_count + 1;
write_tt_s <= '0';
if s_count = s_count_max then
blo_pulse_fsm <= S2_FORBIDDEN;
output <= '0';
else
end if;
when S2_FORBIDDEN =>
s_count <= s_count + 1;
if s_count = s_count_max2 then
blo_pulse_fsm <= S0_WAITING;
else
end if;
when others =>
end case;
end if;
else
end if;
end process;
end Behavioral;
----------------------------------------------------------------------------------
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 16:00:11 10/12/2011
-- Design Name: Basic gc_monostable
-- Module Name: gc_monostable - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description: A basic gc_monostable circuit
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity gc_simple_monostable is
generic(g_PULSE_LENGTH : NATURAL := 20);
port (
rst : in STD_LOGIC;
clk : in STD_LOGIC;
input : in STD_LOGIC;
output : out STD_LOGIC;
output_n : out STD_LOGIC);
end gc_simple_monostable;
architecture Behavioral of gc_simple_monostable is
constant c_count_max : UNSIGNED (63 downto 0) :=
to_unsigned(g_PULSE_LENGTH, 64);
signal s_count : UNSIGNED (63 downto 0) := to_unsigned(0, 64);
signal s_input : STD_LOGIC := '0';
signal s_input_d0 : STD_LOGIC := '0';
signal s_running : STD_LOGIC := '0';
signal s_output : STD_LOGIC := '0';
signal s_output_n : STD_LOGIC := '1';
begin
s_input <= input;
output <= s_output;
output_n <= s_output_n;
p_mono: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
s_count <= to_unsigned(0, 64);
s_running <= '0';
s_input_d0 <= '0';
s_output <= '0';
s_output_n <= '1';
else
s_input_d0 <= s_input;
s_output <= '0';
s_output_n <= '1';
s_count <= to_unsigned(0, 64);
s_running <= '0';
if (s_input = '1')
and (s_input_d0 = '0') then
s_count <= s_count + 1;
s_running <= '1';
s_output <= '1';
s_output_n <= '0';
elsif s_running = '1' then
if s_count < c_count_max then
s_count <= s_count + 1;
s_running <= '1';
s_output <= '1';
s_output_n <= '0';
else
s_count <= to_unsigned(0, 64);
s_running <= '0';
end if;
end if;
end if;
end if;
end process;
end Behavioral;
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