2015-05-18 39 views
0

最近我用有限状态机写了一个小问题,我最近用VHDL编写了 。我试图创建由频率为2Hz的时钟触发的“智能”计数器 。 该计数器是建立在FSM的一种状态下,并通过按DE2板上的 按钮启动。VHDL中FSM的内部计数器

首先,整个系统处于空闲状态,如果按下此按钮,则状态为 变为COUNTING并且计数器开始递增,并且其当前的 值显示在LED显示屏上。在达到模数值后,状态 COUNTING被留回到IDLE并且计数器被设置为零。

我的问题是,计数器不能正常工作 - 计数 值太大了。所以我试图用这种结构解决它:如果 (clk_tick'event和clk_tick = 1)然后....有一些错误 综合: 错误(10822):Citac_FSM.vhd(57)的HDL错误:无法实施作业 上注册,这个时钟边沿

错误(10821):在Citac_FSM.vhd HDL错误(62):不能推断注册 “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:我很抱歉,我的英语不太好。

+0

第二个过程是时钟和非时钟逻辑的混合,这可能会混淆综合工具。将它们分开。并确保计数器是计时的:目前它是非计时的。或者更好的是,把整个作品写成一个更简单,更小的单进程状态机。 –

+0

如何生成'clk_tick'?每500ms发生一次1/50MHz的对称时钟还是1脉冲? –

回答

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; 

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

0

我已经解决了我的问题:-)。我已将柜台移至独立的过程,然后将女巫信号附加到FSM。所以,它工作得很好。

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

我必须作出一个观察的VHDL编程风格 - 这太不一样了“正常”编程像C语言:-D

愉快的一天!