otsdaq_prepmodernization  v2_05_02_indev
data_send.vhd
1 ----------------------------------------------------------------------------------
2 -- Company: Fermilab
3 -- Engineer: Collin Bradford
4 --
5 -- Create Date: 10:14:49 07/08/2016
6 -- Design Name:
7 -- Module Name: data_send - Behavioral
8 -- Project Name:
9 -- Target Devices:
10 -- Tool versions:
11 -- Description: The data_send module receives a trigger event from the peak_finder module with the address of the event.
12 -- It then waits until the circular buffer has come around to the start address and reads out the information. This module
13 -- takes into account the number of pretrigger samples, the read size, and the positive delay requested by the user when
14 -- collecting the samples to read. The module also adds header and footer information to the starting and ending packets.
15 --
16 -- Dependencies:
17 --
18 -- Revision:
19 -- Revision 0.01 - File Created
20 -- Additional Comments:
21 --
22 ----------------------------------------------------------------------------------
23 library IEEE;
24 use IEEE.STD_LOGIC_1164.ALL;
25 use IEEE.NUMERIC_STD.ALL;
26 use IEEE.STD_LOGIC_UNSIGNED.ALL;
27 
28 entity data_send is
29  Port ( --default signals
30  rst : in STD_LOGIC;
31  clk : in STD_LOGIC;
32  clock_enable : in STD_LOGIC;
33  --data signals
34  data_in : in STD_LOGIC_VECTOR (63 downto 0);
35  --trigger signals
36  new_trigger : in STD_LOGIC;
37  trigger_addr : in STD_LOGIC_VECTOR (9 downto 0);
38  ram_addr : in STD_LOGIC_VECTOR (9 downto 0);
39  --user sample sizes
40  user_sample_size : in STD_LOGIC_VECTOR (15 downto 0);
41  user_pretrig_sample_size : in STD_LOGIC_VECTOR (15 downto 0);
42  user_positive_delay : in STD_LOGIC_VECTOR(15 downto 0);
43  --header/footer signals
44  debug_signals : in STD_LOGIC_VECTOR(7 downto 0);
45  signal_ID : in STD_LOGIC_VECTOR(3 downto 0);
46  header : in STD_LOGIC_VECTOR(59 downto 0);
47  --burst data control signals
48  b_data : out STD_LOGIC_VECTOR (63 downto 0);
49  b_data_we : out STD_LOGIC;
50  b_force_packet : out STD_LOGIC);
51 end data_send;
52 
53 architecture Behavioral of data_send is
54 --address signals
55 signal startAddr : unsigned(9 downto 0);
56 signal endAddr : unsigned(9 downto 0);
57 --repeated signals
58 signal userSampleSizeUns : unsigned(15 downto 0);
59 signal userPretrigSamplesUns : unsigned(15 downto 0);
60 signal userPositiveDelayUns : unsigned(15 downto 0);
61 signal triggerAddressUns : unsigned(9 downto 0);
62 signal ramAddrUns : unsigned(9 downto 0);
63 signal delayed_clk_en : std_logic;
64 --positive delay signals
65 signal positiveDelayTimer : unsigned(15 downto 0);
66 signal timing : std_logic;
67 --internal flags
68 signal armed : std_logic;
69 signal reading : std_logic;
70 signal sendUDP, lastRead : std_logic;
71 signal burstWrEn : std_logic;
72 signal headerTwoStart : std_logic;
73 signal busy : std_logic;
74 --outgoing data signals
75 signal dataOut : std_logic_vector(63 downto 0);
76 signal headerOneOut : std_logic_vector(63 downto 0);
77 signal headerTwoOut : std_logic_vector(63 downto 0);
78 --header signals
79 signal missedTriggerCount : unsigned(7 downto 0);
80 signal triggerCount : unsigned(31 downto 0); --Keeps a count of the number of triggers
81 signal sampleSize : unsigned(15 downto 0); --Number of samles for this read (in clocks meaning that 1 clock = 4 samples)
82 
83 begin
84  --repeated signal assignments
85  b_force_packet <= sendUDP;
86  triggerAddressUns <= unsigned(trigger_addr);
87  userSampleSizeUns <= unsigned(user_sample_size);
88  userPretrigSamplesUns <= unsigned(user_pretrig_sample_size);
89  userPositiveDelayUns <= unsigned(user_positive_delay);
90  ramAddrUns <= unsigned(ram_addr);
91  --data signal assignments (repeated)
92  dataOut(7 downto 0) <= data_in(63 downto 56);
93  dataOut(15 downto 8) <= data_in(55 downto 48);
94  dataOut(23 downto 16) <= data_in(47 downto 40);
95  dataOut(31 downto 24) <= data_in(39 downto 32);
96  dataOut(39 downto 32) <= data_in(31 downto 24);
97  dataOut(47 downto 40) <= data_in(23 downto 16);
98  dataOut(55 downto 48) <= data_in(15 downto 8);
99  dataOut(63 downto 56) <= data_in(7 downto 0);
100  --header one signal assignments
101  headerOneOut(63 downto 32) <= std_logic_vector(triggerCount(31 downto 0));
102  headerOneOut(31 downto 16) <= std_logic_vector(sampleSize(15 downto 0));
103  headerOneOut(15 downto 8) <= debug_signals(7 downto 0);
104  headerOneOut(7 downto 0) <= std_logic_vector(missedTriggerCount(7 downto 0));
105  --header two signal assignments
106  headerTwoOut(63 downto 60) <= signal_ID(3 downto 0);
107  headerTwoOut(59 downto 0) <= header(59 downto 0);
108 
109  process(clk) begin
110  if(rising_edge(clk)) then
111 
112  --pulsed signals
113  b_data_we <= '0';
114  sendUDP <= '0';
115  lastRead <= '0';
116 
117  if(rst = '1') then
118  --reset code here
119  busy <= '0';
120  timing <= '0';
121  armed <= '0';
122  headerTwoStart <= '0';
123  reading <= '0';
124 
125  triggerCount <= (others => '0');
126  missedTriggerCount <= (others => '0');
127  positiveDelayTimer <= (others => '0');
128  else
129 
130  delayed_clk_en <= clock_enable;
131 
132  --use clock_enable to handle address related things
133  --use delayed_clk_en to handle data related things
134 
135  --====================
136  --====================
137  if(clock_enable = '1') then
138 
139  --latch the address data as soon as we recieve a trigger event
140  -- and count missed triggers
141  if(new_trigger = '1') then
142  --only latch the new trigger if we don't already have one.
143  if(busy = '0') then
144  busy <= '1';
145  timing <= '1';
146  positiveDelayTimer <= (others => '0');
147  triggerCount <= triggerCount + 1;
148  sampleSize <= userSampleSizeUns + userPretrigSamplesUns;
149  startAddr <= triggerAddressUns + userPositiveDelayUns - userPretrigSamplesUns;--This last number accounts for any delay in the firmware. There must be at least -2 clocks allowed for placement of the header information. Currently, another clock is requried by the peak_finder module for a total of -2.
150  endAddr <= triggerAddressUns + userSampleSizeUns + userPositiveDelayUns + 1;
151  --If we get a trigger that we can't take care of because we are busy, incriment the missed trigger count.
152  else
153  missedTriggerCount <= missedTriggerCount + 1;
154  end if;
155  end if;
156 
157 
158  --If we are triggered and the timing is finished, activate the armed flag.
159  if (timing = '1') then
160  if (positiveDelayTimer = userPositiveDelayUns) then
161  armed <= '1';
162  timing <= '0';
163  else
164  --if we aren't finished timing, but are still timing, then increase the positiveDelayTimer.
165  positiveDelayTimer <= positiveDelayTimer + 1;
166  end if;
167  elsif (armed = '1') then
168  --once we reach the start address for the readout, send header one
169  if(ramAddrUns = startAddr) then --Begins read cycle when buffer reaches starting point.
170  armed <= '0';
171 
172  b_data_we <= '1';
173  b_data <= headerOneOut;
174 
175  headerTwoStart <= '1';
176  end if;
177  elsif(reading = '1' ) then --once we reach the end address
178  if(ramAddrUns = endAddr) then --Ends read cycle when buffer reaches the end point.
179  lastRead <= '1'; --last data arrives on next clock
180  end if;
181  end if;
182 
183  end if; --end if(clock_enable = '1') then
184 
185  --====================
186  --====================
187  --send header two, one clock after header one (i.e. NO clock enable)
188  if(headerTwoStart = '1') then
189  headerTwoStart <= '0';
190 
191  b_data_we <= '1';
192  b_data <= headerTwoOut;
193 
194  reading <= '1';
195  end if;
196 
197  --====================
198  --====================
199  --after allowing last read, close packet and DONE!
200  if(lastRead = '1') then
201  reading <= '0';
202  sendUDP <= '1';
203  busy <= '0';
204  --note: the last we and data is handles by the reading clause (below)
205  end if;
206 
207 
208  --====================
209  --====================
210  --start reading (starts after headers are sent)
211  if(reading = '1' and delayed_clk_en = '1') then
212 
213  b_data_we <= '1';
214  b_data <= dataOut;
215 
216  end if; --end if(delayed_clk_en = '1') then
217 
218 
219  end if;
220  end if;
221  end process;
222 
223 end Behavioral;
224