检测 std_logic vhdl 中的变化

Detect changes in std_logic vhdl

我正在尝试检测我的选择器输入信号的变化。当我找到第一个发生变化的输入(上升沿或下降沿)时,我给出一个索引作为输出。当我尝试综合我的源代码时,出现错误 "unsupported Clock statement"。 A也尝试使用"rising_edge"和"falling_edge",但我得到了同样的错误。 这是我的代码

library ieee;
use ieee.std_logic_1164.all;

entity Selector is
port (
X1:  in std_logic;
X2:  in std_logic;
X3:  in std_logic;
X4:  in std_logic;
X5:  in std_logic;
X6:  in std_logic;
O:       out std_logic_vector(2 downto 0)
);
end Selector;


architecture behave of Selector is
begin
process(X1,X2,X3,X4,X5,X6)
begin
    if (X1'event) then
            O <= "000";
    elsif (X2'event) then
            O <= "001";
    elsif (X3'event) then
            O <= "010";
    elsif (X4'event) then
            O <= "011";
    elsif (X5'event) then
            O <= "100";
    elsif (X6'event) then
            O <= "101";
    else
            O <= "000";
    end if;
end process;
end behave;

是否有替代解决方案?

您需要额外的时钟输入来比较当前时钟周期中的 X1X2、... 的值与上一个时钟周期中的值。如果 Xes 与时钟异步,您必须先将它们同步。

输入同步

要使输入与时钟同步,您必须使用两个 D flip-flops 串行对每个输入进行采样。第一个 flip-flop 的输出可能会受到亚稳态问题的损害,这些问题在这些论文中有更详细的描述:

两者之间的连接 flip-flops(对于每个输入)必须加以约束,以便它们之间的路由路径尽可能短。下面的实现将只显示两个 flip-flops。可以在我是作者之一的 sync_Bits component of the PoC Library 中找到更高级的实现。

比较

一旦输入与时钟同步,只需延迟另一个时钟周期。这将构成最后一个值,因此您可以将当前值与最后一个值进行比较以检测信号变化。输入时钟的频率必须比 X 输入之一的变化频率快得多:

  • 获得edge-detection的快速回复,
  • 捕捉所有信号变化。

这是一个可能的实现:

library ieee;
use ieee.std_logic_1164.all;

entity Selector is
    port (
        clk : in std_logic;
        X1:  in std_logic;
        X2:  in std_logic;
        X3:  in std_logic;
        X4:  in std_logic;
        X5:  in std_logic;
        X6:  in std_logic;
        O:   out std_logic_vector(2 downto 0)
    );
end Selector;

architecture behave of Selector is
    signal X : std_logic_vector(6 downto 1); -- all inputs in one vector
    signal X_meta : std_logic_vector(6 downto 1); -- first  sampling stage
    signal X_curr : std_logic_vector(6 downto 1); -- second sampling stage =
                                                  -- current value
    signal X_last : std_logic_vector(6 downto 1); -- last value of X_curr
begin
    -- Concatenate all inputs to one vector for shorter code below.
    X <= X6 & X5 & X4 & X3 & X2 & X1;

    -- Synchronize external inputs to clock. If the X* inputs are already
    -- synchronous to 'clk' then replace this process with:
    -- X_curr <= X;
    sync: process(clk)
    begin
        if rising_edge(clk) then
            -- The path betweeen these two flip-flops must be constrained for a
            -- short delay, so that, the wire in between is as ahort as
            -- possible. 
            X_meta <= X;
            X_curr <= X_meta;
        end if;
    end process;

    -- This statement delays the current value X_curr by one clock cycle.
    X_last <= X_curr when rising_edge(clk);

    -- Comparison and selector output.
    process(X_curr, X_last)
    begin
        if    (X_curr(1) xor X_last(1)) = '1' then
            O <= "000";
        elsif (X_curr(2) xor X_last(2)) = '1' then
            O <= "001";
        elsif (X_curr(3) xor X_last(3)) = '1' then
            O <= "010";
        elsif (X_curr(4) xor X_last(4)) = '1' then
            O <= "011";
        elsif (X_curr(5) xor X_last(5)) = '1' then
            O <= "100";
        elsif (X_curr(6) xor X_last(6)) = '1' then
            O <= "101";
        else
            O <= "000";
        end if;
    end process;
end behave;