otsdaq_prepmodernization  v2_05_02_indev
PeakFinder.vhd
1 ----------------------------------------------------------------------------------
2 -- Company: Fermilab
3 -- Engineer: Collin Bradford
4 --
5 -- Create Date: 13:51:43 07/07/2016
6 -- Design Name:
7 -- Module Name: PeakFinder - Behavioral
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 -- This module analyzes the input from the adc and looks for peaks.
20 -- Once the input from the adc passes the user-set threshold, it will set the address on the trigger_address
21 -- pin to the address of the trigger. It will also pusle the new_trigger signal.
22 --
23 -- This module is meant to be used with a ram block to establish a looping buffer. The addr_out and data_out pins
24 -- can be directly connected to the ram to establish this looping buffer.
25 --
26 -- In the case that two triggers arrive one after another without a clock cycle inbetween or a single pulse
27 -- lasts longer than the user set read time, a new trigger will be immediately set and no data should be lost.
28 --
29 ----------------------------------------------------------------------------------
30 library IEEE;
31 use IEEE.numeric_std.all;
32 use IEEE.STD_LOGIC_1164.ALL;
33 use IEEE.STD_LOGIC_UNSIGNED.ALL;
34 
35 entity PeakFinder is
36  Port ( --default signals
37  clk : in STD_LOGIC;
38  reset : in STD_LOGIC;
39  clock_enable : in STD_LOGIC;
40  median_filter : in STD_LOGIC;
41  --data signals
42  data_in : in STD_LOGIC_VECTOR (63 downto 0);
43  --trigger types and attributes
44  trig_types : in STD_LOGIC_VECTOR (7 downto 0);
45  signal_threshold : in STD_LOGIC_VECTOR(7 downto 0);
46  manual_force_trig : in STD_LOGIC;
47  ext_trig : in STD_LOGIC;
48  --data_out
49  data_out : out STD_LOGIC_VECTOR (63 downto 0);
50  --address information
51  addr_out : out STD_LOGIC_VECTOR (9 downto 0);
52  trigger_address : out STD_LOGIC_VECTOR(9 downto 0);
53  new_trigger : out STD_LOGIC;
54  out_enable : out STD_LOGIC;
55  --clear the manual trigger flip-flop
56  clear_manual_trig : out STD_LOGIC);
57 end PeakFinder;
58 
59 architecture Behavioral of PeakFinder is
60  --each individual sample gets it's own signal
61  signal sample_one : unsigned(7 downto 0);
62  signal sample_two : unsigned(7 downto 0);
63  signal sample_three : unsigned(7 downto 0);
64  signal sample_four : unsigned(7 downto 0);
65  signal sample_five : unsigned(7 downto 0);
66  signal sample_six : unsigned(7 downto 0);
67  signal sample_seven : unsigned(7 downto 0);
68  signal sample_eight : unsigned(7 downto 0);
69 
70 
71  signal pre_sample_one : unsigned(7 downto 0);
72  signal pre_sample_two : unsigned(7 downto 0);
73  signal pre_sample_three : unsigned(7 downto 0);
74  signal pre_sample_four : unsigned(7 downto 0);
75  signal pre_sample_five : unsigned(7 downto 0);
76  signal pre_sample_six : unsigned(7 downto 0);
77  signal pre_sample_seven : unsigned(7 downto 0);
78  signal pre_sample_eight : unsigned(7 downto 0);
79 
80 
81  signal post_sample_one : unsigned(7 downto 0);
82  signal post_sample_two : unsigned(7 downto 0);
83  signal post_sample_three : unsigned(7 downto 0);
84  signal post_sample_four : unsigned(7 downto 0);
85  signal post_sample_five : unsigned(7 downto 0);
86  signal post_sample_six : unsigned(7 downto 0);
87  signal post_sample_seven : unsigned(7 downto 0);
88  signal post_sample_eight : unsigned(7 downto 0);
89 
90  signal pre_data_in, post_data_in : std_logic_vector(63 downto 0);
91 
92  --repeating signals
93  signal threshold : unsigned( 7 downto 0 );
94  signal ramAddress : unsigned(9 downto 0);
95  signal clearManualTrigSig : std_logic;
96  signal extTrigLatched : std_logic;
97  --internal flags
98  signal new_trigger_sig : std_logic;
99  signal triggered : std_logic;--Means that a signal is over the threshold. Sync with clk.
100  signal trigger_active : std_logic;
101  --each trigger attribute gets it's own signal
102  signal threshTrigEn : std_logic; --Threshold Mode is enabled
103  signal threshHigh : std_logic; --Treshold will trigger if the signal is above the threshold
104  signal lastThreshTrigState : std_logic; --Keeps track of whether we were triggered last clock so that we don't trigger multiple times for the same event.
105  signal manualTrigEn : std_logic; --Manual Mode is enabled
106  signal extTrigEn : std_logic; --External Trig Mode is enabled
107  signal extTrigRising : std_logic; --Trigger on the rising edge of the external trigger
108  signal lastExtTrigState : std_logic; --The last state of the external trigger
109 
110 
111  function MEDIAN_SAMPLE (
112  s0: unsigned(7 downto 0);
113  s1: unsigned(7 downto 0);
114  s2: unsigned(7 downto 0))
115  return std_logic_vector is
116  begin
117  if ((s0 > s1 and s0 < s2) or (s0 < s1 and s0 > s2)) then
118  return std_logic_vector(s0);
119  elsif ((s2 > s1 and s2 < s0) or (s2 < s1 and s2 > s0)) then
120  return std_logic_vector(s2);
121  else
122  return std_logic_vector(s1);
123  end if;
124  end MEDIAN_SAMPLE;
125 begin
126  --assign the samples
127  sample_one <= unsigned(data_in(15 downto 8));
128  sample_two <= unsigned(data_in(7 downto 0));
129  sample_three <= unsigned(data_in(31 downto 24));
130  sample_four <= unsigned(data_in(23 downto 16));
131  sample_five <= unsigned(data_in(47 downto 40));
132  sample_six <= unsigned(data_in(39 downto 32));
133  sample_seven <= unsigned(data_in(63 downto 56));
134  sample_eight <= unsigned(data_in(55 downto 48));
135 
136  pre_sample_one <= unsigned(pre_data_in(15 downto 8));
137  pre_sample_two <= unsigned(pre_data_in(7 downto 0));
138  pre_sample_three <= unsigned(pre_data_in(31 downto 24));
139  pre_sample_four <= unsigned(pre_data_in(23 downto 16));
140  pre_sample_five <= unsigned(pre_data_in(47 downto 40));
141  pre_sample_six <= unsigned(pre_data_in(39 downto 32));
142  pre_sample_seven <= unsigned(pre_data_in(63 downto 56));
143  pre_sample_eight <= unsigned(pre_data_in(55 downto 48));
144 
145  post_sample_one <= unsigned(post_data_in(15 downto 8));
146  post_sample_two <= unsigned(post_data_in(7 downto 0));
147  post_sample_three <= unsigned(post_data_in(31 downto 24));
148  post_sample_four <= unsigned(post_data_in(23 downto 16));
149  post_sample_five <= unsigned(post_data_in(47 downto 40));
150  post_sample_six <= unsigned(post_data_in(39 downto 32));
151  post_sample_seven <= unsigned(post_data_in(63 downto 56));
152  post_sample_eight <= unsigned(post_data_in(55 downto 48));
153 
154 
155  --assign repeating signals
156  threshold <= unsigned(signal_threshold);
157  new_trigger <= new_trigger_sig;
158  addr_out <= std_logic_vector(ramAddress);
159  clear_manual_trig <= clearManualTrigSig;
160  --assign trigger attribute signals
161  threshTrigEn <= trig_types(0);
162  threshHigh <= trig_types(1);
163  manualTrigEn <= trig_types(2);
164  extTrigEn <= trig_types(3);
165  extTrigRising <= trig_types(4);
166 
167 
168 
169 
170  process(clk) begin
171 
172 
173 
174 
175 
176 -- data_out(7 downto 0) <= data_in(7 downto 0);
177 -- data_out(15 downto 8) <= data_in(15 downto 8);
178 -- data_out(23 downto 16) <= data_in(23 downto 16);
179 -- data_out(31 downto 24) <= data_in(31 downto 24);
180 -- data_out(39 downto 32) <= data_in(39 downto 32);
181 -- data_out(47 downto 40) <= data_in(47 downto 40);
182 -- data_out(55 downto 48) <= data_in(55 downto 48);
183 -- data_out(63 downto 56) <= data_in(63 downto 56);
184 
185  if(reset = '0') then--reset is low
186 
187  if(rising_edge(clk)) then
188 
189  lastExtTrigState <= extTrigLatched;
190  extTrigLatched <= ext_trig;
191 
192  out_enable <= '0';
193 
194  --if external trigger mode is enabled
195  if(extTrigEn = '1') then
196  --if we are triggering on the rising edge of the trigger and it actually is the rising edge
197  if(extTrigRising = '1' and lastExtTrigState = '0' and extTrigLatched = '1') then
198  trigger_active <= '1';
199  end if;
200  --if we are triggering on the falling edge of the trigger and it actually is the falling edge
201  if(extTrigRising = '0' and lastExtTrigState = '1' and extTrigLatched = '0') then
202  trigger_active <= '1';
203  end if;
204  end if;
205 
206  if(clock_enable = '1') then--rising edge of clk and the clock is enabled
207 
208  ramAddress <= ramAddress + 1;
209  out_enable <= '1';
210 
211  post_data_in <= data_in;
212  pre_data_in <= post_data_in;
213 
214  -- so ... data in is newest, then post, then pre
215  -- data out will always come from post
216 
217  if (median_filter = '1') then
218 
219  data_out(15 downto 8) <= MEDIAN_SAMPLE(pre_sample_eight,post_sample_one,post_sample_two);
220  data_out(7 downto 0) <= MEDIAN_SAMPLE(post_sample_one,post_sample_two,post_sample_three);
221  data_out(31 downto 24) <= MEDIAN_SAMPLE(post_sample_two,post_sample_three,post_sample_four);
222  data_out(23 downto 16) <= MEDIAN_SAMPLE(post_sample_three,post_sample_four,post_sample_five);
223  data_out(47 downto 40) <= MEDIAN_SAMPLE(post_sample_four,post_sample_five,post_sample_six);
224  data_out(39 downto 32) <= MEDIAN_SAMPLE(post_sample_five,post_sample_six,post_sample_seven);
225  data_out(63 downto 56) <= MEDIAN_SAMPLE(post_sample_six,post_sample_seven,post_sample_eight);
226  data_out(55 downto 48) <= MEDIAN_SAMPLE(post_sample_seven,post_sample_eight,sample_one);
227 
228  else --old way
229  data_out <= data_in;
230  end if;
231 
232  --These are the tests for each trigger state. There is at least one if statement per trigger mode that is enabled when the
233  --respective trigger mode is enabled. If the trigger mode is active and the trigger state is also active, it enables the
234  --trigger_active flag and performs any other checks and resets for each trigger.
235  --
236  --if threshold mode is enabled
237  if(threshTrigEn = '1') then
238  --if we trigger when the signal rises above the trigger line
239  if(threshHigh = '1') then
240  if(sample_one > threshold or sample_two > threshold or sample_three > threshold or sample_four > threshold
241  or sample_five > threshold or sample_six > threshold or sample_seven > threshold or sample_eight > threshold) then
242  --if we aren't already triggered -- prevents triggering multiple times on the same event.
243  if(lastThreshTrigState = '0') then
244  trigger_active <= '1';
245  lastThreshTrigState <= '1';
246  end if;
247  --reset the last thresh trigger state flag so that we can trigger on the next event.
248  else
249  lastThreshTrigState <= '0';
250  end if;
251  end if;
252  --if we trigger when the signal falls below the trigger line
253  if(threshHigh = '0') then
254  if(sample_one < threshold or sample_two < threshold or sample_three < threshold or sample_four < threshold
255  or sample_five < threshold or sample_six < threshold or sample_seven < threshold or sample_eight < threshold) then
256  --if we aren't already triggered -- prevents triggering multiple times on the same event.
257  if(lastThreshTrigState = '0') then
258  trigger_active <= '1';
259  lastThreshTrigState <= '1';
260  end if;
261  --reset the last thresh trigger state flag so that we can trigger on the next event.
262  else
263  lastThreshTrigState <= '0';
264  end if;
265  end if;
266  end if;
267  --if manual trigger mode is enabled and we have a trigger
268  if(manualTrigEn = '1' and manual_force_trig = '1') then
269  trigger_active <= '1';
270  clearManualTrigSig <= '1';
271  end if;
272 
273  --Code that needs to be run for each trigger
274  --
275  --Check for a trigger and run the code.
276  if (trigger_active = '1') then
277  triggered <= '1';
278  new_trigger_sig <= '1';
279  trigger_address <= std_logic_vector(ramAddress);
280  trigger_active <= '0';
281  end if;
282  --these signals need to be pulsed for one clock only.
283  if(new_trigger_sig = '1') then
284  new_trigger_sig <= '0';
285  end if;
286  if(clearManualTrigSig = '1') then
287  clearManualTrigSig <= '0';
288  end if;
289  --clk_enable ends here.
290  end if;
291  end if;
292  --reset is high
293  else
294  triggered <= '0';
295  new_trigger_sig <= '0';
296  ramAddress <= (others => '0');
297  clearManualTrigSig <= '0'; --Needed to clear the FD on reset
298  lastThreshTrigState <= '0';
299  trigger_active <= '0';
300  end if;
301  end process;
302 end Behavioral;
303