【问题标题】:VHDL Vivado's behavioral simulation returns unknown (red X) over output assignment operationVHDL Vivado 的行为仿真通过输出分配操作返回未知(红色 X)
【发布时间】:2020-11-14 10:44:26
【问题描述】:

我写了这个简单的过程。它应该是累加 ((b-a)/n)*yi 项,其中 yi 是每个时钟周期更新的输入,然后输出求和的结果。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all; 
entity Integrator is
    Port ( a : in STD_LOGIC_VECTOR(7 downto 0);
           b : in STD_LOGIC_VECTOR(7 downto 0);
           n : in STD_LOGIC_VECTOR(7 downto 0);
           yi : in STD_LOGIC_VECTOR (15 downto 0);
           start : in std_logic;
           clk : in std_logic;
           output : out signed (15 downto 0);
           done : out STD_LOGIC);
end Integrator;

architecture Integrator_arch of Integrator is
signal do : std_logic;
signal i : unsigned(7 downto 0);
signal tmp1, tmp2, tmp3, res : signed(15 downto 0);
begin
    process(clk)
    begin
        if(clk'event and clk='1') then
            if(start='1') then
                do <= '1';
                i <= (others=>'0');
                done <= '0';
                res <= (others=>'0');
            elsif(do='1' and done='0') then   
                if(i=unsigned(n)) then
                    output <= res;
                    do <= '0';
                    done <= '1';
                else                    
                    tmp1 <= resize(signed(b)-signed(a),16);
                    tmp2 <= resize(tmp1/signed(n),16);
                    tmp3 <= resize(tmp2*signed(yi),16);
                    res <= res + tmp3;
                    i <= i+1;
                end if;
            end if;  
        end if;         
    end process;
end Integrator_arch;

这是测试台:

architecture Behavioral of Integrator_Testbench is
signal start : std_logic;
signal clk, done : std_logic;
signal yi : std_logic_vector(15 downto 0);
signal O : signed(15 downto 0);
begin
    uut: entity work.integrator(integrator_arch)
            port map(a=>"11111110", b=>"00000010", n=>"00000100", yi=>yi
                ,start=>start, clk=>clk, done=>done, output=>O);
    process
    begin
        clk<='0';
        start<='1';
        wait for 200ns;
        
        clk<='1';
        wait for 200ns;
        
        start<='0';
        clk<='0';
        yi<=x"0003";
        wait for 200ns;
        
        clk<='1';
        yi<=x"0003";
        wait for 200ns;
        
        clk<='0';
        yi<=x"0001";
        wait for 200ns;
        
        clk<='1';
        yi<=x"0001";
        wait for 200ns;
        
        clk<='0';
        yi<=x"0000";
        wait for 200ns;
        
        clk<='1';
        yi<=x"0000";
        wait for 200ns;
        
        clk<='0';
        yi<=x"0002";
        wait for 200ns;
        
        clk<='1';
        yi<=x"0002";
        wait for 200ns;
        
        clk<='0';
        yi<=x"0000";
        wait for 200ns;
        
        clk<='1';
        yi<=x"0000";
        wait for 200ns;
        
        clk<='0';
        yi<=x"0000";
        wait for 200ns;
        
        clk<='1';
        yi<=x"0000";
        wait for 200ns;
    end process;
end Behavioral;

但问题是,当我运行行为模拟时,输出总是报告为未知(红色 X)。更奇怪的是它在调试会话中运行良好,通过逐行调试会话,我能够得到正确的输出,即 x"0006"!!!

经过两个小时的尝试寻找问题,我终于决定问。特别是因为它运行得非常好,并且在逐行调试中输出正确的结果,所以我不知道为什么模拟一直在起作用。

非常感谢您的宝贵时间。

【问题讨论】:

  • 查看集成器进程内部,看看哪里出了问题。这是基本的调试。通常,当您看到 XXXX 时,请检查您没有从两个地方驱动信号,例如测试台和组件本身。但最初的 UUUU 表明情况并非如此。
  • @BrianDrummond 不幸的是,调试器工作得很好,输出显示了正确的解决方案,这只会让我更加困惑为什么模拟失败。至于驱动信号,我只在整个代码中驱动输出信号一次,所以这不是问题。
  • 所以你是说如果你将 tmp1-3 和 res 添加到波形窗口中,它们在产生最终输出的时钟沿之前都是正确的?您可以将它们添加到问题中的 sim 图像中吗?
  • 我会将 temp1-3 和 res 声明为变量而不是信号。
  • @vipin 为什么?然后管道长度将匹配 n 输入。

标签: vhdl simulation vivado


【解决方案1】:

通过更多的尝试和错误找到了我自己的答案

numeric_std 表达式的一行结果似乎需要一个时钟周期才能稳定下来,所以当我试图通过编写使其更具可读性时

tmp1 <= resize(signed(b)-signed(a),16);
tmp2 <= resize(tmp1/signed(n),16);
tmp3 <= resize(tmp2*signed(yi),16);
res <= res + tmp3;

稳定下来需要 4 个时钟周期,在这 4 个时钟周期完成之前,端口设置为未知。 所以我将所有这些行缩短为一行

res <= res + resize((resize(b-a,16)/signed(n))*yi,16);

现在结果在 1 个时钟周期内就为我准备好了。

【讨论】:

    【解决方案2】:

    您的开始信号应该被断言更长的时间。在仿真开始时 tmp1、tmp2、tmp3 未初始化,需要 3 个时钟周期才能获得正确计算的 tmp3 值(因为您在时钟过程中使用

    解决方案:

    • 在开始时,再断言启动 3 个周期,
    • 或在声明期间初始化tmp1、tmp2、tmp3
    • 或在 start = 1 时将它们与 res 一起初始化

    您可以更改 tmp1、tmp2、tmp3 变量的代码。时钟过程中的信号表现得像一个管道。只是它是行为代码还是可综合代码,是否满足时序约束的问题。 VHDL是一种描述语言;从功能的角度来看,没有一个好的答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      相关资源
      最近更新 更多