+ Post New Thread
Results 1 to 4 of 4
  1. #1
    Newbie level 2
    Points: 20, Level: 1

    Join Date
    Apr 2018
    Posts
    2
    Helped
    0 / 0
    Points
    20
    Level
    1

    VHDL. Failed Timing. Division

    Hello, I am new to VHDL. I want to make frequency meter from 1KHz to 300kHz and have one problem.
    I use division which have great impact to timing. So maybe someone have some ideas how to solve this ?

    Code:
    ----------------------------------------------------------------------------------
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.numeric_std.ALL;
    
    entity Freq_Counter is
        Port (  Clk : in STD_LOGIC;
              Data : in STD_LOGIC;
               seg : out STD_LOGIC_VECTOR (6 downto 0);
               an: out STD_LOGIC_VECTOR (3 downto 0));
    end Freq_Counter;
    
    architecture Behavioral of Freq_Counter is
    signal SD1 :  std_logic_vector(3 downto 0):="0000" ;
    signal SD2 :  std_logic_vector(3 downto 0):="0000" ;
    signal SD3 :  std_logic_vector(3 downto 0):="0000" ;
    signal Freq:integer range 0 to 300 :=0;
    signal N_Ticks: integer range 0 to 50000 :=0;
    component Segment
    port(
    Clk : in STD_LOGIC;
    Value1 : in STD_LOGIC_VECTOR (3 downto 0);
    Value2 : in STD_LOGIC_VECTOR (3 downto 0);
    Value3 : in STD_LOGIC_VECTOR (3 downto 0);
    seg : out STD_LOGIC_VECTOR (6 downto 0);
    an: out STD_LOGIC_VECTOR (3 downto 0));
    end component;
    
    begin
    
    Segments : Segment
    port map(
    Clk => Clk,
    Value1 => SD1,
    Value2 => SD2,
    Value3 => SD3,
    seg => seg,
    an => an);
    
    process(Data,Clk)
    Variable Ready : integer range 0 to 3 :=0;
    Variable N_Tick: integer range 0 to 50000 :=0;
    begin
    --------------------------BEGIN----------------------------
    if Clk'event and Clk ='1' then
    case Ready is
    
    when 0 =>
    
        if Data ='1' then
            Ready :=1;
        end if;
    
    when 1 => 
    
        N_tick := N_tick +1;
        if Data ='0' then
            Ready:=2;
        end if;
       if N_tick > 100000 then
                 N_tick:=0;
                 Ready:=3;
                 end if;
    
    when 2 => 
        N_tick := N_tick +1;
        if Data ='1' then
         N_ticks <= N_tick;
         Ready:=3;
        end if;
        if N_tick > 100000 then
             N_tick:=0;
             Ready:=3;
             end if;
        
    when 3 =>
     
     if Data ='0' then
     N_tick:=0;
     Ready:=0;
     end if;
     end case;
     end if;
     END PROCESS;
        
    process(CLK)
    constant Speed : integer:=100000;
    Variable duom1 : integer range 0 to 100000 :=0;
    begin
    if Clk'event and Clk ='1' then
    duom1:=duom1+1;
    if duom1>10000 then
    Freq <= Speed/N_ticks;
    duom1:=0;
      end if;
      end if;
     END PROCESS;
     
     process(CLK)
    
     Variable D1 : integer range 0 to 9 :=0;
     Variable D2 : integer range 0 to 9 :=0;
     Variable D3 : integer range 0 to 9 :=0;
     Variable  duom2 : integer range 0 to 100000 :=0;
     begin
    if Clk'event and Clk ='1' then
    duom2:=duom2+1;
    if duom2 > 10000 then
    D3 := freq/100;
    D2 :=(freq/10)mod 10 ;
    D1 := freq mod 10;
    if D1 = 1 then 
    SD1 <= "0001";
    elsif D1 = 2 then 
    SD1 <= "0010";
    elsif D1 = 3 then 
    SD1 <= "0011";
    elsif D1 = 4 then 
    SD1 <= "0100";
    elsif D1 = 5 then 
    SD1 <= "0101";
    elsif D1 = 6 then 
    SD1 <= "0110";
    elsif D1 = 7 then 
    SD1 <= "0111";
    elsif D1 = 8 then 
    SD1 <= "1000";
    elsif D1 = 9 then 
    SD1 <= "1001";
    else 
    SD1 <= "0000";
    end if;
    -----------------------------------------------------
    if D2 = 1 then 
    SD2 <= "0001";
    elsif D2 = 2 then 
    SD2 <= "0010";
    elsif D2 = 3 then 
    SD2 <= "0011";
    elsif D2 = 4 then 
    SD2 <= "0100";
    elsif D2 = 5 then 
    SD2 <= "0101";
    elsif D2 = 6 then 
    SD2 <= "0110";
    elsif D2 = 7 then 
    SD2 <= "0111";
    elsif D2 = 8 then 
    SD2 <= "1000";
    elsif D2 = 9 then 
    SD2 <= "1001";
    else 
    SD2 <= "0000";
    end if;
    -----------------------------------------------------
    if D3 = 1 then 
    SD3 <= "0001";
    elsif D3 = 2 then 
    SD3 <= "0010";
    elsif D3 = 3 then 
    SD3 <= "0011";
    elsif D3 = 4 then 
    SD3 <= "0100";
    elsif D3 = 5 then 
    SD3 <= "0101";
    elsif D3 = 6 then 
    SD3 <= "0110";
    elsif D3 = 7 then 
    SD3 <= "0111";
    elsif D3 = 8 then 
    SD3 <= "1000";
    elsif D3 = 9 then 
    SD3 <= "1001";
    else 
    SD3 <= "0000";
    end if;
    duom2:=0;
    end if;
    end if;
    end process;
    
    end Behavioral;

    •   AltAdvertisment

        
       

  2. #2
    Advanced Member level 3
    Points: 5,550, Level: 17

    Join Date
    Feb 2015
    Posts
    920
    Helped
    263 / 263
    Points
    5,550
    Level
    17

    Re: VHDL. Failed Timing. Division

    For practical implementation, I would use a small FSM. Basically, a design where there is a counter that accumulates count for 1 second. After that, use the basic "can I subtract 100000, 10000, 1000?" FSM to count the number of 100000 that can be subtracted, then the number of 10000 that can be subtracted, then the number of 1000 that can be subtracted. These become the signals to the bcd converter. This is probably what the assignment wants you to do.



    •   AltAdvertisment

        
       

  3. #3
    Newbie level 2
    Points: 20, Level: 1

    Join Date
    Apr 2018
    Posts
    2
    Helped
    0 / 0
    Points
    20
    Level
    1

    Re: VHDL. Failed Timing. Division

    thank you. I have though about such solution, but i hoped that there is easier way to do it.



    •   AltAdvertisment

        
       

  4. #4
    Super Moderator
    Points: 248,140, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    43,156
    Helped
    13131 / 13131
    Points
    248,140
    Level
    100

    Re: VHDL. Failed Timing. Division

    Ultimately, the divider timing problems are brought up because you want the result in a single clock cycle instead of enabling useful pipelining. The division is only needed once per measurement cycle and doesn't need to be particularly fast. An economic serial divider can be used for this purpose.

    There are other design details that have negative timing effects like that usage of variables.



--[[ ]]--