当下一状态组合逻辑块转换中的“当前状态”值时,系统 Verilog FSM“下一状态”不会转换 - 三元运算符

问题描述

在我的 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;

最后是波形输出

fsm_ns_notransition

我的目的是让 ps <= nsS1 无缝转换到 S2S3 回到 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