VHDL中信号的输出值冲突
Output value conflict of signals in VHDL
我写了一个简单的 vhdl 代码到 enable/disable 在某些条件下通过一些控制信号输出端口。问题是输出信号是 U 或 X,而代码看起来不错。
主要实体如下图。第一个进程对 rst
敏感,当它为 1 时将禁用 oe
。第二个进程对 clk
敏感,并将在时钟转换时启用 oe
。输出值也设置为5
.
entity test2 is
port( clk: in std_logic;
rst: in std_logic;
num: out integer range 0 to 7;
oe: out std_logic );
end;
architecture behav of test2 is
begin
process( rst )
begin
if rst = '1' then
oe <= '0';
end if;
end process;
process( clk )
begin
if (clk'event and clk = '1') then
num <= 5;
oe <= '1';
end if;
end process;
end;
现在考虑测试台文件。可以看出,在主进程中,我将连接到rst
的r
设置为1,然后设置为0。
entity test2_tb is
end;
architecture behav of test2_tb is
component test2 port( clk: in std_logic;
rst: in std_logic;
num: out integer range 0 to 7;
oe: out std_logic );
end component;
signal c: std_logic := '0';
signal r: std_logic;
signal n: integer range 0 to 7 := 2;
signal o: std_logic;
begin
u1: test2 port map( c, r, n, o );
process( c )
begin
c <= not c after 2ns;
end process;
process
begin
r <= '1';
wait for 4 ns;
r <= '0';
wait for 8 ns;
end process;
end;
虽然r
为1,但与oe
相连的o
设置为U。为什么?此外,在时钟的上升沿,o
的值变为 X。为什么?请看下面的波浪
即使在您将任务分配给 oe 之后,这些流程仍将继续驱动它们的价值(因为您从未告诉它们做任何其他事情)。一开0一开1给出X。用if-elsif语句将两个进程合二为一。只有一个 driver 没有冲突。最初他们都在驾驶 U.
简而言之:您的 oe
端口可能不是 std_logic
类型,而是 std_ulogic
类型(clk
和 rst
相同)和它可能应该由一个进程而不是两个进程驱动:
process(clk)
begin
if clk'event and clk = '1' then
if rst = '1' then
oe <= '0';
else
num <= 5;
oe <= '1';
end if;
end if;
end process;
或者,如果您更喜欢异步重置:
process(clk, rst)
begin
if rst = '1' then
oe <= '0';
elsif clk'event and clk = '1' then
num <= 5;
oe <= '1';
end if;
end process;
如果您的工具不能正确支持 std_ulogic
(不幸的是,有些逻辑合成器不支持 std_ulogic
,至少在顶层是这样),请使用 std_logic
但非常小心地始终在一个进程中驱动你的输出端口(和内部信号),除非在非常特殊的情况下你真的想要几个硬件同时驱动同一条硬件线,这是非常罕见的(三态逻辑,高阻抗...)
我写了一个简单的 vhdl 代码到 enable/disable 在某些条件下通过一些控制信号输出端口。问题是输出信号是 U 或 X,而代码看起来不错。
主要实体如下图。第一个进程对 rst
敏感,当它为 1 时将禁用 oe
。第二个进程对 clk
敏感,并将在时钟转换时启用 oe
。输出值也设置为5
.
entity test2 is
port( clk: in std_logic;
rst: in std_logic;
num: out integer range 0 to 7;
oe: out std_logic );
end;
architecture behav of test2 is
begin
process( rst )
begin
if rst = '1' then
oe <= '0';
end if;
end process;
process( clk )
begin
if (clk'event and clk = '1') then
num <= 5;
oe <= '1';
end if;
end process;
end;
现在考虑测试台文件。可以看出,在主进程中,我将连接到rst
的r
设置为1,然后设置为0。
entity test2_tb is
end;
architecture behav of test2_tb is
component test2 port( clk: in std_logic;
rst: in std_logic;
num: out integer range 0 to 7;
oe: out std_logic );
end component;
signal c: std_logic := '0';
signal r: std_logic;
signal n: integer range 0 to 7 := 2;
signal o: std_logic;
begin
u1: test2 port map( c, r, n, o );
process( c )
begin
c <= not c after 2ns;
end process;
process
begin
r <= '1';
wait for 4 ns;
r <= '0';
wait for 8 ns;
end process;
end;
虽然r
为1,但与oe
相连的o
设置为U。为什么?此外,在时钟的上升沿,o
的值变为 X。为什么?请看下面的波浪
即使在您将任务分配给 oe 之后,这些流程仍将继续驱动它们的价值(因为您从未告诉它们做任何其他事情)。一开0一开1给出X。用if-elsif语句将两个进程合二为一。只有一个 driver 没有冲突。最初他们都在驾驶 U.
简而言之:您的 oe
端口可能不是 std_logic
类型,而是 std_ulogic
类型(clk
和 rst
相同)和它可能应该由一个进程而不是两个进程驱动:
process(clk)
begin
if clk'event and clk = '1' then
if rst = '1' then
oe <= '0';
else
num <= 5;
oe <= '1';
end if;
end if;
end process;
或者,如果您更喜欢异步重置:
process(clk, rst)
begin
if rst = '1' then
oe <= '0';
elsif clk'event and clk = '1' then
num <= 5;
oe <= '1';
end if;
end process;
如果您的工具不能正确支持 std_ulogic
(不幸的是,有些逻辑合成器不支持 std_ulogic
,至少在顶层是这样),请使用 std_logic
但非常小心地始终在一个进程中驱动你的输出端口(和内部信号),除非在非常特殊的情况下你真的想要几个硬件同时驱动同一条硬件线,这是非常罕见的(三态逻辑,高阻抗...)