我是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;
答案 0 :(得分:1)
这是一个非常标准的状态机,大多数设计人员将使用一到三个进程来处理状态机。如果您刚刚开始,那么使用三个流程可能会让您更轻松。这些过程将是:
请注意,前两个进程纯粹是组合逻辑,而第三个进程是时钟顺序进程。
答案 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信号的上升沿,你必须在时钟的上升沿看它(采样它),存储值,然后当你得到它时将它与下一个值进行比较下一个时钟边缘。如果最后一个是零并且当前的一个是一个,你知道它在时钟边缘之间“上升”,你可以在那一点做任何你喜欢的事情。另见我在这个问题上的答案: