如何避免ASM图表verilog中的推断锁存器?

时间:2018-01-31 18:50:09

标签: verilog

我不明白如何在我的ASM设计中避免推断锁存器 这是我的代码。

module ASM (
input[7:0] SW,
input Start, Reset, Clock,
output reg Led,
output reg[3:0] result);

reg[2:0] state, next_state;
reg[7:0] A;
wire Done;

parameter S1 = 3'd1;
parameter S2 = 3'd2;
parameter S3 = 3'd3;
parameter S4 = 3'd4;
parameter S5 = 3'd5;
parameter S6 = 3'd6;

always @(posedge Clock)
begin
    if (!Reset)
        state <= next_state;
    else
        state <= S1;
end

always @(state, Start, A)
begin

    case(state)
    S1: begin
        if (Start)
            next_state = S2;
        else
            next_state = S1;
    end
    S2: begin //check A == 0
        if (A == 8'd0)
            next_state = S6; //done
        else
            next_state = S3;//check A0
    end
    S3: begin //check A0
        if (A[0])
            next_state = S4; //result++
        else
            next_state = S5; //A>>1
    end
    S4: begin //result++
        next_state = S5;
    end
    S5: begin //A>>1
        next_state = S2;
    end     
    S6: begin //done
        if (Start)
            next_state = S6;
        else
            next_state = S1;
    end
    default: begin
        next_state = S1;
    end     
    endcase
end

always @(state, SW)
begin
    //result = 4'b0;
    //A = 8'd0;
    //Led = 1'b0;   
    case (state)
    S1: begin
        A = SW;
        result = 4'b0;
        Led = 1'b0; 
    end
    S2: begin

    end
    S3: begin

    end
    S4: begin
        result <= result + 4'd1;
    end
    S5: begin
        A = A >> 1;
    end     
    S6: begin
        Led = 1'b1;
    end     
    default: begin
        result = 4'b0;
        Led = 1'b0;     
    end 
    endcase
end
endmodule

我理解我应该在第二个“always”块中的“case”语句之前初始化变量“A”,“result”和“led”。但是如果每次“始终”块处于活动状态时都这样做,我会松开以前的变量结果并再次将它们分配给初始值,因此整个设计是错误的。这样我就无法避免使用锁存器而只是不应该初始化这些变量。但是锁存是不好的做法。所以你能解释我应该如何改变代码来避免这种情况吗?

3 个答案:

答案 0 :(得分:0)

嗯,你想要获得的行为(仅对某些输入进行更改并保留其值)是锁存器的行为。如果你想避免使用锁存器并且使用内存变量,则使用同步始终阻塞。

always @(posedge Clock)
begin 
    case (next_state)
    S1: begin
        A <= SW;
        result <= 4'b0;
        Led <= 1'b0; 
    end
    S2, S3: begin

    end
    S4: begin
        result <= result + 4'd1;
    end
    S5: begin
        A <= A >> 1;
    end     
    S6: begin
        Led <= 1'b1;
    end     
    default: begin
        result <= 4'b0;
        Led <= 1'b0;     
    end 
    endcase
end

答案 1 :(得分:0)

合成器只关心同步逻辑的灵敏度列表。 @(state, SW)仅触发模拟中的特定变量。合成器基本上看@(state, SW, result)。这种方式@*(同义@(*))是组合逻辑和有意锁存的首选。

有关推断锁存器的详细信息,请阅读:What is inferred latch and how it is created when it is missing else statement in if condition.can anybody explain briefly?

对于您的情况,您应该使块同步。将@(state, SW)更改为@(posedge Clock)。要缩短时序延迟,请在同一个始终阻止中将case (state)更改为case (next_state)。您应该使用非阻止分配AresultLed。您可能想要添加重置条件。

答案 2 :(得分:0)

从示例中的第二个case语句中推断出锁存器。原因是所有3个变量都在某些条件下分配(S1)而在其他条件下没有分配(S2,S3,...),这意味着它们在这种情况下保留旧值。这是典型的锁存行为。因此,您推断了锁存器。

我认为这种说法在任何情况下都不适合修复。你有一堆错误,使用的操作只能在同步块中完成,比如A = A >> 1或混合阻塞和非阻塞分配。它不是设计状态机的方法。那么,看看@Hans的Lehnert的回答来获得一个想法。