假设我有一个信号,我可以指定初始值为零或者我可以在RESET时将其设置为零.我看到我的同事可以互换地使用这两种方法.我只想看到别人对此的看法.
示例(使用初始值):
architecture arch of xxx is
signal flag : STD_LOGIC := 0;
begin
process (clk) begin
if rising_edge(clk) then
-- do something
end if;
end process;
end arch;
Run Code Online (Sandbox Code Playgroud)
示例(使用重置值):
architecture arch of xxx is
signal flag : STD_LOGIC;
begin
process (clk,rst) begin
if (rst = '1') then
flag <= '0';
elsif rising_edge(clk) then
-- do something
end if;
end process;
end arch;
Run Code Online (Sandbox Code Playgroud)
如果可能,请使用专用的复位信号,原因如下:
使用复杂时钟生成的设计可能要求模块保持空闲(复位)直到时钟稳定.使用具有不稳定但正在运行的时钟的初始值可能会更改预期的初始值.
与其他模块或外部模块接口的模块可能在启动期间在接口上发生协议违规,并且为了避免由于协议违规而导致的错误操作或挂起,可能需要将模块保持在复位状态,直到协议操作在接口.
通过断言复位可以重新启动整个系统或部分系统,而不必重新加载整个FPGA,这需要更长的时间,如果需要CPU交互,可能会更复杂.
某些FPGA技术(例如Altera部分重配置)不支持部分重配置中使用的模块的初始值.因此,如果仅使用复位,则更容易重用模块.
当可以应用复位并继续相同的模拟序列时,模拟不同的启动/重启条件会更容易.如果使用初始值,则必须重新启动整个模拟.
由于Russell指出的资源原因,将重置应用于尽可能少的触发器.此外,仅将其应用于所需的触发器,可以更容易地在模拟过程中捕获设计中的错误和疏忽,因为X
可能会出现未知值.复位应该是异步的,因为大多数FPGA和ASIC技术都具有带有专用复位输入的触发器,并且复位将不会减慢同步设计部分的时序,通过插入逻辑来应用复位值.在例如Altera Cyclone V中可以看到减速,由于通过MLABCELL的同步复位,逻辑插入到数据路径中,如此处的数据路径时序报告所示:

使用异步复位的触发器在数据路径中没有这种额外的延迟,如图中通过此链接所示.
具有复位功能的触发器的过程应使用复位部分写入:
process (clk, rst) begin
if rising_edge(clk) then
-- Flip-flops updated at clock
end if;
if (rst = '1') then
-- Flip-flops reset
end if;
end process;
Run Code Online (Sandbox Code Playgroud)
这种编码风格使得可以仅将复位应用于在上升时钟更新的一些触发器,而剩余的触发器在没有复位的情况下实现.
组合if-then-elsif-end if的问题代码,实际上指定了在复位期间状态被保持为未复位的触发器,因为该
rising_edge(clk)部分if不会生效.这可能不是预期的实现.
为了正确定时,复位信号(rst)应与时钟(clk)同步,至少是为了无效(1至0),因此不会违反恢复和移除时间.