1. 二段状态机,三段状态机
刷题过程中发现,对于状态机的掌握并不熟练,按照规范的逻辑去写状态机
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
parameter[3:0] IDLE = 4'd0;
parameter[3:0] S1 = 4'd1;
parameter[3:0] S2 = 4'd2;
parameter[3:0] S3 = 4'd3;
parameter[3:0] S4 = 4'd4;
parameter[3:0] S5 = 4'd5;
parameter[3:0] S6 = 4'd6;
parameter[3:0] S7 = 4'd7;
parameter[3:0] S8 = 4'd8;
reg[3:0] current_state;
reg[3:0] next_state;
//状态跳转逻辑
always @(*) begin
case(current_state)
IDLE: next_state = a? IDLE : S1;
S1 : next_state = a? S2 : S1;
S2 : next_state = a? S3 : S1;
S3 : next_state = a? S4 : S1;
S4 : next_state = a? IDLE : S5;
S5 : next_state = a? S2 : S6;
S6 : next_state = a? S2 : S7;
S7 : next_state = a? S8 : S1;
S8 : next_state = a? S3 : S1;
endcase
end
//状态跳转实现
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
//输出
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
match <= 1'b0;
else if(current_state == S8) begin
match <= 1'b1;
end
else
match <= 1'b0;
end
endmodule
- (1)一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;
- (2)二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;
- (3)三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。
此为牛客第25题的逻辑输出,可见,其状态转移和输出两段状态机用的是时序逻辑,状态跳转的逻辑使用组合逻辑,避免了时序逻辑导致的时间延迟一拍。