VHDL中FSM内的计数器

时间:2015-05-18 11:33:58

标签: process synchronization vhdl counter fsm

我的有限状态机遇到了一个小问题 最近用VHDL编写。我试图创造“智能”计数器 由频率为2 Hz的时钟触发。 此计数器构建在一个FSM状态,并通过按a启动 DE2板上的按钮。

首先,整个系统处于IDLE状态,如果按下此按钮,状态为 改为COUNTING,计数器开始增加和他的当前 值显示在LED显示屏上。在达到模数值后,状态 COUNTING返回IDLE,计数器设置为零。

我的问题是计数器无法正常工作 - 计数 价值太大了。所以我尝试用这种结构解决它:如果 (clk_tick'event和clk_tick = 1)然后....,有一些错误 合成: 错误(10822):Citac_FSM.vhd(57)的HDL错误:无法实现 寄存器用于此时钟边沿的分配

错误(10821):Citac_FSM.vhd(62)处的HDL错误:无法推断注册 “AUTOMAT:flg”因为它的行为与任何支持的寄存器都不匹配 模型

拜托,有人有想法解决它吗?什么是正确的方式 用两个(或更多)时钟源写时钟触发的FSM?

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; 

非常感谢。

米雷克

P.S。:对不起,我的英语不太好。

2 个答案:

答案 0 :(得分:0)

首先,你不应该使用clk_tick作为第二个时钟信号。 您应该做的是保存clk_tick的先前值,然后将clk_tick的当前值与先前的值进行比较以检测冲洗边缘。根据clk_tick的生成方式,您可能需要将clk_tick与CLK的时钟域同步。

你可以这样写:

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;

我会留给你添加额外的寄存器。

答案 1 :(得分:0)

我已经解决了我的问题:-)。我已经将计数器移动到单独的过程中,然后将女巫信号附加到FSM。所以,它运作良好。

通过阅读按钮,我正在使用两个D触发器来同步它。

我必须对VHDL编程的风格进行观察 - 它与C语言的“普通”编程有太大不同:-D

美好的一天!