Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

  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;
  467.