我正在编写一些Verilog
代码,以便在 Altera Cyclone II FPGA 板上编程,我有一个always
块,应该在按下钥匙开关:
reg START;
...
...
always @ (negedge key[3]) begin
if (START != 1) START = 1;
end
我正在为有限状态机编写一个程序,这个按键应该表示用户想要开始使用该程序,它应该从其初始状态转移到下一个状态。由于寄存器的初始化不可合成,我不能假设START
从0开始。
问题在于,一旦我对电路板进行编程并将其打开,在我按下分配给always
的密钥之前,此key[3]
块已经运行过一次。我已经在程序执行时检查了START
的值,它已经在1
。我无法弄清楚为什么会发生这种情况,因为关键是只有在按键时它处于负面边缘。在以前的情况下,我总是使用具有相同条件的块,并且它工作正常,所以我认为这与START
的初始化有关吗?
答案 0 :(得分:1)
你应该使用"首字母"阻止设置信号的启动值。必须设置START和键[3]的值。
initial begin
START = 1'b0;
key[3] = 1'b1;
end
你说
由于寄存器的初始化不可合成,我不能 假设START从0开始。
但事实并非如此!您可以使用上述方法为设计中的任何信号设置默认值。该值包含在固件的比特流中,并且信号启动时具有此值。
欢呼声
答案 1 :(得分:1)
应该注意initial
的可合成性取决于您编码的目标。
例如,如果您为模拟器编码,initial
效果很好。如果您的目标是FPGA,那么该工具(在您的情况下为quartus)可以完全控制原理图和内部每个触发器的初始状态:实际上,将固件上传到FPGA会将每个触发器设置为已知状态,并且quartus能够解析initial
以得出每个触发器的状态。
相反,如果你的目标是裸硅,每个触发器只是一堆晶体管,它的状态在上电时是完全无限的,所以控制它的通电状态的唯一方法是应用某种类型重置,像这样:
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
重新同步是避免同步设计中亚稳状态的关键因素。
第二点是你应该考虑对机械开关的任何输入进行去抖动,除非你的设计能够容忍多次开关跳闸。
回到原来的问题瑞恩麦克卢尔要求。可以看出,在原始代码中没有initial
START在启动时未定义,并且只能跳转到&#39; 1&#39;州。因此,合成器只是假设START是恒定的,总是有它&#39; 1&#39;。