我了解默认信号分配在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
是变量时是否有必要?
答案 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;
在这种情况下,仅当q
为en
时更新'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位存储器。因此,您不必担心(同步)顺序过程中的完整分配。您期望生成的电路能够存储东西。