0

我正在编写一些要在Altera Cyclone II FPGAVerilog板上编程的代码,并且我有一个应该在按下按键开关时激活的块:always

reg START;

...
...

always @ (negedge key[3]) begin
    if (START != 1) START = 1;
end

我正在为有限状态机编写一个程序,这个按键应该表明用户想要开始使用该程序,并且它应该从其初始状态移动到下一个状态。由于寄存器的初始化是不可综合的,我不能假设它START从 0 开始。

问题是,一旦我对电路板进行编程并打开它,always在我按下分配给的键之前,这个块已经运行了一次key[3]。我已经检查了STARTat 程序执行的值,它已经在1. 我不知道为什么会发生这种情况,因为只有在按键时键才处于负边缘。我在以前的情况下总是使用具有相同条件的块并且它工作正常,所以我认为这与初始化有关START

4

2 回答 2

1

您应该使用“初始”块来设置信号的启动值。必须设置 START 和 key[3] 的值。

initial begin
  START = 1'b0;
  key[3] = 1'b1;
end

你说

由于寄存器的初始化是不可综合的,我不能假设 START 从 0 开始。

但是这是错误的!您可以使用上述方法为设计中的任何信号设置默认值。该值包含在固件的比特流中,并且具有该值的信号启动。

干杯

于 2014-11-13T09:32:35.363 回答
1

应该注意的是,可综合性initial取决于您正在编码的目标。
例如,如果您为模拟器编写代码,initial效果会很好。如果您的目标是 FPGA,则该工具(在您的情况下为 quartus)可以完全控制原理图以及其中每个触发器的初始状态:实际上,将固件上传到 FPGA 会将每个触发器设置为已知状态,并且 quartus 能够解析initials 以导出每个触发器的状态。相反,如果您的目标是裸硅,每个触发器只是一堆晶体管,其状态在通电时完全不确定,因此控制其通电状态的唯一方法是应用某种类型的复位,例如这个:

always @(posedge clk, negedge rst_n)
if( !rst_n )
    START <= 1'b0; // no start condition upon reset
else if( some_condition )
    START <= 1'b1;

您的代码的另一点是,在解析来自开关的输入时,您应该首先重新同步到您的设计时钟,如下所示:

reg start_r, start_rr;
always @(posedge clk)
begin
    start_r  <= START;
    start_rr <= start_r;
end
// now use start_rr instead of START

重新同步是避免同步设计中出现亚稳态的关键要素。

第二点是您应该考虑对机械开关的任何输入进行去抖,除非您的设计能够容忍开关的多次跳闸。

回到 Ryan McClure 提出的原始问题。可以看出,在没有initialSTART 的原始代码中,在启动时是未定义的,并且只能跳到“1”状态。因此,合成器只是假设 START 是恒定的,始终为“1”。

于 2014-11-14T15:40:08.637 回答