ghdl 永远不会终止,我不知道为什么

问题描述 投票:0回答:2

2022年应该是我计划深入研究fpga编程的一年。 25 年来我确实没有做过任何类似的事情(当时我做了一些 GAL 逻辑)。 因此,无论出于何种意图和目的,就 HDL 内容而言,您可以将这篇文章视为新手的帖子。

我想做的事情其实很简单 - 一个带有进位和借位的简单加法器以及相应的测试台。

-- add1.vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity add1 is
port ( 
  borrow : in std_ulogic;
  a : in std_ulogic;
  b : in std_ulogic;
  o : out std_ulogic;
  carry : out std_ulogic;
  err : out std_ulogic);
end add1;

architecture add1arch of add1 is
begin
  process
    variable inputs : std_ulogic_vector(2 downto 0);
  begin
    inputs := borrow & a & b;
    err <= '0';
    case inputs is
      when "000" => 
        o <= '0';
        carry <= '0';
      when "100" =>
        o <= '1';
        carry <= '0';
      when "010" =>
        o <= '1';
        carry <= '0';
      when "001" =>
        o <= '1';
        carry <= '0';
      when "011" =>
        o <= '0';
        carry <= '1';
      when "110" =>
        o <= '0';
        carry <= '0';
      when "101" =>
        o <= '0';
        carry <= '0';
      when "111" =>
        o <= '1';
        carry <= '1';
      when others =>
        o <= '0';
        carry <= '0';
        err <= '1';
    end case;
  end process;
end architecture;

测试台是这样的:

-- add1_tb.vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity add1_tb is
end add1_tb;    

architecture test of add1_tb is
  component add1
    port ( 
      borrow : in std_ulogic;
      a : in std_ulogic;
      b : in std_ulogic;
      o : out std_ulogic;
      carry : out std_ulogic;
      err : out std_ulogic);
  end component;

  signal borrow, a, b, o, carry, err : std_ulogic;
  signal inputs : std_ulogic_vector(2 downto 0);
begin
  adder: add1 port map
    (borrow => borrow,
     a => a,
     b => b,
     o => o,
     carry => carry,
     err => err);
  process
  begin
    inputs <= borrow & a & b;

    inputs <= "XXX";
    wait for 1 ns;
    
    inputs <= "000";
    wait for 1 ns;

    inputs <= "001";
    wait for 1 ns;

    inputs <= "010";
    wait for 1 ns;

    inputs <= "011";
    wait for 1 ns;
    
    inputs <= "100";
    wait for 1 ns;

    inputs <= "101";
    wait for 1 ns;

    inputs <= "110";
    wait for 1 ns;

    inputs <= "111";
    wait for 1 ns;

    assert false report "done.";
    wait;
    
  end process;
end architecture;

使用

ghdl --版本
GHDL 1.0.0 (Debian 1.0.0+dfsg-3) [Dunoon 版]
使用 GNAT 版本编译:10.2.1 20210110
mcode 代码生成器
由特里斯坦·金戈尔德撰写。
版权所有 (C) 2003 - 2021 特里斯坦·金戈尔德。
GHDL 是免费软件,受 GNU 通用公共许可证保护。 没有
保修单;甚至不是为了适销性或特定用途的适用性。

在 Debian bullseye 64 位机器上。
构建:

ghdl——干净
ghdl -a add1.vhdl
ghdl -a add1_tb.vhdl
ghdl -e add1_tb
ghdl -r add1_tb --vcd=add1.vcd

最后一个命令永远不会终止,当我在一段时间后使用 control-c 时,

add1.vcd
文件为空。

现在的问题将帮助我确定我的 vhdl 代码中是否存在工具链问题或错误:

有人发现我的代码有什么问题吗? (我知道它很笨拙,但由于我没有收到错误或警告,我认为它在语法上是正确的。)

vhdl ghdl
2个回答
0
投票

事实证明,关于“敏感度列表”的建议(我必须先查找,这意味着什么......)可以轻松解决我的问题

显然,设计运行时“模拟”流程的方式取决于一些“触发器”来使“状态机”继续进行。这可以是等待,或者 - 正如我现在了解到的 - 更改“敏感度列表”中包含的信号(这是编程术语中进程的一种参数列表)。

所以,为了解决我的小问题,我所要做的就是......

-- add1.vhdl
-- ...
architecture add1arch of add1 is
begin
  process (borrow, a, b) -- list signals in sensitivity list to avoid hangs!

至于测试台中的另一个问题,我试图为我的输入信号找到更好的表示法(

"001" instead of "borrow <= 0; a <= 0; b <= 1;"
),我必须做出以下更改:

-- add1_tb.vhdl
-- ...
  signal inputs : std_ulogic_vector(2 downto 0);
  signal o, carry, err : std_ulogic;
  alias borrow : std_ulogic is inputs(0);
  alias a : std_ulogic is inputs(1);
  alias b : std_ulogic is inputs(2);
-- ...

现在它的行为符合预期,我可以看到 gtkwave 输出。 唯一的缺点是,gtkwave 不提供显示别名值,所以我现在只能使用输入向量。


0
投票

是的,敏感度列表是你的问题。虽然实际电路并不真正需要它们,但模拟器需要它们知道何时需要重新评估过程。

如果您没有敏感度列表,则不会评估任何内容,模拟器将永远等待永远不会发生的事件。

这很奇怪、令人困惑且容易出错。我了解敏感度列表,但前几天我花了 6 个小时,因为我忘记将一个敏感度列表放入敏感度列表中,而且当模拟中事情根本没有发生时,我感到很困惑。

但实际上,这可能是使模拟易于处理的唯一方法。通过灵敏度列表,您可以限制模拟器需要查看以进行评估的信号数量,从而获得更合理的模拟性能。

也许知道敏感度列表的用途可能有助于记住?

© www.soinside.com 2019 - 2024. All rights reserved.