我需要监控两个信号的进程数量?

时间:2013-12-09 11:30:00

标签: vhdl

我是vhdl begginner,需要帮助解决我的问题。 我有2个需要监控的信号。一个是CHECK,另一个是OK。 每当我要求检查时,我都应该好(高或低)。 我需要连续监测6个连续的CHECK脉冲,然后计数OK。 如果我有6 OK(LOW),那么我需要产生输出(HIGH),任何其他情况输出(LOW)。 我写了一些代码,但上面没有产生想要的输出。但我首先有一个基本问题。 这可以在一个过程中完成吗?

--one process
if ...
  reset clauses
elsif
  count pulses and set a variable to 6
else  
  if variable = 6, produce output
end if;

还是我需要更多?

--first process
start counter on rising_edge of CHECK

-- second process
count pulses and set a signal some value (6)

-- third process 
monitor signal and if =6, produce output

编辑: 这是我尝试的代码,但失败了...将调查FSM ......

counter_operation:process (RESETn, CHECK, OK)
variable counter : unsigned (2 downto 0);
variable lost_count : unsigned (2 downto 0);
begin
-- if reset it asserted ensure counter is not running
if ( RESETn = '0') then
    trip_signal <= '0';
    lost_count := to_unsigned (0,3);
    counter := to_unsigned (0,3);

-- run counter and perform actions
elsif (rising_edge(CHECK)) then
        -- increment counter and limit maximum value
        counter := counter+1;   
        if (counter > to_unsigned(6,3) ) then
            counter := to_unsigned (0,3);
            lost_count := to_unsigned (0,3);
        end if;

        -- check for first OK(LOW)
        if (counter = to_unsigned(1,3))  then
            if (OK = '0') then
                lost_count := lost_count + to_unsigned (1,3);
            else
                lost_count := lost_count;   
            end if; 
        end if;
        -- check for second consecutive OK(LOW)
        if (counter = to_unsigned(2,3))  then
            if (OK = '0') then
                lost_count := lost_count + to_unsigned (1,3);
            else
                lost_count := lost_count;   
            end if; 
        end if;
        -- check for third consecutive OK(LOW)
        if (counter = to_unsigned(3,3))  then
            if (OK = '0') then
                lost_count := lost_count + to_unsigned (1,3);
            else
                lost_count := lost_count;   
            end if; 
        end if;
        -- check for fourth consecutive OK(LOW)
        if (counter = to_unsigned(4,3))  then
            if (OK = '0') then
                lost_count := lost_count + to_unsigned (1,3);
            else
                lost_count := lost_count;   
            end if; 
        end if;
        -- check for fifth consecutive OK(LOW)
        if (counter = to_unsigned(5,3))  then
            if (OK = '0') then
                lost_count := lost_count + to_unsigned (1,3);
            else
                lost_count := lost_count;   
            end if; 
        end if;
        -- check for sixth consecutive OK(LOW)
        if (counter = to_unsigned(6,3))  then
            if (OK = '0') then
                lost_count := lost_count + to_unsigned (1,3);
            else
                lost_count := lost_count;   
            end if; 
        end if;
        -- check if we lost 6 consecutive 
        if (lost_count = to_unsigned (6,3)) then
            trip_signal <= '1';
        else
            trip_signal <= '0'; 
        end if; 
    end if;
end process counter_operation;

我在这里定义有问题,因为模拟前后不会产生相同的结果。预SIM卡似乎有用,但后期SIM卡没有。

编辑(2): 对于FSM,这样的事情?

library IEEE;
use IEEE.std_logic_1164.all;

entity FSM_1 is
port (
    CHECK : in std_logic;
    CRC :in std_logic;
    CLK : in std_logic; 
    RESETn :in std_logic;
    OUT_SIG : out std_logic

);
end FSM_1;

architecture arch of FSM_1 is


-- signal, component etc. declarations
type TargetSeqStates is (IDLE, FIRST_CHECK, SECOND_CHECK, THIRD_CHECK, FOURTH_CHECK, FIFTH_CHECK, SIXTH_CHECK);
signal curr_st, next_st : TargetSeqStates;

begin
--------------------------------------------------------------------------------
-- Using the current state of the counter and the input signals, decide what the next state should be
--------------------------------------------------------------------------------
NxStDecode:process (CHECK, OK, curr_st)
begin
-- default next-state condition
next_st <= IDLE;
-- TODO...

-- TODO...
end process NxStDecode;
--------------------------------------------------------------------------------
-- At the desired clock edge, load the next state of the counter (from 1.) into the counter
-- create the current-state variables 
--------------------------------------------------------------------------------
CurStDecode:process (CLK, RESETn)
begin
-- Clear FSM to start state 
if (RESETn = '0') then
    curr_st <= IDLE;
elsif (rising_edge(CLK)) then
    curr_st <= next_st;
end if;
end process CurStDecode;

--------------------------------------------------------------------------------
-- Using the current state of the counter and the input signals, decide what the values of all output signals should be
--------------------------------------------------------------------------------
DecOutputs;process (curr_st)
begin
-- TODO....

-- TODO...

end process DecOutputs;

end arch;

我猜TODO部件是否依赖于状态图? 另外,我需要CLK吗?看来我需要改变状态, 在CHECK的rising_edge上,而不是CLK。

最终编辑:

counter_operation:process (RESETn, CHECK, OK, CLK)
variable lost_counter : integer := 0;
variable last_CHECK : std_logic;

begin
    if ( RESETn = '0') then
    D_TRIP <= '0';
    lost_counter := 0;

else 
    if (rising_edge(CLK)) then
        if (CHECK /= last_CHECK) then
            if (OK = '0') then
            lost_counter := lost_counter + 1;
            else
            lost_counter := 0;  
            end if; 
            D_TRIP <= '0';
            if (lost_counter = 6) then
            D_TRIP <= '1';
            lost_counter := 0;
            end if;   
        end if;
        last_CHECK := CHECK;
    end if;
end if;
end process counter_operation;

2 个答案:

答案 0 :(得分:1)

这是一个非常标准的状态机,大多数设计人员将使用一到三个进程来处理状态机。如果您刚刚开始,那么使用三个流程可能会让您更轻松。这些过程将是:

  1. 使用计数器的当前状态和输入信号,确定下一个状态应该是什么。
  2. 使用计数器的当前状态和输入信号,确定所有输出信号的值应该是什么。
  3. 在所需的时钟边沿,将计数器的下一个状态(从1开始)加载到计数器中。
  4. 请注意,前两个进程纯粹是组合逻辑,而第三个进程是时钟顺序进程。

答案 1 :(得分:0)

我认为制作单进程状态机是最好的启动方式。它可以节省一些闩锁形成的潜在问题,并阻止你跳到各处试图查看每个状态下发生的事情(你必须在两个甚至三个不同的地方看看)。但我不确定你需要一个完整的FSM!

您的原始代码看起来并不太糟糕。快速评论一下:

您可以将整数添加到无符号向量,因此您不必执行此操作:

lost_count := lost_count + to_unsigned (1,3);

你可以这样做:

lost_count := lost_count + 1;

我也将lost_counter设为integer,而不是无符号向量,因为您不需要它包裹,也不想要大于2 ** 31的值,也不想要直接访问位。因此整数是一个全面的胜利。

看起来你想要找到6个连续的0位 - 下面的代码是我将如何做的 - 它将进入时钟进程(你的第一次尝试):

if ok = '0' then
    lost_counter := lost_counter + 1;
else
    lost_counter := 0;
end if;
trip <= '0';
if lost_counter = 6 then
    trip <= '1';
    lost_counter := 0;
end if;  

有关时钟的更新......

是的,有一个时钟几乎是强制性的,所以rising_edge是在时钟上完成的,然后你使用那​​个转换来采样你感兴趣的所有信号。还有其他方法可以做到,但它们是仅适用于非常先进的特殊情况。对每个进程使用单个时钟的方法称为“同步设计”,它被广泛使用,以至于所有工具都非常期待你。

为了找到CHECK信号的上升沿,你必须在时钟的上升沿看它(采样它),存储值,然后当你得到它时将它与下一个值进行比较下一个时钟边缘。如果最后一个是零并且当前的一个是一个,你知道它在时钟边缘之间“上升”,你可以在那一点做任何你喜欢的事情。另见我在这个问题上的答案:

https://stackoverflow.com/a/20472791/106092