VHDL 忽略进程外的语句
VHDL ignores statement outside a process
我希望这是在正确的地方,但因为我认为这是语法问题而不是实际系统设计问题,所以可能是。
出于某种原因,当我将它留在进程之外时,我有一个语句被忽略了。我可以 copy/paste 将相同的语句放入一个进程中,然后它突然起作用了。但随后它必须等待时钟信号,这就把整个事情搞砸了。
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
OPCODES(3) <= OPCODE_IN; --problem statement!
process(CLK)
begin
if rising_edge(CLK) then
for I in 0 to 2 loop
OPCODES(I) <= OPCODES(I + 1);
end loop;
end if;
end process;
--more code
end CU;
如果我这样模拟,我会得到这种我不明白的情况:
注意 OPCODE_IN 是 D 但 OPCODES(3) 仍然是 U。
如果我在进程中移动语句,它会将 OPCODE_IN 的值转移到 OPCODES(3) 中,但当然它需要另一个时钟周期,这会打乱所有的时间:
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
process(CLK)
begin
if rising_edge(CLK) then
for I in 0 to 2 loop
OPCODES(I) <= OPCODES(I + 1);
end loop;
OPCODES(3) <= OPCODE_IN; --problem statement!
end if;
end process;
--more code
end CU;
有人知道为什么会这样吗?
在评论中总结答案:
第一个示例中的过程将为来自最长静态前缀 OPCODES(I) 的所有信号创建驱动程序,即 OPCODES。所以 OPCODES(0) 也会有驱动程序。但是在您的过程中没有为 OPCODES(0) 赋值,因此它是 'U'.
当你把OPCODES(3) <= OPCODE_IN;
放在进程中时,你进行赋值,问题就解决了。
展开循环时,分配的最长静态前缀变为 OPCODES(1)
、OPCODES(2)
和 OPCODES(3)
,而不是 OPCODES
。所以你没有OPCODES(0)
的驱动了,问题又解决了。
这是 VHDL 变得非常 counter-intuitive 的怪癖之一。它特别令人困惑,因为其他并行处理语言没有它。
另一个解决方案是使用 generate-statement.
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
OPCODES(3) <= OPCODE_IN; --problem statement!
some_label: for I in 0 to 2 generate
OPCODES(I) <= OPCODES(I + 1) when rising_edge(clk);
end generate;
--more code
end architecture;
有趣的是,在这种情况下 OPCODES(I)
突然又是一个静态表达式。非常一致,嗯? ;)
您可以直接表示移位,同时消除for...loop
和最长静态前缀问题。
process(CLK)
begin
if rising_edge(CLK) then
OPCODES <= OPCODE_IN & OPCODES(3 downto 1);
end if;
end process;
或者,如果您喜欢循环...
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
process(CLK, OPCODE_IN)
begin
OPCODES(3) <= OPCODE_IN;
if rising_edge(CLK) then
for I in 0 to 2 loop
OPCODES(I) <= OPCODES(I + 1);
end loop;
end if;
end process;
--more code
end CU;
...虽然我觉得不是很满意。对 OPCODES(3)
的赋值不必在进程的时钟部分内。
它有一个丑陋之处,因为它需要敏感列表中的额外信号,并且没有提供任何明显的理由将其作为静态前缀问题的解决方案。
我希望这是在正确的地方,但因为我认为这是语法问题而不是实际系统设计问题,所以可能是。
出于某种原因,当我将它留在进程之外时,我有一个语句被忽略了。我可以 copy/paste 将相同的语句放入一个进程中,然后它突然起作用了。但随后它必须等待时钟信号,这就把整个事情搞砸了。
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
OPCODES(3) <= OPCODE_IN; --problem statement!
process(CLK)
begin
if rising_edge(CLK) then
for I in 0 to 2 loop
OPCODES(I) <= OPCODES(I + 1);
end loop;
end if;
end process;
--more code
end CU;
如果我这样模拟,我会得到这种我不明白的情况:
注意 OPCODE_IN 是 D 但 OPCODES(3) 仍然是 U。
如果我在进程中移动语句,它会将 OPCODE_IN 的值转移到 OPCODES(3) 中,但当然它需要另一个时钟周期,这会打乱所有的时间:
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
process(CLK)
begin
if rising_edge(CLK) then
for I in 0 to 2 loop
OPCODES(I) <= OPCODES(I + 1);
end loop;
OPCODES(3) <= OPCODE_IN; --problem statement!
end if;
end process;
--more code
end CU;
有人知道为什么会这样吗?
在评论中总结答案:
第一个示例中的过程将为来自最长静态前缀 OPCODES(I) 的所有信号创建驱动程序,即 OPCODES。所以 OPCODES(0) 也会有驱动程序。但是在您的过程中没有为 OPCODES(0) 赋值,因此它是 'U'.
当你把OPCODES(3) <= OPCODE_IN;
放在进程中时,你进行赋值,问题就解决了。
展开循环时,分配的最长静态前缀变为 OPCODES(1)
、OPCODES(2)
和 OPCODES(3)
,而不是 OPCODES
。所以你没有OPCODES(0)
的驱动了,问题又解决了。
这是 VHDL 变得非常 counter-intuitive 的怪癖之一。它特别令人困惑,因为其他并行处理语言没有它。
另一个解决方案是使用 generate-statement.
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
OPCODES(3) <= OPCODE_IN; --problem statement!
some_label: for I in 0 to 2 generate
OPCODES(I) <= OPCODES(I + 1) when rising_edge(clk);
end generate;
--more code
end architecture;
有趣的是,在这种情况下 OPCODES(I)
突然又是一个静态表达式。非常一致,嗯? ;)
您可以直接表示移位,同时消除for...loop
和最长静态前缀问题。
process(CLK)
begin
if rising_edge(CLK) then
OPCODES <= OPCODE_IN & OPCODES(3 downto 1);
end if;
end process;
或者,如果您喜欢循环...
architecture CU of CONTROL_UNIT is
type OPCODE_ARRAY is array(3 downto 0) of std_logic_vector(3 downto 0);
signal OPCODES : OPCODE_ARRAY;
begin
process(CLK, OPCODE_IN)
begin
OPCODES(3) <= OPCODE_IN;
if rising_edge(CLK) then
for I in 0 to 2 loop
OPCODES(I) <= OPCODES(I + 1);
end loop;
end if;
end process;
--more code
end CU;
...虽然我觉得不是很满意。对 OPCODES(3)
的赋值不必在进程的时钟部分内。
它有一个丑陋之处,因为它需要敏感列表中的额外信号,并且没有提供任何明显的理由将其作为静态前缀问题的解决方案。