ROD firmware  1.0.5
ATLAS l1-calo - ROD_eFEX and ROD_jFEX firmware for the L1Calo ROD board

Back to ROD documentation
clock_test_ipbus.vhd
1 ----------------------------------------------------------------------------------
2 -- Company:
3 -- Engineer:
4 --
5 -- Create Date: 19.02.2019 13:36:52
6 -- Design Name:
7 -- Module Name: reset_count - RTL
8 -- Project Name:
9 -- Target Devices:
10 -- Tool Versions:
11 -- Description:
12 --
13 -- Dependencies:
14 --
15 -- Revision:
16 -- Revision 0.01 - File Created
17 -- Additional Comments:
18 --
19 ----------------------------------------------------------------------------------
20 
21 -->the ROD has three primary clock sources:
22 --> 1) The Si chip - takes 40MHz from Hub and produces clean 40MHz inputs to the FPGA and the TI chip
23 --> 2) The TI chip - takes 40MHz from the Si chip, and produces the 160MHz and 240MHz MGT reference clocks. If the Si chip is not working,
24 --> then this device will also fail to produce the correct frequencies
25 --> 3) The ethernet PHY chip has a 25MHz oscilator and it produces a 125MHz signal to the FPGA when working properly. If this chip is not working properly
26 --> it has been observed to produce 25MHz or even a random frequence like 116MHz. However, since the results of this checker are intended to
27 --> be read via IPBus, we have to assume that the 125MHz is working correctly.
28 --> Thus there is no explicite 125MHz check
29 
30 --> The circuit below resets all three counters at the end of each measurement sequence.
31 --> The length of the sequence is determined by the "reset_count" generic
32 --> At the end of each sequence the values of clk_40_count and clk_160_count are checked against a constant value
33 --> If the value matches within a range, then the "good" bit is set
34 --> If the value does not match within the range, then the "good" bit is cleared.
35 
36 
37 
38 
39 library IEEE;
40 use IEEE.STD_LOGIC_1164.ALL;
41 use IEEE.STD_LOGIC_UNSIGNED.ALL;
42 
43 -- Uncomment the following library declaration if using
44 -- arithmetic functions with Signed or Unsigned values
45 --use IEEE.NUMERIC_STD.ALL;
46 
47 -- Uncomment the following library declaration if instantiating
48 -- any Xilinx leaf cells in this code.
49 --library UNISIM;
50 --use UNISIM.VComponents.all;
51 
53  generic
54 (
55  COUNTER_WIDTH_40 : integer := 8;
56  reset_count : std_logic_vector(15 downto 0) := x"03ff"; --count_125 rollover resets the system
57  count_40_term : std_logic_vector(7 downto 0) := x"45";
58  count_160_term : std_logic_vector(7 downto 0) := x"45"
59 
60  --for a shorter test sequence, use the values below
61  --reset_count : std_logic_vector(15 downto 0) := x"01ff"; --count_125 rollover resets the system
62  --count_40_term : std_logic_vector(7 downto 0) := x"A2";
63  --count_160_term : std_logic_vector(7 downto 0) := x"A2"
64 );
65 
66  Port (
67  clock_40 : in STD_LOGIC;
68  clock_160 : in STD_LOGIC;
69  clock_125 : in STD_LOGIC;
70  reset : in STD_LOGIC;
71  clock_160_lock : in STD_LOGIC;
72  clk_40_good : out std_logic;
73  clk_160_good : out std_logic;
74  count_40 : out std_logic_vector(counter_width_40-1 downto 0);
75  count_160 : out std_logic_vector(counter_width_40-1 downto 0);
76  count_125 : out std_logic_vector(counter_width_40-1 downto 0)
77 
78  );
80 
81 architecture RTL of clock_test_ipbus is
82 
83 signal counter_40 : std_logic_vector(counter_width_40-1 downto 0) := (others => '0');
84 signal counter_160 : std_logic_vector(counter_width_40+2-1 downto 0) := (others => '0');
85 signal counter_125 : std_logic_vector(counter_width_40+8-1 downto 0) := (others => '0');
86 signal clk_40_good_i : std_logic;
87 signal clk_160_good_i : std_logic;
88 signal clk_125_good_i : std_logic;
89 signal reset_timer : std_logic_vector(3 downto 0) := (others => '0');
90 signal timed_reset : std_logic;
91 signal timed_reset_40 : std_logic;
92 signal timed_reset_160 : std_logic;
93 
94 begin
95 process (clock_40) begin
96 
97  if rising_edge (clock_40) then
98  if reset = '1' or timed_reset_40 = '1' then --counter_125 = reset_count then
99  counter_40 <= (others => '0');
100  else
101  counter_40 <= counter_40+1;
102  end if;
103  end if;
104 end process;
105 
106 process (clock_160) begin
107  if rising_edge (clock_160) then
108  if reset = '1' or clock_160_lock = '0' or timed_reset_160 = '1' then --counter_125 = reset_count then
109  counter_160 <= (others => '0');
110  else
111  counter_160 <= counter_160 +1;
112  end if;
113  end if;
114 end process;
115 
116 process (clock_125) begin
117  if rising_edge (clock_125) then
118  if (reset = '1') or timed_reset = '1' then
119  counter_125 <= (others => '0');
120  else
121  counter_125 <= counter_125 +1;
122  end if;
123  end if;
124 end process;
125 
126 
127 
128 count_40 <= counter_40;
129 
130 count_160 <= counter_160(counter_width_40+2-1 downto 2);
131 
132 count_125 <= counter_125(counter_width_40+2-1 downto 2);
133 
134 process (clock_125) begin
135  if rising_edge (clock_125) then
136  if reset = '1' or counter_125 = reset_count then
137  reset_timer <= x"f";
138  elsif reset_timer /= x"0" then
139  reset_timer <= reset_timer -1;
140  else
141  reset_timer <= reset_timer;
142  end if;
143  end if;
144 end process;
145 
146 --timed_reset <= '1' when reset_timer /= x"0" else '0';
147 timed_reset <= reset_timer(3) or reset_timer(2) or reset_timer(1) or reset_timer(0);
148 -- reset the timers using the 125MHz clock rollover
149 
150 process (clock_40) begin
151  if rising_edge (clock_40) then
152  timed_reset_40 <= timed_reset;
153  end if;
154 end process;
155 
156 process (clock_160) begin
157  if rising_edge (clock_160) then
158  timed_reset_160 <= timed_reset;
159  end if;
160 end process;
161 
162 
163 
164 --check clk_40 using clk_125
165 --the clk_40 timer should reach a specific value +/- 4 just before the 125 counter rolls over
166 --after the clk_40 counter value is checked, all of the counters are reset to start the nect test sequence.
167 
168 process (clock_125) begin
169  if rising_edge (clock_125) then
170  if reset = '1' then
171  clk_40_good_i <= '0';
172  elsif (counter_125 = reset_count - 4) then
173  if (counter_40 >= (count_40_term -4)) and (counter_40 <= (count_40_term +4)) then
174  clk_40_good_i <= '1';
175  elsif (counter_40 <= (count_40_term -4)) or (counter_40 >= (count_40_term +4)) then
176  clk_40_good_i <= '0';
177  else
178  clk_40_good_i <= clk_40_good_i;
179  end if;
180  else
181  clk_40_good_i <= clk_40_good_i;
182  end if;
183  end if;
184 end process;
185 
186 --check clk_160 using clk_125
187 --the clk_160 timer should reach a specific value +/- 4 just before the 125 counter rolls over
188 --after the clk_160 counter value is checked, all of the counters are reset to start the nect test sequence.
189 
190 process (clock_125) begin
191  if rising_edge (clock_125) then
192  if reset = '1' then
193  clk_160_good_i <= '0';
194  elsif (counter_125 = reset_count - 4) then
195  if (counter_160(9 downto 2) >= (count_160_term -4)) and (counter_160(9 downto 2) <= (count_160_term +4)) then
196  clk_160_good_i <= '1';
197  elsif (counter_160(9 downto 2) <= (count_160_term -4)) or (counter_160(9 downto 2) >= (count_160_term +4)) then
198  clk_160_good_i <= '0';
199  else
200  clk_160_good_i <= clk_160_good_i;
201  end if;
202  else
203  clk_160_good_i <= clk_160_good_i;
204  end if;
205  end if;
206 end process;
207 
208 clk_40_good <= clk_40_good_i;
209 clk_160_good <= clk_160_good_i;
210 
211 
212 
213 
214 --> clock Status Register
215 --> (15 downto 8) clk_160_count
216 --> (23 downto 16) clk_40_count
217 --> (31 downto 24) clk125_count
218 --> (0) clock_160_lock
219 --> (1) clk_160_good
220 --> (2) clk_40_good
221 
222 
223 end RTL;
224