Search code examples
vhdlfpga

VHDL change CLK speed


From this code I create a block, then add CLK, KEY[0] and LEDR[0:15]

   library ieee;
use ieee.std_logic_1164.all;

--library work;
--use work.car_pkg.all;


entity knight_rider2 is
    port (  clk, resetn, clock_button : in std_logic;
        led1, led2, led3, led4, led5, led6, led7, led8, 
        led9, led10, led11, led12, led13, led14, led15 : out std_logic);
end entity knight_rider2;



architecture fsm of knight_rider2 is
    type state_types is (start, forward1, forward2, forward3, 
    forward4, forward5, forward6, forward7, forward8, forward9, 
    forward10,forward11,forward12, forward13, forward14);


    signal state: state_types;
    signal led_states : std_logic_vector(14 downto 0);

begin

             count : process(clk, resetn, clock_button)
begin
  if clock_button = '0' then
    counter   <= 0;
    fsm_pulse <= '0';
  else
    if rising_edge(clk) then
      counter     <= counter + 1;
      fsm_pulse   <= '0';
      if counter = divider then
        fsm_pulse <= '1';
        counter   <= 0;
      end if;
    end if;
  end if;
end process;


    combined_next_current: process (clk, resetn, clock_button)
    begin
        if (resetn = '0') then
            state <= start;
        elsif rising_edge(clk) then
            if fsm_pulse = '1' then
            case state is

                when start => 
                    state <= forward1;

                when forward1 =>                
                    state <= forward2;              


                when forward2 =>                    
                        state <= forward3;              

                when forward3 =>            
                        state <= forward4;              

                when forward4 =>                    
                        state <= forward5;                  


                when forward5 =>                
                        state <= forward6;                  


                when forward6 =>                    
                        state <= forward7;                  


                when forward7 =>                
                            state <= forward8;              

                when forward8 =>                    
                            state <= forward9;      


                when forward9 =>                    
                            state <= forward10;                     

                when forward10 =>                       
                            state <= forward11;


                when forward11 =>                   
                            state <= forward12;                 


                when forward12 =>                       
                            state <= forward13;


                when forward13 =>                       
                            state <= forward14;



                when forward14 => state <=start;

                when others =>
                state <= forward1;

            end case;
        end if;
    end process;


    --combinational output logic

    --internal signal to control state machine transistions


    led_select : process(state)
begin
  case state is
    when forward1 =>
     led_states <= "000000000000011";
     when forward2 =>
     led_states <= "000000000000110";
    when forward3 =>
     led_states <= "000000000001100";
    when forward4 =>
     led_states <= "000000000011000";
     when forward5 =>
     led_states <= "000000000110000";
     when forward6 =>
     led_states <= "000000001100000";
     when forward7 =>
     led_states <= "000000011000000";
     when forward8 =>
     led_states <= "000000110000000";
     when forward9 =>
     led_states <= "000001100000000";
     when forward10 =>
     led_states <= "000011000000000";
     when forward11=>
     led_states <= "000110000000000";
     when forward12=>
     led_states <= "001100000000000";
     when forward13=>
     led_states <= "011000000000000";
     when forward14=>
     led_states <= "110000000000000";
     when others =>
     led_states <= "100000000000001";

  end case;
end process;

led1 <= led_states(0);
led2 <= led_states(1);
led3 <= led_states(2);
led4 <= led_states(3);
led5 <= led_states(4);

led6 <= led_states(5);
led7 <= led_states(6);
led8 <= led_states(7);
led9 <= led_states(8);
led10 <= led_states(9);

led11 <= led_states(10);
led12 <= led_states(11);
led13 <= led_states(12);
led14 <= led_states(13);
led15 <= led_states(14);





end;

But now I want add KEY[1] button to change speed, for example:

1st press : 2*f

2 press: 4*f

3 press: 8*f

4 press: f

5 press: 2*f etc

So, how can I change this code to do what I want?


Solution

  • You can change the rate that your state machine operates at by employing a counter, for example:

    -- Generate a counter at your main clock frequency
    -- counter is declared as an integer.
    count : process(clock, resetn)
    begin
      if resetn = '0' then
        counter   <= 0;
        fsm_pulse <= '0';
      else
        if rising_edge(clock) then
          counter     <= counter + 1;
          fsm_pulse   <= '0';
          if counter = divider then
            fsm_pulse <= '1';
            counter   <= 0;
          end if;
        end if;
      end if;
    end process;
    

    The new signals are declared as follows:

    signal fsm_pulse : std_logic;
    signal counter   : integer;
    signal divider   : integer;
    

    Then, in your FSM process you can trigger state transitions using the fsm_pulse you generated:

    combined_next_current: process (clk, resetn)
    begin
        if (resetn = '0') then
            state <= start;
        elsif rising_edge(clk) then
          if fsm_pulse = '1' then
            case state is
                when start => 
                    state <= forward1;
                when forward1 =>                
                    state <= forward2; 
    
            ...
    
            etc (your remaining states)
          end if;
    

    The fsm_pulse will be set to '1' for a single clock cycle whenever the counter reaches the divider value you have chosen. The divider value represents the number of clock cycles you desire each FSM transition to occur after, for example a divider of zero will make the FSM transition at the main clock frequency and a divider of 1 will make the FSM transition at halve the main clock frequency.