代码之家  ›  专栏  ›  技术社区  ›  Nigel Davies

变量是否也需要VHDL默认信号分配?

  •  2
  • Nigel Davies  · 技术社区  · 7 年前

    我知道默认信号分配在VHDL中很有用(甚至是必要的),可以避免不完整的分配和推断的锁存。我无法发现变量是否也需要它。

    考虑以下代码块:

      test_sequencer : process(fpga_clock)
        variable sequencer_count : unsigned(3 downto 0) := (others => '0');
      begin
        if rising_edge(fpga_clock) then
          start_writing   <= start_writing;
          start_reading   <= start_reading;
          sequencer_count := sequencer_count; -- is this line necessary
          if not_every_fpga_clock = '1' then
            case sequencer_count is
              when x"4" =>
                start_writing <= '1';
              when x"12" =>
                start_reading <= '1';
              when others =>
                null;
            end case;
            if sequencer_count /= 15 then
              sequencer_count := sequencer_count + 1;
            end if;
          end if;
        end if;
      end process;
    

    是否需要标有“是否需要此行”的行?我知道它一定在那里如果 sequencer_count 是一个信号。什么时候有必要 序列器计数 是变量吗?

    3 回复  |  直到 7 年前
        1
  •  2
  •   Jim Lewis    7 年前

    首先,默认分配仅在没有时钟存在的情况下防止锁存-即:组合逻辑。

    在寄存器/触发器逻辑(在“if上升沿(时钟)”后面的代码)中,默认分配防止保持条件-这是寄存器逻辑的正常部分。“如果上升沿(时钟)”下的代码永远不会产生锁存。

    奥托,你所拥有的我称之为身份分配:

      start_writing   <= start_writing;
      start_reading   <= start_reading;
      sequencer_count := sequencer_count; 
    

    身份分配不是默认分配,而是显式指定反馈。这些并不能阻止组合逻辑中的锁存。

      start_writing   <= '0';
      sequencer_count := "0000";
      LedState <= LedNext;
    

    请注意,对于流程中的变量声明,只有在详细说明流程时才会运行初始化—这是在时间开始时,而不是每次流程运行时:

    variable sequencer_count : unsigned(3 downto 0) := (others => '0');
    

    这与每次调用时创建并初始化变量的子程序执行不同。

        2
  •  1
  •   Matthew Taylor    7 年前

    这些线路都不是必需的:

      start_writing   <= start_writing;
      start_reading   <= start_reading;
      sequencer_count := sequencer_count; -- is this line necessary
    

    他们什么也没做。在完全赋值和锁存中,逻辑推理只是一个组合逻辑问题。这是(同步)顺序逻辑。您不必担心使用(同步)顺序逻辑完成赋值。

    为什么会这样?好吧,在组合逻辑的情况下,如果你没有完全赋值,就会有一些输入的组合,它会导致一个路径,在这个路径中,进程的输出(由它驱动的信号)不会被赋值。任何信号都将保持其值,直到分配新值。因此,在不完全赋值的情况下,结果电路必须记住(存储)该输出的状态。因此,将合成某种能存储信息的电路。这不会是一个触发器,因为没有时钟,没有 rising_edge

    但是,在(同步)时序电路中,您已经有了存储器。触发器可以看作是1位存储器。因此,您不必担心(同步)顺序过程中的完整赋值。您期望得到的电路能够存储东西。

        3
  •  1
  •   Morten Zilmer    7 年前

    rising_edge(fpga_clock) ,既不需要默认变量赋值,也不需要默认信号赋值,如果进程由于上升时钟触发(执行)时没有新赋值,则两者都将保持上升时钟之前的值。

    if

    process (d, en, q)
    begin
        if en = '1' then
            q <= d;
        end if;
    end process;
    

    在这种情况下 q 仅在以下情况下更新 en '1' ,因此将推断一个锁存器来保存 q '0'

    作为一个相关的注释,在一个连续的(有时钟的)过程中使用变量来保持状态通常是不好的编码方式,并且最好声明一个信号 sequencer_count