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

时间:2018-09-26 14:05:35

标签: vhdl fpga

我了解默认信号分配在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是一个信号,它必须存在。 sequencer_count是变量时是否有必要?

3 个答案:

答案 0 :(得分:2)

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

在寄存器/触发器逻辑(“ ifrise_edge(clock)”之后的代码)内,默认分配可防止保持条件-这是寄存器逻辑的正常部分。永远不会在“如果上升边缘(时钟)”下从代码中生成锁存器。

OTOH,我称之为身份分配:

  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');

这与子程序执行不同,子程序执行在每次调用时都会创建和初始化变量。

答案 1 :(得分:1)

在同步过程中,使用rising_edge(fpga_clock)时,既不需要缺省变量分配也不需要缺省信号分配,并且如果在过程触发时没有新的分配,则两者都将在上升时钟之前保存该值。 (执行)是由于时钟上升。

关于推断锁存器的想法可能与组合过程有关,在组合过程中,如果if语句的某些分支未分配给驱动信号,则可以推断出锁存器,例如:

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

在这种情况下,仅当qen时更新'1',因此,如果q为{ {1}}。

作为相关注释,使用变量在顺序(计时的)过程中保持状态通常是不好的编码风格,并且最好为en声明信号。原因是所有触发器的编码方式都相同,并且由于变量在典型的仿真波形中不可见,因此调试起来更容易。

答案 2 :(得分:1)

这些行都不是必需的:

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

他们什么都不做。在完全分配和锁存器推断中,组合逻辑只是一个问题。这是(同步)顺序逻辑。您无需担心使用(同步)顺序逻辑进行完整分配。

这是为什么?好吧,在组合逻辑的情况下,如果您没有完整的分配,则会有一些输入组合,从而导致遵循流程的路径,而流程的输出(由其驱动的信号)会没有得到分配值。任何信号都将保持其值,直到分配了新值。因此,在分配不完全的情况下,所产生的电路必须记住(存储)该输出的状态。因此,将合成某种可以存储信息的电路。那将不是触发器,因为它没有时钟,没有rising_edge函数调用,等等。取而代之的是,锁存器将被综合起来进行记忆。这是双倍的糟糕,因为(a)锁存器从根本上来说是糟糕的,并且(b)您想要组合逻辑,但需要顺序执行。那是个错误。

但是,在(同步)顺序电路中,您已经有存储。触发器可以视为1位存储器。因此,您不必担心(同步)顺序过程中的完整分配。您期望生成的电路能够存储东西。