-- |-------------------------------------------------------------------------|
-- | Projet         : fréquencemètre                                          
-- | Carte         : prototype freq                                                            
-- | Bloc Superieur : Aucun                                                                            
-- | Description     : Mesure de la fréquence d'un signal
-- |                   compteur des impulsions pendant une seconde
-- |                   gestion de la donnée vers afficheur 7 ségments        
-- |                                  
-- |                                                                
-- | Version | Auteur         |   Date   | Observations                
-- |   1.0   |   F.P         | 24/03/03 | Création                    
---|-------------------------------------------------------------------------|
--
--
-- Remarques :
-- Une des premières restrictions dans un composant programmable, c'est le nombre
-- de process clocké sur des horloges différentes   ; en effet le composant dispose d'un
-- nombre limité de réseau d'horloge permettant l'accès aux bascules. Ces réseaux permettent
-- d'avoir l'horloge en phase sur les différentes bascules. Les routages sont réalisés
-- de façon similaires entre un point d'entrée du réseau et chacune des bascules.
-- Ne pas passer par ce réseau entrainerait des temps de routage différents entre l'horlge
-- de deux bascules, ce qui peut-être fort regrétable si ce temps devient supérieur à la période...
--

library IEEE ;
use IEEE.Std_logic_1164.all ;
use IEEE.Numeric_std.all ;

entity mesure_freq is port (
  XGSR             : in   std_logic ; -- Reset asynchrone, programmation des xilinx
  I_CLK_10M       : in   std_logic ; -- Horloge 10 MHz provenant du TCXO externe
  I_input_HF       : in   std_logic ; -- Entrée du signal mode HF
  I_input_BF       : in   std_logic ; -- Entrée du signal mode BF
  I_select         : in   std_logic ; -- Entrée de sélection BF/HF
  I_prediv_128     : in   std_logic ; -- facteur de division du pré diviseur HF
  I_prediv_64     : in   std_logic ; -- A '1' si le facteur de division utilisé=64
  O_Sel_0to9       : out std_logic_vector ( 9 downto 0 ) ; --10 digits
  O_7segments     : out std_logic_vector ( 6 downto 0 )   --7 ségments
) ;
end mesure_freq ;
 
architecture Alpha of mesure_freq is

  -- Génération des horloges 1 seconde, 1 milliseconde et 1 microseconde
  signal Osc_1sec           : std_logic ; --1ms/1000
  signal Osc_1msec         : std_logic ; --1us/1000  
  signal Osc_1usec         : std_logic ; --10MHz/10
  signal Cpt_Div10         : natural range 0 to 9 ;
  signal Cpt_Div1000       : natural range 0 to 999 ;
  signal Cpt_Div1000bis     : natural range 0 to 999 ;
  signal Osc_1msec_D       : std_logic ;
  signal Osc_1usec_D       : std_logic ;
  signal Top_1msec         : std_logic ;
  signal Top_1usec         : std_logic ;
 
  -- signaux de traitement divers
  signal select_auto_BF     : std_logic ; -- détection automatique de signal HF
  signal Clk_mesure         : std_logic ; -- signal à mesurer multipléxé BF/HF
  signal Clear             : std_logic ; -- raz du copmteur fréquence
  signal Clear_synchroFs   : std_logic ; -- A '1' toute les secondes, dure 1
                                        -- cycle du signal 10MHz
  signal Clear_synchroFs_D : Std_logic ; -- Synchronisation sur fin
  signal Fd_Clear_Fs       : std_logic ; -- détecstion de front, 1 cycle de fin
 
  -- compteur BCD sur la fréquence à afficher
  type BCD_vector is array ( 9 downto 0 ) of unsigned( 3 downto 0 ) ;
  signal BCDcount           : BCD_vector ; -- compteur temps réel
  signal mem_val           : BCD_vector ; -- compteur mémorisé chaque seconde
 
  -- gestion de l'afficheur
  signal Osc_1sec_D         : std_logic ; -- signal seconde décalé
  signal Top_sec           : std_logic ; -- top fin de mesure pour mémorisation
  signal Sept_segments     : std_logic_vector ( 6 downto 0 ) ;
  signal MCDU_val           : std_logic_vector ( 3 downto 0 ) ; -- valeur décimale unitaire
  signal Sel_0to9           : std_logic_vector ( 9 downto 0 ) ;
  signal Cpt_0to9           : natural range 0 to 9 ;

  signal high               : std_logic ;
  signal low               : std_logic ;  

begin

  high <= '1' ;
  low   <= '0' ;

  O_7segments <= Sept_segments ;
  O_sel_0to9   <= sel_0to9 ;

  Clk_mesure   <= I_input_HF when ( I_select='1' ) else I_input_BF ;

  -- on insère dans le réseau d'horloge :
  -- Clk_mesure ( ou bufgmux ! )
  -- Clk 10MHz.

  ---------------------------------
  -- Génération de l'horloge 1usec
  -- 10MHz/10 = 1 micro seconde
  ---------------------------------

  process( I_CLK_10M, XGSR )
  begin
    if ( XGSR='1' ) then
      Cpt_Div10   <= 0 ;
      Osc_1usec   <= '0' ;
      Top_1usec   <= '0' ;
      Osc_1usec_D <= '0' ;
    elsif rising_edge( I_CLK_10M ) then
      if ( Cpt_Div10=9 ) then
        Cpt_Div10 <= 0 ;
      else
        Cpt_Div10 <= Cpt_Div10 + 1 ;
      end if ;
      if ( Cpt_Div10 < 5 ) then
        Osc_1usec <= '0' ; --0,1,2,3,4
      else
        Osc_1usec <= '1' ; --5,6,7,8,9
      end if ;
      Osc_1usec_D <= Osc_1usec ;
      Top_1usec <= Osc_1usec and not Osc_1usec_D ;
  end if ;
  end process ;
 
  ---------------------------------
  -- Génération de l'horloge 1msec
  -- ( 10MHz/10 )/1000 = 1 milli seconde
  ---------------------------------

  process( I_CLK_10M, XGSR )              
  begin
    if ( XGSR='1' ) then
      Cpt_Div1000 <= 0 ;
      Osc_1msec   <= '0' ;
      Osc_1msec_D <= '0' ;
      Top_1msec   <= '0' ;
    elsif rising_edge( I_CLK_10M ) then
    if ( Top_1usec='1' ) then
      if ( Cpt_Div1000=999 ) then
        Cpt_Div1000 <= 0 ;
      else
        Cpt_Div1000 <= Cpt_Div1000 + 1 ;
      end if ;
      if ( Cpt_Div1000 < 500 ) then
        Osc_1msec <= '0' ;
      else
        Osc_1msec <= '1' ;
      end if ;
    end if ; -- CE 1/10
    Osc_1msec_D <= Osc_1msec ;
    Top_1msec <= Osc_1msec and not Osc_1msec_D ;
  end if ;
  end process ;
 
  ---------------------------------
  -- Génération de l'horloge 1 sec
  -- Osc_1msec/1000 = 1 seconde
  ---------------------------------

  process( I_CLK_10M, XGSR )
  begin
    if ( XGSR='1' ) then
      Cpt_Div1000bis <= 0 ;
      Osc_1sec       <= '0' ;
    elsif rising_edge( I_CLK_10M ) then
    if ( Top_1msec='1' ) then
      if ( Cpt_Div1000bis=999 ) then
        Cpt_Div1000bis <= 0 ;
      else
        Cpt_Div1000bis <= Cpt_Div1000bis + 1 ;
      end if ;
      if ( Cpt_Div1000bis < 500 ) then
        Osc_1sec <= '0' ;
      else
        Osc_1sec <= '1' ;
      end if ;
    end if ; -- CE 1/( 10*1000 )
  end if ;
  end process ;

  ------------------------------------------------------
  -- Compteur principal, nb de période du signal d'entrée
  -- dans N secondes ( N=1 à 8 : précision )
  -- Signaux d'entrée :
  -- Clear : pour la remise à zéro, synchrone 10MHz !!!
  --         pendant la durée active du clear, on ne compte pas...
  -- EnableCounters : validation du compteur
  -- Signaux de sorties :
  -- BSDcount : valeur BCD de la fréquence
  ------------------------------------------------------
  process( Clk_mesure, XGSR )
  begin
    if ( XGSR='1' ) then
      Clear_synchroFs   <= '0' ;
      Clear_synchroFs_D <= '0' ;
      Fd_Clear_Fs       <= '0' ;
      for I in 9 downto 0 loop
        BCDcount( I ) <= "0000" ;
      end loop ;
    elsif rising_edge( Clk_mesure ) then
      Clear_synchroFs   <= Clear ;
      Clear_synchroFs_D <= Clear_synchroFs ;
      Fd_Clear_Fs       <= Clear_synchroFs and not Clear_synchroFs_D ;
      if ( Fd_Clear_Fs = '1' ) then
        for I in 9 downto 0 loop
          BCDcount( I ) <= "0000" ;      
        end loop ;
      else
        --if EnableCounters = '1' then
          for I in 0 to 9 loop
            if BCDcount( I ) < "1001" then
              BCDcount( I ) <= BCDcount( I ) + "1" ;
              exit ;
            else
              BCDcount( I ) <= "0000" ;
            end if ;
          end loop ;
        --end if ;
      end if ;
    end if ;
  end process ;

  ------------------------------------------------
  -- Le signal fin est divisé par 128 en mode HF,
  -- on effectue donc un décalage de 7 à gauche,
  -- la précision sur une seconde est limitée, on
  -- compte donc plus longtemps...
  ------------------------------------------------
  process( I_CLK_10M, XGSR )
  begin
  if ( XGSR='1' ) then
    for I in 9 downto 0 loop
      mem_val( I ) <= "0000" ;
    end loop ;
    Osc_1sec_D   <= '0' ;
    Top_sec       <= '0' ;
    Cpt_0to9     <= 0 ;
    Clear         <= '0' ;
  elsif rising_edge( I_CLK_10M ) then  
    Osc_1sec_D <= Osc_1sec ;
    Top_sec <= not Osc_1sec and Osc_1sec_D ;
    if ( Top_1msec = '1' ) then             -- Top_sec
      mem_val <= BCDcount ;
      Clear   <= '1' ;
    else
      Clear   <= '0' ;
    end if ;
    -- compteur permanant pour sélection de l'afficheur 1 parmi 9
    if ( Cpt_0to9=9 ) then
      Cpt_0to9 <= 0 ;
    else
      Cpt_0to9 <= Cpt_0to9 + 1 ;
    end if ;
  end if ;
  end process ;

  Def_sel_0to9: process ( Cpt_0to9 )
  begin
    case Cpt_0to9 is
      when 0 => sel_0to9 <= "0000000001" ;
      when 1 => sel_0to9 <= "0000000010" ;
      when 2 => sel_0to9 <= "0000000100" ;
      when 3 => sel_0to9 <= "0000001000" ;
      when 4 => sel_0to9 <= "0000010000" ;
      when 5 => sel_0to9 <= "0000100000" ;
      when 6 => sel_0to9 <= "0001000000" ;
      when 7 => sel_0to9 <= "0010000000" ;
      when 8 => sel_0to9 <= "0100000000" ;
      when 9 => sel_0to9 <= "1000000000" ;
      when others => sel_0to9 <= "0000000000" ;
    end case ;
  end process ;

  -----------------------------------------------------------------------------
  -- A positionner ds le case ci-dessus...
  -----------------------------------------------------------------------------
  Selection_aff: process ( sel_0to9 )
  begin
    case sel_0to9 is
      when "0000000001" => MCDU_val <= std_logic_vector ( mem_val( 0 ) ) ;
      when "0000000010" => MCDU_val <= std_logic_vector ( mem_val( 1 ) ) ;
      when "0000000100" => MCDU_val <= std_logic_vector ( mem_val( 2 ) ) ;
      when "0000001000" => MCDU_val <= std_logic_vector ( mem_val( 3 ) ) ;
      when "0000010000" => MCDU_val <= std_logic_vector ( mem_val( 4 ) ) ;
      when "0000100000" => MCDU_val <= std_logic_vector ( mem_val( 5 ) ) ;
      when "0001000000" => MCDU_val <= std_logic_vector ( mem_val( 6 ) ) ;
      when "0010000000" => MCDU_val <= std_logic_vector ( mem_val( 7 ) ) ;
      when "0100000000" => MCDU_val <= std_logic_vector ( mem_val( 8 ) ) ;
      when "1000000000" => MCDU_val <= std_logic_vector ( mem_val( 9 ) ) ;
      when others => MCDU_val <= "0000" ;
    end case ;
  end process ;

  EncodeurSeptSegments: process ( MCDU_val )
  begin
    case MCDU_val is
      when "0000" => sept_segments <= "1111110" ;
      when "0001" => sept_segments <= "0110000" ;
      when "0010" => sept_segments <= "1101101" ;
      when "0011" => sept_segments <= "1111001" ;
      when "0100" => sept_segments <= "0110001" ;
      when "0101" => sept_segments <= "1011011" ;
      when "0110" => sept_segments <= "0011111" ;
      when "0111" => sept_segments <= "1110000" ;
      when "1000" => sept_segments <= "1111111" ;
      when "1001" => sept_segments <= "1110011" ;
      when others => sept_segments <= "-------" ;
    end case ;
  end process ;

  --LeadingZeroSuppress: process
  --begin
  --   wait until Rising_edge( Osc ) ;
  --   if IOshift = '0' then
  --     Suppress <= '1' ;
  --   elsif SR8x4( 7 ) /= "0000" then
  --     Suppress <= '0' ;
  --   end if ;
  --end process ;

  --LCDlogic: process ( Suppress, SR8x4( 7 ), Raw7Seg )
  --begin
  --   if Suppress = '1' and SR8x4( 7 ) = "0000" then
  --     Final7Seg <= "0000000" ;
  --   else
  --     Final7Seg <= Raw7Seg ;
  --   end if ;
  --end process ;

end Alpha ;

-------------------------------
-- Test du composant
-------------------------------

entity test_mesure_freq is
end ;

library IEEE ;
use IEEE.Std_logic_1164.all ;

architecture A of test_mesure_freq is

  component mesure_freq
  port (
    XGSR             : in   std_logic ; -- Reset asynchrone, programmation des xilinx
    I_CLK_10M       : in   std_logic ; -- Horloge 10 MHz provenant du TCXO externe
    I_input_HF       : in   std_logic ; -- Entrée du signal mode HF
    I_input_BF       : in   std_logic ; -- Entrée du signal mode BF
    I_select         : in   std_logic ; -- Entrée de sélection BF/HF
    I_prediv_128     : in   std_logic ; -- facteur de division du pré diviseur HF
    I_prediv_64     : in   std_logic ; -- A '1' si le facteur de division utilisé=64
    O_Sel_0to9       : out std_logic_vector ( 9 downto 0 ) ; --10 digits
    O_7segments     : out std_logic_vector ( 6 downto 0 ) ) ;
  end component ;

  signal Osc, Fin1, fin2, Reset: Std_logic := '0' ;
  signal LCD:   Std_logic_vector ( 55 downto 0 ) ;
  signal Going: Boolean := True ;
  signal Vcc:   Std_logic ;
  signal gnd : std_logic ;
 
begin
  Reset <= '1', '0' after 1 us ;
  gnd   <= '0' ;
  vcc   <= '1' ;

  process
    variable StopTime: TIME := 0 sec ;
    variable HalfPeriod: TIME := 1 ns ;
    -- 100 KHz, 10 KHz, 1 KHz, 100 Hz, 10 Hz
  begin
    for I in 1 to 5 loop
      StopTime := StopTime + 2.001 sec ;
      while now < StopTime loop
        Fin1 <= not Fin1 ;
        wait for HalfPeriod   ;
      end loop ;
      HalfPeriod := HalfPeriod * 10 ;
    end loop ;

    Going <= False ;
    wait ;
  end process ;

  fin2 <= Fin1 ;
 
  process
  begin
    while Going loop
      Osc <= not Osc ;
      wait for 10 ns ; --10MHz   --15.2587 us; -- 32KHz
    end loop ;
    wait ;
  end process ;

  uut:   mesure_freq
  port map (
    XGSR         => Reset,
    I_CLK_10M     => Osc,
    I_input_HF   => fin1,
    I_input_BF   => fin2,
    I_select     => vcc,
    I_prediv_128 => vcc,
    I_prediv_64   => gnd,
    O_Sel_0to9   => open,
    O_7segments   => open
  ) ;
end ;
   





HTML Source generated with the hdl2html perl script from Millogic