简体   繁体   English

VHDL中的FSM内部计数器

[英]Counter inside FSM in VHDL

I have got a small problem with my finite state machine which I have written in VHDL recently. 我最近用VHDL编写的有限状态机有一个小问题。 I tried to create "intelligent" counter triggered by clock with frequency 2 Hz. 我试图创建由频率为2 Hz的时钟触发的“智能”计数器。 This counter is built in one state of FSM and is started by pushing a button on DE2 board. 该计数器以FSM的一种状态构建,并通过按DE2板上的按钮启动。

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. 首先,整个系统处于“空闲”状态,如果按此按钮,状态将更改为“计数”,计数器开始增加,并且其当前值显示在LED显示屏上。 After it reach value of modulo, the state COUNTING is left back to IDLE and the counter is set up to zero. 达到模值后,状态COUNTING退回到IDLE,并将计数器设置为零。

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 因此,我尝试使用这种结构来解决它:如果(clk_tick´event和clk_tick = 1)则...。,综合存在一些错误:错误(10822):Citac_FSM.vhd(57)处的HDL错误:无法t在此时钟沿实现寄存器分配

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 错误(10821):Citac_FSM.vhd(62)处的HDL错误:无法推断“ AUTOMAT:flg”的寄存器,因为其行为与任何受支持的寄存器模型都不匹配

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? 用两个(或更多)时钟源编写时钟触发的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; 

Thank you very much. 非常感谢你。

Mirek 米雷克

PS: I am sorry my English is not so good. PS:对不起,我的英语不太好。

First of all you should not use clk_tick as a second clock signal. 首先,您不应将clk_tick用作第二个时钟信号。 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. 您应该做的是保存clk_tick的先前值,然后将clk_tick的当前值与先前的值进行比较以检测漂洗边缘。 Depending on how clk_tick is generated you might need to synchronize clk_tick to the clock domain of CLK. 根据clk_tick的生成方式,您可能需要将clk_tick同步到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. 我将留给您添加额外的寄存器。

I have already solved my problem :-). 我已经解决了我的问题:-)。 I have moved the counter into separate process and then attached witch signals to FSM. 我将计数器移到单独的过程中,然后将巫婆信号附加到FSM。 So, it works very well. 因此,它运作良好。

By reading of button I am using two D flip-flops to synchronize it at the moment. 通过读取按钮,我现在使用两个D触发器对其进行同步。

I have to make an observation on style of VHDL programming - it is too different to "normal" programming like C language :-D 我必须对VHDL编程的样式进行观察-它与“常规”编程(如C语言:-D)太不同了

Nice day! 美好的一天!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM