Subversion Repositories f9daq

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
336 f9daq 1
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer: 
4
-- 
5
-- Create Date: 24.10.2018 17:44:30
6
-- Design Name: 
7
-- Module Name: ADC_unit - 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
----------------------------------------------------------------------------------
20
 
21
 
22
library IEEE;
23
use IEEE.STD_LOGIC_1164.ALL;
24
 
25
-- Uncomment the following library declaration if using
26
-- arithmetic functions with Signed or Unsigned values
27
use IEEE.NUMERIC_STD.ALL;
28
 
29
 
30
 
31
-- Uncomment the following library declaration if instantiating
32
-- any Xilinx leaf cells in this code.
33
--library UNISIM;
34
--use UNISIM.VComponents.all;
35
 
36
entity ADC_unit is
37
 
38
    generic ( adc_bit_num : natural := 14; --input data from ad converter is 14 bit
39
              bit_num : natural := 10; -- number of bits for our data (scaled from 14 bit to 10 bit)
40
              num_of_units: natural := 2; -- number of BRAM_buffer and PE_unit units
41
              buffer_size: natural := 5; --size of each BRAM_buffer in bits
42
              mode: string := "MODE_3"; -- modes of operation: MODE_1 = navaden algoritm, MODE_2 = odklop bufferja in 1 enota, MODE_3 = novo od 30.11.2018 naprej
43
              byte: natural := 8
44
 
45
             );
46
 
47
    port ( clk_in: in std_logic;
48
           START: in std_logic; -- start the system
49
           data_in : in unsigned ( (adc_bit_num - 1) downto 0 ); --data from ADC
50
           ADC_unit_feedback: in std_logic;
51
           AD_wr_en: out unsigned ( (num_of_units - 1) downto 0 );-- goes to BRAM_buffer, to AD_wr_en signal
52
           AD_addr: out unsigned ( (buffer_size - 1) downto 0 );  -- goes to BRAM_buffer, address signal
53
           data_out: out unsigned ( (bit_num - 1) downto 0 ); -- goes to data_in of BRAM_buffer
54
           --MODE_3--
55
           threshold: in unsigned ( (11 - 1) downto 0 ); --11 bitno zato, ker imam najvec 2048 kanalov
56
           capt_num_of_samples: in unsigned ( (byte - 1) downto 0 ); --time window
57
           INT_res: out std_logic;
58
 
59
           SW_trigger_value: in unsigned(4 downto 0);
60
           PM_trigger_in: in unsigned ( (adc_bit_num - 1) downto 0)
61
          );
62
 
63
end ADC_unit;
64
 
65
architecture Behavioral of ADC_unit is
66
 
67
 
68
------FUNCTIONS-----------------
69
    function data_map( input: unsigned ( (adc_bit_num - 2) downto 0) := (others => '0'); --transforms data drom one region to the other (for example from 0 - 1023 to 0-512)
70
                       current_low: integer := 0;
71
                       current_high: integer := 0;
72
                       next_low: integer := 0;
73
                       next_high: integer := 0 ) return unsigned is
74
 
75
    --variable result: real := 0.0;
76
    variable output : integer := 0;
77
 
78
    begin    
79
        output := ((to_integer(input) - current_low) * (next_high - next_low)) / (current_high - current_low) + next_low;
80
        --TODO: zaokrozevanje
81
        return to_unsigned(output,bit_num);
82
    end function;
83
 
84
 
85
 
86
--------------CONSTANTS------------------- (used for input arguments of function data_map)
87
    constant adc_low: integer := 0; --old area low 
88
    constant adc_high: integer :=8191; --2**(adc_bit_num -1) - 1; --1443;-- --old area high , blo je adc_bit_num sam to pol se neg. del adc-ja zravn, kar nocm TODO: 12.4.2019, kalibriraj na novo vrednost
89
    constant mapped_low: integer := 0; --new area low
90
    constant mapped_high: integer := 2**bit_num - 1; -- new area high
91
 
92
 
93
 
94
--------SIGNALS--------------------------
95
 
96
    signal data_in_reduced: unsigned ( (adc_bit_num - 2) downto 0) := (others => '0'); -- 13 bitov rabm, da sam pozitivne vrednosti berem, negativnih ne
97
 
98
    signal data_out_sig: unsigned ( (bit_num - 1) downto 0 ) := (others => '0');
99
 
100
    signal AD_addr_sig: unsigned ( (buffer_size - 1) downto 0) := (others =>'0');
101
 
102
    signal absolute_addr: integer := 0; -- ta šteje število podatkov in pol to pretvarja v naslov za bram bufferje (AD_addr_sig = absolute_addr % (2**buffer_size) 
103
 
104
    signal unit: integer := 0;
105
    signal unit_next: integer := 1;
106
    signal last_unit: std_logic;-- := '0';
107
 
108
    signal delay_cycles : integer := 0;
109
    signal delay_cycles_2 : integer := 0;
110
    signal delay_flag : boolean := FALSE;
111
 
112
 
113
   --MODE 3 SIGNALI----------------------------------------- 
114
    --signal threshold_dig: unsigned ( (11 - 1) downto 0 ) := (others => '0'); -- threshold pride notr kot analogna vrednost, potem jo pretvorim v digialno in to zapisem v ta signal: POPRAVEK: zaenkrat ne bo tako, bom kar digitalno vrednost poslal, pretvorba iz analogne sledi v C-programu
115
    signal data_in_mapped: unsigned ( (bit_num - 1) downto 0) := (others => '0'); -- pretvorjen data_in_reduced iz 13 bitov na 10 bitov
116
    signal data_in_mapped_prev: unsigned ( (bit_num - 1) downto 0) := (others => '0'); --gledam prejsnjo vrednost, da dolocicm trenutek prehoda pod treshold
117
    signal send_data_flag: std_logic := '0';
118
 
119
    signal counter: unsigned ( (byte - 1) downto 0) := (others => '0');
120
 
121
    signal int_res_sig: std_logic := '1'; --integrator reset signal   1: RESET , 0: INTEGRIRAJ
122
    signal int_reset_time_cycles: integer := 40;--25; --25 ciklov * 8ns = 200ns
123
    type integrator_mode is (INTEGRATE, RESET); -- stanji integratorja
124
    signal int_state: integrator_mode := INTEGRATE;
125
 
126
    signal trigger_in_reduced: unsigned ( (adc_bit_num - 2) downto 0) := (others => '0');
127
    signal trigger_in_inverted: unsigned ( (adc_bit_num - 1) downto 0) := (others => '0');
128
 
129
begin
130
 
131
--DEL KODE, KI VELJA ZA VSE MODE
132
data_in_reduced <= data_in(12 downto 0) when data_in(13) = '0' else -- vzemi samo pozitivne vrednosti, negativne na 0
133
                  (others => '0') when data_in(13) = '1';
134
 
135
--trigger_in_reduced <= PM_trigger_in(12 downto 0) when PM_trigger_in(13) = '1' else --za vsak slucaj, ce ne gre po dvojiskem komplementu
136
                     -- (others => '0');
137
 
138
trigger_in_inverted <= (not(PM_trigger_in) + 1) when PM_trigger_in(13) = '1' else --dvojiski komplement, hocem pozitivno vrednost, je lazje primerjat
139
                       (others => '0');
140
 
141
data_out <= data_out_sig;
142
 
143
 
144
 
145
 
146
------------------------MODE_1 IN MODE_2 -------------------------------------------------------------------
147
------------------------------------------------------------------------------------------------------------
148
------------------------------------------------------------------------------------------------------------
149
 
150
 
151
 
152
MODE_1_MODE_2: if (mode = "MODE_1" or mode = "MODE_2") generate
153
 
154
---COMBINATIONAL PART-------------------------------
155
 
156
 
157
    AD_addr <= AD_addr_sig;
158
 
159
 
160
    last_unit <= '1' when unit = num_of_units - 1 else
161
                 '0';
162
 
163
 
164
---SEQUENTIAL PART------
165
 
166
    Data_handling_1_2: process (clk_in)
167
       variable end_flag: std_logic := '0';
168
       variable first_flag: std_logic := '0';
169
       variable delay_flag: boolean := FALSE;
170
    begin
171
 
172
        if (rising_edge(clk_in)) then
173
 
174
                if (START = '1') then
175
 
176
                    if(num_of_units = 1) then
177
 
178
                        if(first_flag = '0') then --ko gres prvic skos
179
                            AD_wr_en(0) <= '1'; --prizgi PE_enoto
180
 
181
                            if(delay_cycles < 2) then --delay za 2 cikla
182
                                delay_cycles <= delay_cycles + 1;
183
                            end if;
184
 
185
                            if (delay_cycles = 2) then
186
                                -- naslovi in izhodni podatki
187
                                absolute_addr <= absolute_addr + 1;
188
                                AD_addr_sig <= to_unsigned( absolute_addr rem (2**buffer_size), buffer_size ); -- TODO: 30.11.2018 -- TEGA SPLOH NI TREBA, ker ne uporabljam tega signala v temu mode-u
189
                                data_out_sig <= data_map(data_in_reduced, adc_low, adc_high, mapped_low, mapped_high); -- isto kot komentar eno vrstico zgoraj
190
                            end if;
191
 
192
                            if (AD_addr_sig = 2**buffer_size - 2) then -- ce je -1 pol enga prevec nakonc vpise 
193
                                AD_wr_en(0) <= '0';
194
                                delay_cycles <= 0;
195
                                first_flag := '1';
196
                            end if;
197
 
198
                        elsif(first_flag = '1') then --ideja: tale del das delay ene par ciklov, tolk da ADC_unit_feedback oz. UC_rd_en_sig ze na 1 skoc in pol gledas kdaj je naslednjic 0, to je pa glih takrt k rabs przgat spet
199
 
200
                            if (delay_cycles < 6) then --6 zato, ker tok cajta rab, da UC_wr_en skoc na '1'       
201
                                delay_cycles <= delay_cycles + 1;
202
                                absolute_addr <= 0;
203
                                AD_addr_sig <= (others => '0');
204
                            end if;
205
 
206
                            if( delay_cycles = 6 and ADC_unit_feedback = '0' and AD_addr_sig < 2**buffer_size - 1 ) then --mislim, da addr in data out tukaj ne rabim prirejat, ker sem ga ze zgoraj
207
                                AD_wr_en(0) <= '1';                           --ADC_unit_feedback je v tukaj UC_rd_en_sig, zarad muxa v hist_system_top
208
                                delay_cycles <= 6;
209
 
210
                                if(delay_cycles_2 < 2) then --delay za 2 cikla
211
                                    delay_cycles_2 <= delay_cycles_2 + 1;
212
                                end if;
213
 
214
                                if (delay_cycles_2 = 2) then
215
                                    absolute_addr <= absolute_addr + 1;
216
                                    AD_addr_sig <= to_unsigned( absolute_addr rem (2**buffer_size), buffer_size ); -- isto kot v C-ju: absolute_addr % 2**buffer_size (ostanek pri deljenju)
217
                                    data_out_sig <= data_map(data_in_reduced, adc_low, adc_high, mapped_low, mapped_high);
218
                                end if;
219
                            end if;    
220
 
221
                            if (AD_addr_sig = 2** buffer_size - 2) then
222
                                AD_wr_en(0) <= '0';
223
                                delay_cycles <= 0;
224
                                delay_cycles_2 <= 0;
225
                            end if;
226
 
227
                        end if;
228
 
229
 
230
 
231
                    --ZA VEC ENOT-------------------------------------------
232
                    elsif (num_of_units /= 1 and ADC_unit_feedback = '0') then
233
 
234
                        -- naslovi in izhodni podatki
235
                        absolute_addr <= absolute_addr + 1;
236
                        AD_addr_sig <= to_unsigned( absolute_addr rem (2**buffer_size), buffer_size ); -- isto kot v C-ju: absolute_addr % 2**buffer_size (ostanek pri deljenju)
237
                        data_out_sig <= data_map(data_in_reduced, adc_low, adc_high, mapped_low, mapped_high);
238
 
239
 
240
                        --menjava enot
241
                        if (AD_addr_sig = 2**buffer_size - 1) then
242
 
243
                            if(unit < num_of_units - 2) then
244
                                unit <= unit_next;
245
                                unit_next <= unit_next + 1;
246
 
247
                            elsif (last_unit = '0') then --za zadnjo enoto
248
                                unit <= unit_next;
249
                                --unit_next <= unit_next;--  = kokr da nc ne napisem, pac ne povecam se enkrat
250
                            end if;
251
 
252
                        end if;
253
 
254
 
255
 
256
                        --priziganje in ugasanje enot
257
                        if (last_unit = '0') then  --vse enote razen zadnje
258
                            if (AD_addr_sig < 2**buffer_size - 2 ) then
259
 
260
                                AD_wr_en(unit) <= '1';
261
 
262
 
263
                            elsif (AD_addr_sig = 2**buffer_size - 1) then
264
                                AD_wr_en(unit) <= '0';
265
                                AD_wr_en(unit_next) <= '1';
266
 
267
                            end if;
268
 
269
                        elsif (last_unit = '1') then --ugasni zadnjo en ob pravem casu, prizge se pa: - ko je last unit se 0, ce je vec enot
270
                            if (AD_addr_sig < 2**buffer_size -1 and end_flag = '0') then                                 -- tukaj jo prizgem, ce je samo 1 enota
271
                                AD_wr_en(unit) <= '1';
272
                            else
273
                                AD_wr_en(unit) <= '0';
274
                                end_flag := '1'; --ko se AD_wr(unit) postavi na 0, se celotna elsif zanka potem se 1x izvede in AD_wr_en(unit) se
275
                            end if;             -- spet postavi na '1', kar ni OK. V ta namen tukaj postavim flag, da zadnja enota res ostane na 0
276
                        end if;                 -- ko jo tukaj izklopim (pogoj, da bi se postavila na '1' v vrstici 162 ni izpolnjen)
277
 
278
                    elsif (num_of_units /= 1 and ADC_unit_feedback = '1') then --resetiraj za naslednje sprejemanje, ce je vec enot. ce tega ni, se vse samo 1x izvede
279
                        AD_wr_en <= (others => '0');
280
                        data_out_sig <= (others => '0');
281
                        AD_addr_sig <= (others => '0');
282
                        absolute_addr <= 0;
283
                        unit <= 0;
284
                        unit_next <= 1;
285
                        end_flag := '0';
286
                    end if;
287
 
288
                else  --reset everything when START = '0'-- 
289
 
290
                    AD_wr_en <= (others => '0');
291
                    data_out_sig <= (others => '0');
292
                    AD_addr_sig <= (others => '0');
293
                    absolute_addr <= 0;
294
                    unit <= 0;
295
                    unit_next <= 1;
296
                    delay_cycles <= 0;
297
                    delay_cycles_2 <= 0;
298
                    first_flag := '0';
299
                    end_flag := '0';
300
                end if;
301
 
302
 
303
 
304
        end if;  
305
 
306
    end process;
307
 
308
end generate; --end of code for MODE_1 and MODE_2
309
 
310
 
311
 
312
 
313
------------------------MODE_3 -------------------------------------------------------------------
314
------------------------------------------------------------------------------------------------------------
315
------------------------------------------------------------------------------------------------------------
316
MODE_3: if (mode = "MODE_3") generate
317
 
318
----------COMBINATIONAL PART---------------------
319
    INT_res <=  int_res_sig; --SPREMENJENO 30.3.2019 -- not sm pobrisov, ker sm ga na zadnjem testiranju pomoje dodal, pa ga ni treba. 12-4.2019 -- vse dela ok
320
 
321
----------SEQUENTIAL PART---------------------------
322
 
323
    Data_handling_3: process (clk_in)
324
 
325
    variable min_value: unsigned ( (bit_num - 1) downto 0) := (others => '0'); -- minimalna (zacetna) vrednost na intervalu integriranja
326
    variable max_value: unsigned ( (bit_num - 1) downto 0) := (others => '0'); --maksimalna (koncna) vrednost na intervalu, ko integriramo
327
    --variable counter: unsigned ( (byte - 1) downto 0) := (others => '0');
328
    --variable go_measure: std_logic := '0';
329
    variable do_it_once: std_logic := '0';
330
    variable do_it_once_2: std_logic := '0';
331
 
332
    begin
333
 
334
        if ( rising_edge(clk_in) ) then
335
 
336
           --TODO: pogoj ADC_unit_feedback, da enota ve, kdaj lahko posilja podatke -- 3.2.2019: tole pomoje mam
337
 
338
           if (do_it_once = '0') then --tole samo zato, da ni na zacetku AD_wr_en(0) undefined
339
               AD_wr_en(0) <= '0';
340
               do_it_once := '1';
341
           end if;
342
 
343
 
344
            if ( START = '1' ) then
345
 
346
                data_in_mapped <= data_map(data_in_reduced, adc_low, adc_high, mapped_low, mapped_high);
347
 
348
                if (ADC_unit_feedback = '0' ) then
349
 
350
                    case int_state is
351
 
352
                        when INTEGRATE =>
353
 
354
                            int_res_sig <= '0'; --tole se uporabi samo prvic in samo prvic imam potem 1 clk zamude, ko pridem v INTEGRATE stanje, ker v ostalih primerih 
355
                                            -- sem ravno prisel iz RESET stanja, ki mi pa ze vklopi integriranje, prav zato, da ni 1 clk zamude pri zacetku integriranja
356
                                            -- potem, ko pridem v INTEGRATE stanje
357
 
358
                            if( int_res_sig = '0') then --pogoj zato, da ga ze takoj ne poveca, ko pade int_res na 0 ,ampak z enim clockom zamude, ker je drugace cas integriranja za 1 clock  napacen (prevelik)
359
 
360
                                if(do_it_once_2 = '0') then -- ta del pridobi vhodno vrednost na ADC na zacetku integriranja
361
                                    min_value := data_in_mapped;
362
                                    do_it_once_2 := '1';
363
                                end if;
364
 
365
                                counter <= counter + 1;
366
 
367
 
368
--                                if( counter < capt_num_of_samples - 1) then------------------------------------
369
 
370
--                                    if(data_in_mapped >= threshold) then
371
 
372
--                                        if(data_in_mapped > max_value) then
373
--                                            --max_value := data_in_mapped; --SPREMENJENO 22.7.2019
374
--                                        end if;
375
 
376
--                                    end if;
377
 
378
                                if( counter = capt_num_of_samples - 1) then  ---------------------------------
379
 
380
 
381
                                    send_data_flag <= '1'; --poslji maksimalen podatek v PE enoto
382
 
383
                                    --SPREMENJENO 22.7.2019
384
                                    if (data_in_mapped >= threshold) then
385
                                        data_out_sig <= data_in_mapped; --max_value; -- - min_value; --dodano
386
                                    end if;
387
 
388
 
389
                                    counter <= (others => '0');
390
                                    --max_value := (others => '0');
391
 
392
                                    int_res_sig <= '1'; --ustavi integriranje
393
                                    int_state <= RESET; -- pojdi v reset stanje
394
 
395
                                end if; -----------------------------------------------------------------------
396
 
397
                            end if;
398
 
399
 
400
                        when RESET =>
401
 
402
                            do_it_once_2 := '0';
403
                            --------------VPIS PODATKA V PE_unit----------------
404
                            if (send_data_flag = '1' and data_out_sig >= threshold) then-- data_out_sig dodano, da ne vpisuje nicel , > threshold mogoce
405
 
406
                                send_data_flag <= '0'; -- KO SE data_out_sig POJAVI NA IZHODNEM VODILU, JE POTREBNO POCAKATI EN CLK, 
407
                                AD_wr_en(0) <= '1';    --POTEM PA SELE VKLOPITI PISANJE (DA SE data_out PODATEK POJAVI NA old_value V PE_ENOTI)
408
 
409
                            else
410
                                AD_wr_en(0) <= '0';
411
                                send_data_flag <= '0'; --dodano
412
                                data_out_sig <= (others => '0'); --SPREMENJENO 22.7.2019 dodano
413
                            end if;
414
 
415
                            --------------ŠTETJE ČASA PRAZNJENJA KONDENZATORJA------
416
                            if (delay_cycles < int_reset_time_cycles - 1) then
417
                               delay_cycles <= delay_cycles + 1; --koliko ciklov je preteklo od začetka resetiranja integratorja
418
 
419
 
420
                            elsif (delay_cycles = int_reset_time_cycles - 1) then
421
                                if(to_integer(trigger_in_inverted(12 downto 0)) >= (to_integer(SW_trigger_value) *5) ) then--if ( to_integer(trigger_in_reduced) >= (to_integer(SW_trigger_value) * 5)) then
422
                                    int_res_sig <= '0'; --ze tukaj vklopi integriranje, da ni zamude po prihodu v INTEGRATE stanje
423
                                    int_state <= INTEGRATE;
424
                                    delay_cycles <= 0;
425
                                end if;
426
                            end if;
427
 
428
                    end case;                              
429
 
430
 
431
                else -- ce je ADC_unit_feedback '1'
432
                    data_out_sig <= (others => '0');
433
                    AD_wr_en(0) <= '0';
434
                    max_value := (others => '0');
435
                    counter <= (others => '0');
436
                    send_data_flag <= '0';
437
                    int_res_sig <= '1'; -- izklopi integrator
438
                    delay_cycles <= 0;
439
                    do_it_once_2 := '0';
440
 
441
                end if; --ADC_unit_feedback pogoj
442
 
443
 
444
            else
445
                do_it_once := '0';
446
                do_it_once_2 := '0';
447
                data_out_sig <= (others => '0');  
448
                AD_wr_en(0) <= '0';
449
                max_value := (others => '0');
450
                counter <= (others => '0');
451
                send_data_flag <= '0';
452
                int_res_sig <= '1'; -- izklopi integrator
453
                delay_cycles <= 0;
454
 
455
            end if; --start pogoj
456
 
457
        end if;--clk pogoj
458
 
459
 
460
    end process;
461
 
462
end generate; --konec MODE_3
463
 
464
 
465
 
466
end Behavioral;