具有非静态信号名称的循环过程调用
Procedure call in loop with non-static signal name
在一些测试平台代码中,我使用一个过程来处理信号。然后我在不同的信号上按顺序多次使用这个过程。只要我明确定义信号,这就可以正常工作;一旦我在循环中索引信号,它就会失败
(vcom-1450) Actual (indexed name) for formal "s" is not a static signal name.
为什么这不可能,我该如何解决?
也许我可以将其移动到 for ... generate
,但我希望 do_something
以定义明确的顺序被调用。
library ieee;
use ieee.std_logic_1164.all;
entity test is
end test;
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
begin
dummy: process is
procedure do_something (
signal s : out std_logic
) is begin
s <= '1';
report "tic";
wait for 1 ns;
-- actually we would do something more interesting here
s <= '0';
report "toc";
end procedure;
begin
-- This works well, but requires manual loop-unrolling
do_something(foo(0));
do_something(foo(1));
-- This should do the same
for i in foo'range loop
-- This is the offending line:
do_something(foo(i));
end loop;
wait; -- for ever
end process dummy;
end architecture tb;
我正在使用 ModelSim 10.4 PE。
有趣的是,如果 foo
是进程的本地变量,(并且 s
被调整以适应)ghdl 编译它。这突出了原始版本中的问题。 "for" 循环需要一直驱动整个 foo
,因为你不能让信号驱动器随意出现或消失——它不能对它驱动的位有矛盾,(并且如您所见,该过程尝试在不同时间驱动不同的位)。
因此,如果您可以重新调整您的应用程序以允许变量更新语义,并使 foo
成为进程的本地变量,那将行得通。 (如果你想看到效果,你必须在每个 "wait" 之前将它的值复制到一个信号中!)
或者,将整个 foo
信号和索引传递给子程序,以便后者始终驱动所有 foo
如下...
(我还添加了缺失的位并修复了虚假的并发 "wait" :以后,请在发布之前检查您的代码示例是否实际编译!)
library ieee;
use ieee.std_logic_1164.all;
entity test is
end test;
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
begin
dummy: process is
procedure do_something (
signal s : out std_logic_vector(1 downto 0);
constant i : in natural
) is begin
s <= (others => '0');
s(i) <= '1';
report "tic";
wait for 1 ns;
-- actually we would do something more interesting here
s(i) <= '0';
report "toc";
end procedure;
begin
-- This works well, but requires manual loop-unrolling
do_something(foo,0);
do_something(foo,1);
-- This should do the same
for i in foo'range loop
-- This is the offending line:
do_something(foo,i);
end loop;
wait; -- for ever
end process dummy;
end architecture tb;
我和你一样认为这是一种愚蠢的语言限制。减去 wait
和 report
语句,您的示例肯定具有有效的硬件实现,更不用说定义明确的模拟行为了。
我觉得这种情况在大多数情况下是可以避免的。例如,在您的简单示例中,您可以将过程的内容复制到过程主体中,或者按照 Brian 的建议传递整个向量。如果您确实需要这样做,这是一种解决方法:
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
signal t : std_logic;
signal p : integer := 0;
begin
foo(p) <= t;
dummy: process is
procedure do_something (
signal s : out std_logic
) is begin
s <= '1';
wait for 1 ns;
s <= '0';
end procedure;
begin
for i in foo'range loop
p <= idx;
do_something(t);
wait for 0 ns;
end loop;
wait;
end process dummy;
end architecture tb;
这仅适用于模拟,与在过程不包含等待语句时在零时间内完成的展开循环相比,每次迭代将导致一个增量循环延迟。
在一些测试平台代码中,我使用一个过程来处理信号。然后我在不同的信号上按顺序多次使用这个过程。只要我明确定义信号,这就可以正常工作;一旦我在循环中索引信号,它就会失败
(vcom-1450) Actual (indexed name) for formal "s" is not a static signal name.
为什么这不可能,我该如何解决?
也许我可以将其移动到 for ... generate
,但我希望 do_something
以定义明确的顺序被调用。
library ieee;
use ieee.std_logic_1164.all;
entity test is
end test;
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
begin
dummy: process is
procedure do_something (
signal s : out std_logic
) is begin
s <= '1';
report "tic";
wait for 1 ns;
-- actually we would do something more interesting here
s <= '0';
report "toc";
end procedure;
begin
-- This works well, but requires manual loop-unrolling
do_something(foo(0));
do_something(foo(1));
-- This should do the same
for i in foo'range loop
-- This is the offending line:
do_something(foo(i));
end loop;
wait; -- for ever
end process dummy;
end architecture tb;
我正在使用 ModelSim 10.4 PE。
有趣的是,如果 foo
是进程的本地变量,(并且 s
被调整以适应)ghdl 编译它。这突出了原始版本中的问题。 "for" 循环需要一直驱动整个 foo
,因为你不能让信号驱动器随意出现或消失——它不能对它驱动的位有矛盾,(并且如您所见,该过程尝试在不同时间驱动不同的位)。
因此,如果您可以重新调整您的应用程序以允许变量更新语义,并使 foo
成为进程的本地变量,那将行得通。 (如果你想看到效果,你必须在每个 "wait" 之前将它的值复制到一个信号中!)
或者,将整个 foo
信号和索引传递给子程序,以便后者始终驱动所有 foo
如下...
(我还添加了缺失的位并修复了虚假的并发 "wait" :以后,请在发布之前检查您的代码示例是否实际编译!)
library ieee;
use ieee.std_logic_1164.all;
entity test is
end test;
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
begin
dummy: process is
procedure do_something (
signal s : out std_logic_vector(1 downto 0);
constant i : in natural
) is begin
s <= (others => '0');
s(i) <= '1';
report "tic";
wait for 1 ns;
-- actually we would do something more interesting here
s(i) <= '0';
report "toc";
end procedure;
begin
-- This works well, but requires manual loop-unrolling
do_something(foo,0);
do_something(foo,1);
-- This should do the same
for i in foo'range loop
-- This is the offending line:
do_something(foo,i);
end loop;
wait; -- for ever
end process dummy;
end architecture tb;
我和你一样认为这是一种愚蠢的语言限制。减去 wait
和 report
语句,您的示例肯定具有有效的硬件实现,更不用说定义明确的模拟行为了。
我觉得这种情况在大多数情况下是可以避免的。例如,在您的简单示例中,您可以将过程的内容复制到过程主体中,或者按照 Brian 的建议传递整个向量。如果您确实需要这样做,这是一种解决方法:
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
signal t : std_logic;
signal p : integer := 0;
begin
foo(p) <= t;
dummy: process is
procedure do_something (
signal s : out std_logic
) is begin
s <= '1';
wait for 1 ns;
s <= '0';
end procedure;
begin
for i in foo'range loop
p <= idx;
do_something(t);
wait for 0 ns;
end loop;
wait;
end process dummy;
end architecture tb;
这仅适用于模拟,与在过程不包含等待语句时在零时间内完成的展开循环相比,每次迭代将导致一个增量循环延迟。