正如布赖恩·德拉蒙德 (Brian Drummond) 所写,您可以用变量合成进程,网表结果取决于变量是在赋值之前还是之后读取。
如果变量在赋值之前被读取,那么变量会将一个值从前一个时间转移到当前时间,并且需要存储(通常是触发器或锁存器)以保持状态随时间推移。示例代码,其中
sig和var都将导致触发器,因为变量var在分配之前被读取:
process (clk_i) is
variable var : std_logic;
begin
if rising_edge(clk_i) then
sig <= var;
var := arg;
end if;
end process;
Run Code Online (Sandbox Code Playgroud)
如果变量在赋值后被读取,那么之前的任何变量值都不会被使用,因此在网表中没有实现存储。因此,该变量仅用于生成中间值,例如简化代码编写。示例代码,其中只会sig导致触发器,因为变量
var是在赋值后读取的:
process (clk_i) is
variable var : std_logic;
begin
if rising_edge(clk_i) then
var := arg;
sig <= var;
end if;
end process;
Run Code Online (Sandbox Code Playgroud)
在更复杂(现实)的代码中,可能很难确保变量只在赋值后读取,因此不会推断出意外的存储(触发器或锁存器)。一种有用的编码风格是'X'在代码的开头用未知 ( )分配所有变量。如果在分配之前读取变量,则通常会在模拟和调试的早期发现错误。示例代码:
process (clk_i) is
variable var : std_logic;
begin
if rising_edge(clk_i) then
var := `X`; -- Ensure variable assign before any use to avoid storage
var := arg;
sig <= var;
end if;
end process;
Run Code Online (Sandbox Code Playgroud)
请注意,在仿真中,通常需要付出额外的努力才能在波形中包含变量;例如,ModelSim 在单独的“本地”视图中显示过程变量。如果保持状态的变量被排除在波形之外,那么调试就会困难得多,因为波形只显示了一半的故事。
因此,一种实用的编码风格是仅将变量用于过程中的中间值,从而始终在分配后进行读取。