检测 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;
是否有替代解决方案?
您需要额外的时钟输入来比较当前时钟周期中的 X1
、X2
、... 的值与上一个时钟周期中的值。如果 X
es 与时钟异步,您必须先将它们同步。
输入同步
要使输入与时钟同步,您必须使用两个 D flip-flops 串行对每个输入进行采样。第一个 flip-flop 的输出可能会受到亚稳态问题的损害,这些问题在这些论文中有更详细的描述:
- 运行 吉诺萨尔:Metastability and Synchronizers: A Tutorial
- Sunburst 设计:用于设计多通道的综合和脚本技术
异步时钟设计
两者之间的连接 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;
我正在尝试检测我的选择器输入信号的变化。当我找到第一个发生变化的输入(上升沿或下降沿)时,我给出一个索引作为输出。当我尝试综合我的源代码时,出现错误 "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;
是否有替代解决方案?
您需要额外的时钟输入来比较当前时钟周期中的 X1
、X2
、... 的值与上一个时钟周期中的值。如果 X
es 与时钟异步,您必须先将它们同步。
输入同步
要使输入与时钟同步,您必须使用两个 D flip-flops 串行对每个输入进行采样。第一个 flip-flop 的输出可能会受到亚稳态问题的损害,这些问题在这些论文中有更详细的描述:
- 运行 吉诺萨尔:Metastability and Synchronizers: A Tutorial
- Sunburst 设计:用于设计多通道的综合和脚本技术 异步时钟设计
两者之间的连接 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;