Testbench 在 Modelsim 中返回未定义的值

Testbench is returning undefinded values in Modelsim

我正在用 VHDL 编写模式生成器。 我最近完成了它,但现在我在测试台上遇到了问题。

我的代码:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;

entity pattern_gen is
    Port ( 
    clk_i : in STD_LOGIC;-- 100Mhz clock on Basys 3 FPGA board

    x : in INTEGER;
    y: in INTEGER;
    modus : in STD_LOGIC;
    enable : in STD_LOGIC;

    red : out STD_LOGIC_VECTOR(3 downto 0);
    green : out STD_LOGIC_VECTOR(3 downto 0);
    blue : out STD_LOGIC_VECTOR(3 downto 0)
    );
end pattern_gen;

architecture Behavioral of pattern_gen is
    signal segment_x : integer := 0;
    signal segment_y : integer := 0;

begin
    stripes : PROCESS(modus, segment_x, x, clk_i)
    BEGIN
        IF( clk_i'EVENT and clk_i = '1') then
            IF(modus = '0' AND enable = '1' ) THEN        --Mod 0 -> Stripes enabled
                    IF(x < (40+ (160*(segment_x-1)))) THEN
                        red <= (OTHERS => '1');
                        green  <= (OTHERS => '0');
                        blue <= (OTHERS => '0');
                    ELSE IF(x < (80+ (160*(segment_x-1)))) THEN
                        red <= (OTHERS => '0');
                        green  <= (OTHERS => '1');
                        blue <= (OTHERS => '0');
                        ELSE IF(x < (120+ (160*(segment_x-1)))) THEN
                            red <= (OTHERS => '0');
                            green  <= (OTHERS => '0');
                            blue <= (OTHERS => '1');
                            ELSE IF(x < (160+ (160*(segment_x-1)))) THEN
                                red <= (OTHERS => '0');
                                green  <= (OTHERS => '0');
                                blue <= (OTHERS => '0');
                            END IF;
                        END IF;
                    END IF;
                END IF;
            END IF;
        end if;
    END PROCESS;

    panels: PROCESS(modus, segment_x, segment_y, clk_i)
    variable i: integer range -10 to 100;
    BEGIN
        IF(clk_i'EVENT and clk_i = '1') then 
            IF(modus = '1' AND enable = '1' ) THEN        --Mod 1 -> Panels enabled
                    i := segment_x*segment_y;

                    while (i>0) loop
                        IF (i = 1) then
                            red <= (OTHERS => '1');
                            green  <= (OTHERS => '0');
                            blue <= (OTHERS => '0');
                        else if(i = 2) then
                            red <= (OTHERS => '0');
                            green  <= (OTHERS => '1');
                            blue <= (OTHERS => '0');
                            else if(i=3) then
                                red <= (OTHERS => '0');
                                green  <= (OTHERS => '0');
                                blue <= (OTHERS => '1');
                                end if;
                            end if;
                        end if;

                        i := i - 3;

                    end loop;
            END IF;
        END IF;
    END PROCESS;

    segment: PROCESS(x, y, modus, clk_i)
    variable i: integer range 0 to 10;
    BEGIN
        if(clk_i'EVENT and clk_i = '1') then
            IF(modus = '0' AND enable = '1') THEN
                i := 1;
                while i<=4 loop
                    IF(x < (i * 160))then
                        segment_x <= i;
                        exit;
                    END IF;
                    i := i +1;
                END loop;
            ELSIF (modus = '1' AND enable = '1') THEN --Mod 1 -> Panels enabled
                i:=1; --reset i for horizintal segment 
                while i<=10 loop
                    IF(x < (i * 64))then
                        segment_x <= i;
                        exit;
                    END IF;
                    i := i +1;
                end loop;
                i:=1; --reset i for vertical segment
                while i<=10 loop
                    IF(y < (i * 48)) then
                        segment_y <= i;
                        exit;
                    end if;
                    i := i +1;
                end loop;   
            END IF;
        end if; 
     END PROCESS;
end Behavioral;

测试平台很短,我只想测试几个案例。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
entity pattern_gen_tb is

end entity;

architecture sim of pattern_gen_tb is
component pattern_gen
   Port ( 
    clk_i : in STD_LOGIC;

    x : in INTEGER;
    y: in INTEGER;
    modus : in STD_LOGIC;
    enable : in STD_LOGIC;

    red : out STD_LOGIC_VECTOR(3 downto 0);
    green : out STD_LOGIC_VECTOR(3 downto 0);
    blue : out STD_LOGIC_VECTOR(3 downto 0)
    );
end component;

signal clk_s : STD_LOGIC := '0';

signal x_s : INTEGER;
signal y_s : INTEGER;
signal modus_s : std_logic;
signal enable_s : std_logic;

signal red_s : STD_LOGIC_VECTOR(3 downto 0);
signal green_s :STD_LOGIC_VECTOR(3 downto 0);
signal blue_s : STD_LOGIC_VECTOR(3 downto 0);

begin
    uut : pattern_gen
    port map(
        clk_i => clk_s,

        x => x_s,
        y => y_s,
        modus => modus_s,
        enable => enable_s,

        red => red_s,
        green => green_s,
        blue => blue_s
        );
    clk_s  <= not clk_s after 10 ns;

 p_test : process
 begin
    x_s <= 44; 
    y_s<= 300;
    modus_s <= '0';
    enable_s <= '1'; -- result should be green(1,1,1,1)

    wait; 

end process;

end sim;

即使段计算正确,模拟结果仍未定义,并且应该触发第二个 If 语句,因为 44 < (80 + 160 * (1-1)) 因此输出应该是

段 1 和条纹 2 -> 绿色 (1,1,1,1) 红色和蓝色 (0,0,0,0)

我错过了什么?我已经尝试让它工作几个小时了。

您从多个进程中驱动红色、绿色和蓝色。

在搜索了迄今为止关于多个驱动程序的 152 个帖子后,没有一个已发布的问题得到了赞成的答案,足以解释您 return 'U' 的原因或方式(或者在某些情况下 'X's).

IEEE 标准 1076-2008
14.7 模型的执行
14.7.2 驱动程序

Every signal assignment statement in a process statement defines a set of drivers for certain scalar signals. There is a single driver for a given scalar signal S in a process statement, provided that there is at least one signal assignment statement in that process statement and that the longest static prefix of the target signal of that signal assignment statement denotes S or denotes a composite signal of which S is a subelement. Each such signal assignment statement is said to be associated with that driver. Execution of a signal assignment statement affects only the associated driver(s).

14.7.3.2 驱动值

> 任意信号S的驱动值由以下步骤决定:

...
e) If S is a basic signal:

...
— If S is a resolved signal and has one or more sources, then the driving values of the sources of S are examined. ... the driving value of S is obtained by executing the resolution function associated with S, where that function is called with an input parameter consisting of the concatenation of the driving values of the sources of S, with the exception of the value of any source of S whose current value is determined by the null transaction.

14.7.3.2 驱动值中描述了如何操作分辨率函数。

类型或子类型 std_logic_vector (-2008) 是已解析的复合类型或具有已解析元素类型 (-2008) 的子类型,该元素类型使用 IEEE 包 std_logic_1164 中提供的元素的解析函数, 包体:

  -------------------------------------------------------------------
  -- resolution function
  -------------------------------------------------------------------
  constant resolution_table : stdlogic_table := (
    --      ---------------------------------------------------------
    --      |  U    X    0    1    Z    W    L    H    -        |   |
    --      ---------------------------------------------------------
             ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'),  -- | U |
             ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'),  -- | X |
             ('U', 'X', '0', 'X', '0', '0', '0', '0', 'X'),  -- | 0 |
             ('U', 'X', 'X', '1', '1', '1', '1', '1', 'X'),  -- | 1 |
             ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X'),  -- | Z |
             ('U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X'),  -- | W |
             ('U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X'),  -- | L |
             ('U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X'),  -- | H |
             ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X')   -- | - |
             );

  function resolved (s : STD_ULOGIC_VECTOR) return STD_ULOGIC is
    variable result : STD_ULOGIC := 'Z';  -- weakest state default
  begin
    -- the test for a single driver is essential otherwise the
    -- loop would return 'X' for a single driver of '-' and that
    -- would conflict with the value of a single driver unresolved
    -- signal.
    if (s'length = 1) then return s(s'low);
    else
      for i in s'range loop
        result := resolution_table(result, s(i));
      end loop;
    end if;
    return result;
  end function resolved;

将每个驱动程序值逐一与先前驱动程序的解析值进行比较,以确定包含每个新驱动程序的解析值。

由于称为最长静态前缀(8.名称)的特性,信号更新由元素完成,其中使用索引名称(8.4)或切片名称(8.5)强制数组组合到元素的驱动程序粒度(也满足子元素的定义)。 (对记录元素的赋值具有记录组合的所有元素和任何子元素的驱动程序。请参阅 8.3 选定名称。记录没有元素子集。)

多个驱动器的分辨率模拟两个输出连接在一起时发生的情况。例如,将多个输出连接在一起可能会违反用于内部网络的 FPGA 综合工具中的设计约束。

在您的设计中,您对多个进程中的驱动程序进行了分配(并且并发语句也提供了进程语句)。

其中两个进程不会根据未更新的 modus 值对红色、绿色或蓝色进行任何分配。 'U' 与 std_ulogic 的任何其他值的解析结果为 'U'.

如果您的测试平台导致在多个进程中分配给红色、绿色或蓝色,一个进程中一个标量元素驱动程序的“0”将被另一个驱动程序的“1”解析为 'X'.

很多目标设备系列不允许内部信号有多个来源(驱动程序)。例如,这在 FPGA 中很常见(而 Xilinx 支持自动转换互斥驱动的多个源,以通过某些设备系列的软件专利流程转换为多路复用器选择的源)。

对多个驱动程序的综合限制的一个解决方案可能是将前两个过程合并为一个过程,分配由模式值的条件选择分开。

另一个解决方案可能是在每个进程中分配唯一的信号,并在另一个由 modus 值引导的进程中为这些值分配红色、绿色和蓝色(手动模拟软件专利,这也应该提供质疑它的理由有效性)。

虽然循环在历史上不符合合成条件,但始终支持具有固定范围循环参数的循环。今天,一些综合工具支持 while 循环,其中退出条件可以通过相对较少的循环迭代来确定。 (循环在综合中展开。)至少有一个 while 循环可能需要重写正在实现的算法。