2013-12-09 33 views
1

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

--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; 

我definetely有什么错在这里,是因为之前和之后做模拟不会产生相同的结果。 Pre-sim似乎可以工作,但是后sim不能。

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

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; 

回答

0

我想说制作一个单进程状态机是最好的开始。它可以节省一些潜在的闩锁形成问题,并且可以阻止你在各个地方跳跃,试图了解每个状态下发生了什么(你必须在两个甚至三个不同的地方查看)。但我不确定你需要一个完整的FSM!

您的原始代码看起来不错。它的快速评论:

您可以添加整数无符号的载体,所以你没有做到这一点:

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

,你可以这样做:

lost_count := lost_count + 1; 

我会也可以使用lost_counterinteger,而不是无符号的向量,因为您不需要它来回绕,也不想要大于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

+0

我看到两个答案都是指CLK信号,这是否意味着我不能在没有CLK的情况下监视信号?我虽然我可以使用CHECK作为参考,并计数确定。马丁,感谢您对我的原始代码的评论,请告诉我为什么它不起作用?缺乏CLK? – sparkyT

+0

非常感谢您的信息,我已经更新了我的代码与您的建议(如果我理解得很好),它的工作原理,但我没有得到的东西。 lost_counter = 6,每输出一个连续的第三个丢失位,lost_counter = 9,每四分之一,依此类推... – sparkyT

+0

刚刚意识到我在Final Edit中强制设计的方式,我正在计算和递增检查信号。上升计数为1,下降沿计数为2。所以要检测6个零位,我需要我的计数为12. – sparkyT

1

这是一个非常标准的状态机,和大多数设计师将一至三个过程使用的状态机。如果你刚刚开始,那么使用三个过程可能会让你更容易。这些过程将是:

  1. 使用计数器的当前状态和输入信号,决定下一个状态应该是什么。
  2. 使用计数器的当前状态和输入信号,决定所有输出信号的值应该是多少。
  3. 在所需的时钟边沿,将计数器的下一个状态(从1.开始)加载到计数器中。

请注意,前两个进程是纯粹的组合逻辑,而第三个进程是一个时钟顺序进程。

+0

快速的响应非常赞赏,虽然乍看之下,我不很明白如何产生你所描述的三个进程,我将深入FSM,并尝试... – sparkyT