three kinds of writing and advantages and disadvantages of finite state machine
The key to state machine description is to describe the features of several state machines mentioned earlier, that is, how state transitions are performed, what the output of each state is, whether state transitions are related to input conditions, and so on. Specific description of the various methods, some designers are accustomed to the entire state machine written to 1 always module, in the module that describes the state transfer, also describes the state input and output, which is generally referred to as a paragraph of the FSM description method; There is also a way to use 2 always modules, where a always module uses synchronous timing to describe state transitions, and the other module uses combinatorial logic to judge state transitions, describing state transitions , which are called two-segment FSM description methods. Another way of writing is developed on the basis of a two-paragraph description method, which uses 3 always modules, one always module uses synchronous timing to describe the state transfer, and the second one uses combinatorial logic to judge state transition conditions, and describes the law of State transfer; the third always The module uses a synchronous sequential circuit to describe the output of each state , which is called a three-paragraph notation.
Generally speaking, the recommended FSM description method is the latter two, namely two-stage and three-segment FSM description method. The reason for this is that FSM, like other designs, is best designed with synchronous timing to improve design stability and eliminate burrs. When the state machine is implemented, in general, the state transfer part is the synchronous sequential circuit, and the judgment of the state transfer condition is the combinatorial logic . The reason why two-stage encoding is more reasonable than a piece of code is that the two-segment encoding combines synchronous timing and combinational logic into different always program blocks . The benefits of doing so are not only easy to read, understand, maintain, but more importantly, to optimize the code for the integrated system, to facilitate the user to add the appropriate timing constraints, the layout of the design to facilitate the implementation. The segment FSM description is not conducive to timing constraints, function changes, debugging, etc., and does not represent the output of the Miller FSM, easy to write latches, resulting in a logical function error.
In the general two-paragraph description, in order to facilitate the description of the current state of output, many designers are accustomed to the current state of output with the combination of logic implementation. However, this combination logic still has the possibility of producing burrs, and it is unfavorable to the constraint, which is not conducive to the high performance design of the synthesis and the layout router. Therefore, if the design runs an additional clock-beat insertion (latency), it is required to register the output of the state machine with a single shot. However, many situations do not allow the insertion of a register beat, which can be solved by a three-segment description method. Compared with the two-segment, the key is to determine the output of the current state according to the input conditions in the previous state, so that the register output is realized without inserting the extra clock beats.
For the sake of understanding, we discuss these three different ways of writing through an example.
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/-->//One-stage state machine description method (should be avoided)
// The one-piece description code for this example is as follows:
// 1-paragraph method to describe FSM
// Describe state transition, state output, input condition in 1 always block
module state1 (nrst, clk, i1, i2, o1, o2, err);
input nrst, clk;
input i1, i2;
output o1, o2, err;
reg o1, o2, err;
reg [2: 0] NS; // NextState
parameter [2: 0] // one hot with zero idle
IDLE = 3'b000,
S1 = 3’b001,
S2 = 3’b010,
ERROR = 3’b100;
// 1 always block to describe state transition, state output, input condition
always @ (posedge clk or negedge nrst)
if (! nrst)
begin
NS <= IDLE;
{o1, o2, err} <= 3'b000;
end
else
begin
NS <= 3'bx;
{o1, o2, err} <= 3'b000;
case (NS)
IDLE: begin
if (~ i1) begin (o1, o2, err) <= 3'b000; NS <= IDLE; end
if (i1 && i2) begin {o1, o2, err} <= 3'b100; NS <= S1; end
if (i1 && ~ i2) begin {o1, o2, err} <= 3'b111; NS <= ERROR; end
end
S1: begin
if (~ i2) begin (o1, o2, err) <= 3'b100; NS <= S1; end
if (i2 && i1) begin {o1, o2, err} <= 3'b010; NS <= S2; end
if (i2 && (~ i1)) begin (o1, o2, err) <= 3'b111; NS <= ERROR; end
end
S2: begin
if (i2) begin {o1, o2, err} <= 3'b010; NS <= S2; end
if (~ i2 && i1) begin {o1, o2, err} <= 3'b000; NS <= IDLE; end
if (~ i2 && (~ i1)) begin (o1, o2, err) <= 3'b111; NS <= ERROR; end
end
ERROR: begin
if (i1) begin {o1, o2, err} <= 3'b111; NS <= ERROR; end
if (~ i1) begin (o1, o2, err) <= 3'b000; NS <= IDLE; end
end
default: begin {o1, o2, err} <= 3'b000; NS <= IDLE; end
endcase
end
endmodule
// Two-stage state machine description method (recommended writing)
// In order to make the FSM description clear and easy to maintain, it is easy to attach timing constraints, making the synthesizer and place and route more
// Good optimization design, two-stage FSM description method is recommended.
// The two-part description code for this example is as follows:
// 2-paragraph method to describe FSM
// Describe sequential state transition in 1 sequential always block
// State transition conditions in the other combinational always block
// Package state output by task. Then register the output
module state2 (nrst, clk, i1, i2, o1, o2, err);
input nrst, clk;
input i1, i2;
output o1, o2, err;
reg o1, o2, err;
reg [2: 0] NS, CS;
parameter [2: 0] // one hot with zero idle
IDLE = 3'b000,
S1 = 3’b001,
S2 = 3’b010,
ERROR = 3’b100;
always @ (posedge clk or negedge nrst) // sequential state transition
if (! nrst)
CS <= IDLE;
else
CS <= NS;
always @ (CS or i1 or i2) // combinational condition judgment
begin
NS = 3'bx;
ERROR_out;
case (CS)
IDLE: begin
IDLE_out;
if (~ i1) NS = IDLE;
if (i1 && i2) NS = S1;
if (i1 && ~ i2) NS = ERROR;
end
S1: begin
S1_out;
if (~ i2) NS = S1;
if (i2 && i1) NS = S2;
if (i2 && (~ i1)) NS = ERROR;
end
S2: begin
S2_out;
if (i2) NS = S2;
if (~ i2 && i1) NS = IDLE;
if (~ i2 && (~ i1)) NS = ERROR;
end
ERROR: begin
ERROR_out;
if (i1) NS = ERROR;
if (~ i1) NS = IDLE;
end
default: begin
IDLE_out;
NS = IDLE;
end
endcase
end
task IDLE_out;
{o1, o2, err} = 3'b000; // output task
endtask
task S1_out;
{o1, o2, err} = 3'b100;
endtask
task S2_out;
{o1, o2, err} = 3'b010;
endtask
task ERROR_out;
{o1, o2, err} = 3'b111;
endtask
endmodule
// The three-segment description code for this example is as follows:
// 3-paragraph method to describe FSM
// Describe sequential state transition in the 1st sequential always block
// State transition conditions in the 2nd combinational always block
// Describe the FSM out in the 3rd sequential always block
module state3 (nrst, clk, i1, i2, o1, o2, err);
input nrst, clk;
input i1, i2;
output o1, o2, err;
reg o1, o2, err;
reg [2: 0] NS, CS;
parameter [2: 0] // one hot with zero idle
IDLE = 3'b000,
S1 = 3'b001,
S2 = 3'b010,
ERROR = 3'b100;
always @ (posedge clk or negedge nrst) // 1st always block, sequential state transition
if (! nrst)
CS <= IDLE;
else
CS <= NS;
always @ (nrst or CS or i1 or i2) // 2nd always block, combinational condition judgment
begin
NS = 3'bx;
case (CS)
IDLE: begin
if (~ i1) NS = IDLE;
if (i1 && i2) NS = S1;
if (i1 && ~ i2) NS = ERROR;
end
S1: begin
if (~ i2) NS = S1;
if (i2 && i1) NS = S2;
if (i2 && (~ i1)) NS = ERROR;
end
S2: begin
if (i2) NS = S2;
if (~ i2 && i1) NS = IDLE;
if (~ i2 && (~ i1)) NS = ERROR;
end
ERROR: begin
if (i1) NS = ERROR;
if (~ i1) NS = IDLE;
end
default: NS = IDLE;
endcase
end
always @ (posedge clk or negedge nrst) // 3rd always block, the sequential FSM output
if (! nrst)
{o1, o2, err} <= 3'b000;
else
begin
{o1, o2, err} <= 3'b000;
case (NS)
IDLE: {o1, o2, err} <= 3'b000;
S1: {o1, o2, err} <= 3'b100;
S2: {o1, o2, err} <= 3'b010;
ERROR: {o1, o2, err} <= 3'b111;
endcase
end
endmodule