问题描述
在我的 Verilog 代码中,ns
值没有分配给 next state logic
中的任何值。当我对 next state logic
进行编码以在 ns
中发生转换时为 ps
状态变量赋值。
这是 FSM 代码片段
// State registers
always@(posedge clk,negedge rst) begin
if(!rst) ps <= S1;
else ps <= ns;
end
assign present_state = ps;
assign next_state = ns;
// Next state logic
always@(ps,start) begin
case(ps)
S1: ns = start ? S2 : S1;
S2: ns = S3;
S3: ns = S1;
//default : ns = S1;
endcase
end
这是tb代码片段
initial begin
#0 rst = 0; start = 0;
#2 rst = 1;
#10 a = 3; b = 4;
#10 start = 1;
最后是波形输出
我的目的是让 ps <= ns
从 S1
无缝转换到 S2
到 S3
回到 S1
等等,但是出于某种原因,尽管always_comb
下一个状态逻辑块,在 t=0 时 ps
的状态变化没有将 ns
分配给有效状态?导致所有进一步的 ps <= ns
分配始终为 'x
状态
这个逻辑有问题吗?
非常感谢您的快速帮助
谢谢
解决方法
我可能是错的,但我认为你有一个从 ns 到 ns 的意外隐含锁存器。由于您注释掉了默认值,当 ps 不是 {S1,S2,S3} 中的任何一个时,ns 会被锁回自身。这些块在模拟开始时处理的顺序可能会改变,所以这可能是 ns 以 X 开头的原因。
由于 ns 以 X 开头,这就解释了为什么 X 在第一个时钟上升沿而不是复位时传播到 ps;从那里开始, ps 将不匹配(因为您使用的是 case 而不是 casex),并且两者都会像您在此处看到的那样保持 X。
我认为解决这个问题的最简单方法是通过在 case 语句中指定默认值来使 ns 不是闩锁。
(使用 always_ff 和 always_comb 可以让编译器帮助你警告这样的事情)
,感谢您的回复,我已经找到原因了。它的三元运算符 ()? x:y;
冒号没有正确括起来,导致编译器错误地推断三元运算符 ()? x:y;
冒号是 case ... endcase
冒号。我通过使用 if else
语句来避免歧义解决了这个问题。我想三元运算符 ()? x:y;
可以用在 case
语句中,如果写得正确和封闭,但我只是使用了 if else
语句以避免歧义。
// Next state logic
always@(ps,start) begin
case(ps)
//S1: begin ns = (start ? S2 : S1); end // old code
S1: begin if(start) ns = S2; else ns = S1; end // new code
S2: ns = S3;
S3: ns = S4;
S4: ns = S1;
//default : ns = S1;
endcase
end