使用非静态信号名

时间:2015-06-25 08:25:43

标签: vhdl modelsim

在某些测试平台代码中,我使用一个过程来处理信号。然后,我在不同的信号上按顺序多次使用此过程。只要我明确定义信号,这就可以正常工作;一旦我在循环中索引信号,它就会失败

  

(vcom-1450)正式“s”的实际(索引名称)不是静态信号名称。

为什么这不可能,我该如何解决? 可能我可以将其移动到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。

2 个答案:

答案 0 :(得分:2)

有趣的是,如果foo是流程的本地变量,(并且s被调整为适合),ghdl会编译它。这突出了原始版本中的问题。 &#34; for&#34;需要循环来驱动整个foo,因为你不能让信号驱动器随意出现或消失 - 它对于它所驱动的位是不矛盾的, (正如您所看到的,该过程会尝试在不同时间驱动不同的位)。

因此,如果你可以重新调整你的应用程序以允许变量更新语义,并使foo变量本地变量,那将是有效的。 (你必须在每个&#34之前将其值复制到一个信号;等待&#34;如果你想看到效果!)

或者,将整个foo信号和索引传递给子程序,以便后者始终按以下方式驱动所有foo ... (我还添加了缺失的位并修复了虚假并发&#34;等待&#34;:将来,请检查您的代码示例在发布前实际编译!)

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;

答案 1 :(得分:1)

我与你分享你对这种语言的愚蠢限制的感受。减去waitreport语句,您的示例肯定具有有效的硬件实现,更不用说明确定义的模拟行为。

我认为在大多数情况下可以避免这种情况。例如,在您的简单示例中,您可以将过程的内容复制到过程体中,或者像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;

这仅适用于模拟,并且每次迭代将导致一个增量循环延迟,相比之下,当过程不包含等待语句时,展开在零时间内完成的循环。