记一个Verilog一段式状态机的低级错误

问题是这样的:
我想在某个状态state1下根据输入a改变输出b的值,但是在芯片里运行的时候发现只要状态维持在state1下,b的值始终是从上一个状态跳到state1时的值,只有在state1变化的边沿,b的值才会根据输入a更新。

环境:quartus II 12.1

原代码如下:

always @ (posedge clk) 
begin
    if (rst) begin
        b <= 'd0;
        state <= state1;
    end else begin
        case (state):
            state1: begin
                if (a) b <= 'd1;        // 逻辑1
                if (c) state <= state2; // 逻辑2
            end
            state2:
            default:
        endcase
    end
end

这个代码看起来好像没什么问题,在state1下b的值跟随条件a变化(逻辑1),满足条件c则进行状态跳转(逻辑2)。
但实际上state1里的逻辑是这样的(综合后的电路逻辑):

if (c) begin
    state <= state2;
    if (a) b <= 'd1;
end else begin
    state <= state;
    b <= b;
end

跟我想要的逻辑完全不一样,而且掉入这样的坑里面之后,半天爬不出来。在原代码里忽略了if…else…的优先级,本来逻辑1、逻辑2是可以分开的,但必须是写在两个always里才可以,这里写在一个always里,综合工具就不能理解代码的意思了,因为可以分开也可以不分开,代码有歧义。

修改后的代码如下:

always @ (posedge clk) 
begin
    if (rst) begin
        b <= 'd0;
        state <= state1;
    end else begin
        case (state):
            state1: begin
                if (c) begin
                    state <= state2;
                    if (a) b <= 'd1;
                end else begin
                    state <= state1;
                    if (a) b <= 'd1;
                end
            end
            state2:
            default:
        endcase
    end
end

如果是三段式状态机就不会存在这样的问题,所以如果状态机比较大,状态数很多,个人觉得还是三段式好一点,至少出了问题好分析。

.
.
.
.
.

你可能感兴趣的:(Verilog)