我在verilog中创建一个状态机,根据用户输入实现某些算术功能。然而,我遇到了障碍;我的第一个总是阻塞,一个处理我的重置并保持正确状态,阻止不按预期行事;它没有正确更新状态。代码如下:
always @ (posedge CLOCK_50 or negedge RESET) begin
if(RESET == 1'b0)
STATE <= BASE;
else
STATE <= NEXT_STATE; // this always block, and specifically this line, is //not executing correctly.
end
以下是复位后的文件的一般输出,然后按下三个按钮(KEY [1]),SW = 0000:
编辑:添加实际CLOCK_50和RESET信号的波形
至于我的问题,我只是想知道我在这部分代码中做错了什么。我认为没有理由这样做。感谢您提供的任何帮助。
EDIT2:FFS,我将块更改为negedge CLOCK_50,现在它正在运行。如果你能告诉我,我真的很想知道为什么。
答案 0 :(得分:2)
STATE
({case}块的默认值为STATE <= STATE
。这很糟糕,因为它是两个块之间的竞争条件,实际分配了哪个。在您的情况下,第二个块覆盖第一个块,以便每个时钟执行STATE <= STATE
。您不应在多个always块中分配相同的变量。
此外,您应该注意这些警告,但它们指的是always @(ENABLE)
块。这是抱怨,因为你推断了奇怪的锁存行为,因为输出取决于STATE和SW,但它们不在敏感列表中。您可能应该将其设为组合块,并使用自动敏感列表always @*
。
答案 1 :(得分:1)
每个始终阻塞,以及始终阻止之外的每个语句,都有效地并行运行。
由于您的“状态”由两个始终块驱动,因此您实际上有两根电线馈入单根电线。在数字逻辑设计中,你无法做到这一点。 (不包括上拉电阻等,但这是另一个话题。)
在模拟中,如果驱动该单线的多根线具有相同的逻辑值,则可以获得所需的输出;但如果它们具有不同的值,您将得到无效或不可预测的输出。
在综合中,这只会因“多个驱动程序”错误而失败。
此外,始终阻止的敏感性列表应包含三个内容之一:
任何其他东西都可能导致无意识的锁存,这会导致问题。
在第3种情况下,您需要确保always块中驱动的每根导线都有一个默认值。任何其他东西都可能导致无意识的锁定。
最后,您不能进行循环分配,也不会冒逻辑循环的风险。你可以通过为自己分配next_state来获得一个。任何“循环”都需要一个触发器,也就是上面概述的类型1或2的总是块。