在 vhdl 中的模拟中使用 U 逻辑初始化输出

Output get initialized with U logic in simulation in vhdl

我正在使用 Xilinx。目前我正在从事一个开发流水线 MIPS 处理器的项目。我制作了一个名为 Program_Counter.vhd 的组件文件。当我使用测试台模拟它时,输出会用 U 初始化,然后就可以了。我无法理解这种行为。任何帮助将不胜感激。

我的Program_Counter.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Program_Counter is
  port (clk,reset,Last : in std_logic;
        addressALU : in std_logic_vector(31 downto 0);
        addressIR : out std_logic_vector(31 downto 0)
     ) ;
end entity ; -- Program_Counter

architecture Behavioral of Program_Counter is

signal PC : std_logic_vector(31 downto 0);

begin
process(clk)
begin
if rising_edge(clk) then
    if reset = '1' then
        PC <= (others => '0');
    elsif Last ='1' then
        null;
    else
        PC <= addressALU;       
    end if ;
end if ;
end process;
addressIR <= PC;
end Behavioral;

这是测试平台

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;

ENTITY PC_tb IS
END PC_tb;

ARCHITECTURE behavior OF PC_tb IS 

    COMPONENT Program_Counter
    PORT(
         clk : IN  std_logic;
         reset : IN  std_logic;
         Last : IN  std_logic;
         addressALU : IN  std_logic_vector(31 downto 0);
         addressIR : OUT  std_logic_vector(31 downto 0)
        );
    END COMPONENT;


   --Inputs
   signal clk : std_logic := '0';
   signal reset : std_logic := '0';
   signal Last : std_logic := '0';
   signal addressALU : std_logic_vector(31 downto 0) := (others => '0');

    --Outputs
   signal addressIR : std_logic_vector(31 downto 0);

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: Program_Counter PORT MAP (
          clk => clk,
          reset => reset,
          Last => Last,
          addressALU => addressALU,
          addressIR => addressIR
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;

   -- Stimulus process
   stim_proc: process
   begin        

      wait for 35 ns;
        --reset <= '0';
            for i in 1 to 10 loop
                addressALU <= addressALU + "1";
                wait for clk_period ;
            end loop;

      wait for clk_period*10;

      wait;
   end process;
END;

请参考仿真后的波形。 提前致谢。

PC信号通过连续赋值驱动addressIR输出:

addressIR <= PC;

但是PC直到clk的第一个上升沿才赋值,所以PC最初全是'U',称为"uninitialized" 在 std_logic_1164 包中,这是未分配的 std_logic 元素的第一个也是初始值。

PC 信号可以使用以下方法给定初始值:

signal PC : std_logic_vector(31 downto 0) := (others => '0');

但通常最好不要这样做,因为在模拟中显示非 '0'/'1' 值是好处之一,因为它可能揭示缺少分配的实际问题,例如由于遗漏了重置或类似问题。

信号 addressIR 在第一个时钟上升沿之前都是 'U',因为您没有为其分配任何其他值。赋值来自这个语句:

addressIR <= PC;

and在模拟启动后执行一次,每次PC变化。也就是说,addressIR 在增量循环后等于 PC。信号 PC 在时钟上升沿的时钟过程中第一次被分配。在此之前,PC 的信号值由其声明定义。您没有在那里指定值,因此 std_logic_vector 的所有元素都被初始化为 std_logic 类型枚举中的第一个值。那就是'U',表示信号是未初始化.

模拟在这里显示了真实世界的行为,特别是如果您为 standard cell technology. On FPGAs you have sometimes the option to program the initial value of a flip-flop. But, you will have to reset the FPGA design after startup anyway as discussed in the question "Do I need to reset my FPGA design after startup?" on Electrical Engineering. My answer there 合成 VHDL 代码,包括初始化失败的屏幕截图。因此,无论如何你都必须断言reset

第一个时钟上升沿之前 addressIR 的值应该没有意义,因为使用该信号值的单元也应该处于复位状态。例如,指令总线单元不应在复位时发出总线事务。

整个系统的所有组件都应在第一个时钟上升沿执行复位。


您应该在您的测试平台中包含一个重置同步器。稍后,这个重置同步器将成为整个系统的一部分。您将需要这些声明:

signal reset_sync : std_logic_vector(1 downto 0) := (others => '1');
signal reset : std_logic;

以及架构主体(寄存器链)中的这些语句:

reset_sync <= reset_sync(reset_sync'high-1 downto 0) & reset_pin when rising_edge(clock);
reset <= reset_sync(reset_sync'high); -- active-high

信号reset_pin为外部复位输入。如果您不需要它,只需将其替换为“0”即可。

是的,此重置同步器使用 FPGA 上的已初始化触发器。但是,只有触发器 reset_sync(0) 会遇到初始化问题。在 Xilinx FPGA 上的全局写入使能 (GWE) 释放后的第一个时钟上升沿之后,该触发器的值可能为“0”或“1”。触发器 reset_sync(1) 将在至少一个完整时钟周期内为“1”。