Reputation: 37
I'm trying to create a vending machine in System Verilog using an FSM, and during synthesis, the software warned me with this error:
[Synth 8-327] inferring latch for variable 'FSM_sequential_statoProssimo_reg' ["MacchinettaMerendine.sv":87]
The code is:
...
module FSM_50_Cent (
input logic Clk100_MHz, Reset,
input logic Cent20, Cent50, Euro1, Confirm,
input logic [7:0] Switch50,
output logic Er, r10, r20, r40, r50
);
enum logic [4:0] {S0, S1, S2, S3, S4, S5, S6, S7, S8, S9,
S10, S11, S12, S13, S14, S15, S16, S17} Stati; //STATES
logic [4:0] Stato, statoProssimo; //STATE AND NEXTSTATE
always_ff @(posedge Clk100_MHz, posedge Reset) //FLIP FLOP
begin
if(Reset) Stato <= S0;
else Stato <= statoProssimo;
end
always_comb //NEXT STATE LOGIC
begin
if((|Switch50) == 1)
begin
case(Stato)
S0: if (Cent20) statoProssimo = S1;
else if (Cent50) statoProssimo = S3;
else if (Euro1) statoProssimo = S8;
else if (Confirm) statoProssimo = S0;
S1: if (Cent20) statoProssimo = S2;
else if (Cent50) statoProssimo = S5;
else if (Euro1) statoProssimo = S9;
else if (Confirm) statoProssimo = S1;
S2: if (Cent20) statoProssimo = S4;
else if (Cent50) statoProssimo = S7;
else if (Euro1) statoProssimo = S10;
else if (Confirm) statoProssimo = S2;
S3: if (Confirm) statoProssimo = S0;
S4: if (Confirm) statoProssimo = S0;
S5: if (Confirm) statoProssimo = S0;
S6: if (Confirm) statoProssimo = S0;
S7: if (Confirm) statoProssimo = S0;
S8: if (Confirm) statoProssimo = S0;
S9: if (Confirm) statoProssimo = S0;
S10: if (Confirm) statoProssimo = S0;
default statoProssimo = S0;
endcase
end
end
...
endmodule
...
And the error is on this line: S0: if (Cent20) statoProssimo = S1;
Why?
Upvotes: 1
Views: 1010
Reputation: 363
Go through the toolic explanation of answer and see the always_comb
section of this code.
module FSM_50_Cent (
input logic Clk100_MHz, Reset,
input logic Cent20, Cent50, Euro1, Confirm,
input logic [7:0] Switch50,
output logic Er, r10, r20, r40, r50
);
typedef enum logic [4:0] {S0, S1, S2, S3, S4, S5, S6, S7, S8, S9,
S10, S11, S12, S13, S14, S15, S16, S17} Stati; //STATES
Stati Stato, statoProssimo; //STATE AND NEXTSTATE
//STATE FLIP FLOPS
always_ff @(posedge Clk100_MHz, posedge Reset)
if(Reset) Stato <= S0;
else Stato <= statoProssimo;
//NEXT STATE LOGIC
always_comb begin
statoProssimo = Stato;
if((|Switch50) == 1)
case(Stato)
S0: if (Cent20) statoProssimo = S1;
else if (Cent50) statoProssimo = S3;
else if (Euro1) statoProssimo = S8;
else if (Confirm) statoProssimo = S0;
S1: if (Cent20) statoProssimo = S2;
else if (Cent50) statoProssimo = S5;
else if (Euro1) statoProssimo = S9;
else if (Confirm) statoProssimo = S1;
S2: if (Cent20) statoProssimo = S4;
else if (Cent50) statoProssimo = S7;
else if (Euro1) statoProssimo = S10;
else if (Confirm) statoProssimo = S2;
S3,S4,
S5,S6,
S7,S8,
S9,S10: if (Confirm) statoProssimo = S0;
default statoProssimo = S0;
endcase
end
Upvotes: 1
Reputation: 61987
To avoid a latch, the always_comb
block must assign a value to statoProssimo
under all conditions.
However, the block does not assign a value to statoProssimo
when Switch50
is 0, for example. Therefore, the Verilog simulation will retain the value of statoProssimo
. This infers a memory element (a latch).
You could add an else
clause and assign a value. For example:
always_comb //NEXT STATE LOGIC
begin
if((|Switch50) == 1)
begin
case(Stato)
...
endcase
end
else statoProssimo = S0;
end
The same applies for each of the case
items. You should use an else
clause to assign a value.
S0: if (Cent20) statoProssimo = S1;
else if (Cent50) statoProssimo = S3;
else if (Euro1) statoProssimo = S8;
else statoProssimo = S0;
You need to decide what value to assign in each case.
Upvotes: 1