Counter inside FSM in VHDL

浪子不回头ぞ 提交于 2019-12-25 05:36:07

问题


I have got a small problem with my finite state machine which I have written in VHDL recently. I tried to create "intelligent" counter triggered by clock with frequency 2 Hz. This counter is built in one state of FSM and is started by pushing a button on DE2 board.

Firstly, whole system is in IDLE state and if I push this button, state is changed to COUNTING and counter begin to be incremented and his current value is shown on LED display. After it reach value of modulo, the state COUNTING is left back to IDLE and the counter is set up to zero.

My problem is that the counter doesn´t work correctly - the counting value was too great. So I tried to solve it with this construction: if (clk_tick´event and clk_tick = 1) then.... , there are some errors by synthesis: Error (10822): HDL error at Citac_FSM.vhd(57): couldn't implement registers for assignments on this clock edge

Error (10821): HDL error at Citac_FSM.vhd(62): can't infer register for "AUTOMAT:flg" because its behavior does not match any supported register model

Please, does somebody have an idea to solve it? And what is it correct way to write clock triggered FSM with two (or more) clock sources?

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;

ENTITY Counter_FSM IS
 GENERIC (
      REGSIZE  : integer := 8;    -- range of counter
      MODULO   : natural := 50  -- modulo value
        );  
 PORT (
       CLK      : IN STD_LOGIC;    -- puls 50 MHz
       CLK_tick : IN STD_LOGIC;   -- puls 2 Hz
       RESET    : IN STD_LOGIC;  -- reset
       READY    : OUT STD_LOGIC; -- counter is ready to start
       START_C  : IN STD_LOGIC;  -- start of counting
       DOUT         : OUT STD_LOGIC_VECTOR(REGSIZE - 1 downto 0)  --out
    );
 END Counter_FSM;


ARCHITECTURE Behavior OF Counter_FSM is

    type counterState is (IDLE, COUNTING);  -- states of FSM
    signal currCounterState : counterState;     -- current state
    signal nextCounterState : counterState; -- next state
    signal cnt : std_logic_vector(REGSIZE - 1 downto 0);  -- counter

    begin 

    UPDATE: process(RESET, CLK)
        begin
            if (RESET = '0') then
                currCounterState <= IDLE;
            elsif (CLK'event and CLK = '1') then
                currCounterState <= nextCounterState;
            end if;
    end process;


    COMBI: process (clk_tick, start_c, currCounterState)
        variable flg : std_logic := '0';
         begin
             if (clk_tick'event and clk_tick = '1') then
                 flg := '1';
            end if;

            case currCounterState is
                when IDLE => 
                    cnt <= (others => '0'); -- counter value = zero
                   READY <= '1';               -- we can start
                    if (start_c = '1') then -- if button is pushed
                    nextCounterState <= COUNTING;   -- go to COUNTING
                    end if;

                when COUNTING => 
                    READY <= '0';
                    if (flg = '1') then -- Was there impuls of 2 Hz?
                        cnt <= cnt + 1;         -- yes -> incrementing
                        flg := '0';
                        if (cnt = MODULO) then  -- if cnt = MODULO
                            cnt <= (others => '0'); -- then cnt = zero
                            nextCounterState <= IDLE;   
                        end if;
                    end if;

                when others => 
                    nextCounterState <= IDLE;
            end case;
        -- OUTPUT 
            douT <= cnt;    
        end process;

end Behavior; 

Thank you very much.

Mirek

P.S.: I am sorry my English is not so good.


回答1:


First of all you should not use clk_tick as a second clock signal. What you should do is to save the previous value of clk_tick, then compare the current value of clk_tick to the previous value to detect a rinsing edge. Depending on how clk_tick is generated you might need to synchronize clk_tick to the clock domain of CLK.

You could write something like this:

when COUNTING => 
    nextCounterState <= COUNTING; 
    READY <= '0';
    if (prev_clk_tick = '0' and clk_tick = '1') then 
        next_cnt <= cnt + 1;         -- yes -> incrementing
        if (cnt = MODULO) then
            next_cnt <= (others => '0');
            nextCounterState <= IDLE;   
        end if;
    end if;

I will leave it to you to add the extra registers.




回答2:


I have already solved my problem :-). I have moved the counter into separate process and then attached witch signals to FSM. So, it works very well.

By reading of button I am using two D flip-flops to synchronize it at the moment.

I have to make an observation on style of VHDL programming - it is too different to "normal" programming like C language :-D

Nice day!



来源:https://stackoverflow.com/questions/30302117/counter-inside-fsm-in-vhdl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!