本文簡化所有邏輯重點講解狀態機的框架。
先給幾點小結:
小結1.在原理圖和實際變現上來說,一段式和三段式完全一致,但在代碼量大的情況下三段式代碼更容易維護。
小結2.二段式的輸出由組合邏輯驅動,不僅可能輸出毛刺,而且不利於時許約束、分析。
小結3.狀態機有着流水線的“缺點”:上電之初若不全面指定初始狀態,則可能有若干個時鐘的無效輸出。
狀態機一般有3個基本組成要素:
要素1.新狀態
要素2.當前狀態
要素3.輸出
當每個clk到來,要完成3個任務:
任務1.將“新狀態”賦給“當前狀態”
任務2.產生下一個“新狀態”(可能包含組合邏輯)
任務3.根據“當前狀態”產生輸出(可能包含組合邏輯)
以下分別給出三種狀態機的框架代碼、原理圖、仿真激勵代碼和仿真波形圖
一段式:
形式上,丟掉“新狀態”這個媒介,直接把新狀態的值賦給“當前狀態”,故沒有任務2。
形式上,在一個觸發器裏完成任務1、3,但實際上這需要2個觸發器,因爲1個觸發器只有一組輸出/輸入。
module one_state_machine(
input clk,
input rest_n,
output out
);
reg out,current_state,next_state;
always@(posedge clk or negedge rest_n) //״̬תӆ
begin
if(!rest_n)
begin out <= 1'd0;current_state <= 1'b0; end
else
case(current_state)
1'b0: begin out <= 1'b1;current_state <= 1'b1; end
1'b1: begin out <= 1'b0;current_state <= 1'b0; end
default:begin out <= 1'b0;current_state <= 1'b1; end
endcase
end
endmodule
二段式:
用1個觸發器完成任務1,用一個組合邏輯完成任務2、3。最後的輸出由組合邏輯驅動,可能會產生毛刺,不利於時序分析和優化。
module two_state_machine(
input clk,
input rest_n,
output out
);
reg out,current_state,next_state;
always@(posedge clk or negedge rest_n) //״̬תӆ
begin
if(!rest_n)
current_state<=1'b0;
else
current_state<=next_state;
end
always@(*)
begin
case(current_state)
1'b0: begin out = 1'd1; next_state = 1'b1; end
1'b1: begin out = 1'd0; next_state = 1'b0; end
default:begin out = 1'd0; next_state = 1'b1; end
endcase
end
endmodule
三段式:
一個觸發器完成任務1,一個組合邏輯完成任務2,一個觸發器完成任務3
module three_state_machine(
input clk,
input rest_n,
output out
);
reg out,current_state,next_state;
always@(posedge clk or negedge rest_n)
begin
if(!rest_n)
current_state<=1'b0;
else
current_state<=next_state;
end
always @ (current_state)
begin
case(current_state)
1'b0: next_state = 1'b1;
1'b1: next_state = 1'b0;
default:next_state = 1'b1;
endcase
end
always@(posedge clk or negedge rest_n)
begin
if(!rest_n)
out <= 1'd0;
else
case(current_state)
1'b0: out <= 1'd1;
1'b1: out <= 1'd0;
default:out <= 1'd0;
endcase
end
endmodule
仿真激勵代碼:
`timescale 1ns / 1ps
module testbench_one_state_machine;
reg clk,rest_n;
wire out;
one_state_machine U0 (
.clk(clk),
.rest_n(rest_n),
.out(out)
);
initial
begin// this process block specifies the stimulus.
rest_n = 0;
#50
rest_n = 1;
end
initial begin
clk = 0;
forever #10 clk = ~clk;
end
endmodule
本文邏輯簡單,三種狀態機波形幾乎一致。