Search code examples
vhdlcounter

VHDL finite state machine counter with start


i pretty new of vhdl and i'm trying to learn how to do a FSM with vhdl. At moment i need a code that after a fixed count value, it give me back a pulse, in order to start a second FSM block. (I have a recurring signal every 100 kHz, i need to count it and release this signal after a fixed number of counts). Actually it work as free run, every time that it see this signal, it start to count, but realy i want to add a "start" signal, so it must start to count this signal after it see this start signal.

at moment my working code is:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity counter is
Port (
    signal_in : in STD_LOGIC := '0'; --segnale di start
    clk : in  STD_LOGIC; --clock di ingresso
    reset  : in  STD_LOGIC; --ff reset
    signal_out: out STD_LOGIC; --gate in uscita
    count_val: in std_logic_vector (7 downto 0);
    start : in STD_LOGIC := '0'


   );
end counter;

architecture behavioral of counter is
type state_type is (idle, count_up);
signal state : state_type;

begin
process (reset, clk, signal_in, start)
variable index : integer :=0;
variable countlen: integer;
variable count_v: std_logic;
variable countlen2 : std_logic;

begin

 countlen := to_integer(unsigned(count_val))-1;



if reset = '1' then  
  count_v := '0';
  index := 0;
  state <= idle;

else
--if start = '1' and
    --if rising_edge(clk) then
    if rising_edge(signal_in) then
    case state is
      when idle =>
        count_v :='0';
        index := 0;
        if (signal_in = '1') then
          state <= count_up;
          else
          state <= idle;
        end if;


      when count_up =>
        if(index < countlen) then
        state <=count_up;
        index := index + 1;
       elsif
        index = countlen then
        count_v := '1';
        state <=idle; 
        end if;        



      when others => null;
    end case;



  end if;
   end if;  

  signal_out <= count_v;

  end process; 


  end Behavioral;

Any attempt to work with cose with "start = 1" will stop the count. Please some one have some suggestion?

Kind REgards

Fulvio


Solution

  • Welcome om StackOverflow. Your specification is not 100% clear. What difference do you make between signal_in and start? According to your code and to your explanations, they both seem to act as a starter.

    Moreover, there are several strange things with your code:

    1. your process seems to be a synchronous one, with asynchronous reset. Its sensitivity list should contain only the clock and the reset. And its body should be:

      process(clk, reset)
          <variable declarations>
      begin
          <NOTHING HERE>
          if reset = '1' then
              <reset code>
          elsif rising_edge(clk) then
              <regular code>
          end if;
          <NOTHING HERE>
      end process;
      
    2. you are using signal_in as a clock and as a logic signal. This is extremely strange. Moreover, your if (signal_in = '1') then is always true (in the synthesis semantics) and thus useless.

    3. You are initializing variables at declaration (index). This is not supported by some synthesizers and hardware targets. Moreover, even when supported, it works only at power up. If:

      • you intend to synthesize your code,
      • you want it to be portable across synthesizers and hardware targets,
      • you want to re-initialize signal and variables not only at power up but also when a reset input is asserted,

      prefer a real explicit reset, instead, and guarantee that it is always asserted after power up (or at the beginning of a simulation) for proper first initialization.

    4. you declare variable index with a full integer range, that is, 32 bits minimum, while 8 bits would suffice. This is a potential waste of hardware resources.

    It is difficult to propose a solution without a clear and complete specification but assuming you want to count only after start has been asserted and only when signal_in is asserted, the following may be a starting point:

    process (clk, reset)
        variable index: natural range 0 to 255;
    begin
        if reset = '1' then
            state      <= idle;   
            signal_out <= '0';
            index      := 0;
        elsif rising_edge(clk) then
            case state is
                when idle =>
                    signal_out <= '0';
                    index      := 0;
                    if start = '1' then
                        state <= count_up;
                    end if;
                when others =>
                    if signal_in = '1' then
                        if index = to_integer(unsigned(count_val)) - 1 then
                            state      <= idle;
                            signal_out <= '1';
                        else
                            index := index + 1;
                        end if;
                    end if;
            end case;
        end if;
    end process;
    

    Note that this is really synchronous of your clock clk. I suspect that you made a very common mistake: as you wanted to increment your counter when signal_in is asserted you decided more or less to use signal_in as a clock. This is not a real synchronous and safe design. In a real safe synchronous design you do not use logic signals as clocks. You have well identified clocks and you use only these as clocks. In your case there is one single clock: clk. If you want to do something synchronously when a logic signal is asserted, wait for the rising edge of your clock and then test the logic signal and take appropriate actions.