1.狀態機適合描述有前後順序有邏輯規律的事情。好比本文最後的紅綠燈,飲料機的題目。異步
2.存儲器加上組合電路能夠描述任何複雜的電路功能,但常常會有輸入相同而歷史輸入不一樣致使的輸出不一樣的狀況,在數字邏輯中引入fsm,fsm將任意模型簡化爲:將要輸出的結果是當前狀態以及當前輸入的組合。ide
3.有限狀態機設計4大部分 :狀態機編碼 狀態機復位 狀態機條件轉換 狀態機的輸出。函數
4.採用gary碼減小相鄰狀態瞬變的次數,採用one_hot碼能夠減小組合邏輯的使用。編碼
5.狀態機復位:設計
同步復位: 指復位要與分頻後的時鐘信號同步,觸發信號僅爲分頻後的時鐘信號。blog
異步復位: 指復位與分頻後的時鐘信號都參與觸發。接口
歸根結底是觸發復位函數的敏感列表中是否把復位鍵信號做爲觸發信號。進程
6.狀態機的跳轉:狀態機核心部分控制狀態機在狀態間的切換從而決定輸出的狀況。input
7. moore只和當前狀態有關,mealy型輸出與輸入有關(不只與當前狀態有關)。同步
二.三段式寫法舉例
三段式:
一:always模塊採用同步時序描述狀態轉移。
二:always模塊採用組合邏輯判斷狀態轉移條件,描述狀態轉移規律。
三:always模塊描述每一個狀態的輸出。(這裏應該是能夠使用同步時序寄存或者說用組合邏輯,使用同步時序的話應該能夠減小毛刺)
例1:
module fsm(
input clk,
input rst_n,
input in1,
input in2,
input in3,
output reg out1,
output reg out2,
output reg out3
);
reg [3:0]state;
reg next_state;
parameter state0 = 4'b0001,state1 = 4'b0010,state2 = 4'b0100,state3 = 4'b1000;
//第一段 更新狀態寄存器
if(!rst_n)
state <= state0;
else
state <= next_state;
//第二段 組合邏輯電路用於狀態轉移規律
//根據當前狀態和輸入確認下一個週期的狀態
always@(state or in1 or in2 or in3)
case(state)
state0:if(in1)
next_state <= state1;
else
next_state <= state0;
state1: next_state <= state2;
state2: if(in2)
next_state <= state3;
else
next_state <= state0;
state3: if(in3)
next_state <= state0;
else
next_state <= state3;
default:
next_state <= state0;
endcase
//第三段 利用狀態寄存器輸出控制結果
always@(state)
begin //先產生默認值 後邊再改寫 防止寄存器產生
{out1,out2,out3} = 3'b000;
case(state)
state1:{out1,out2,out3} = 3'b100;
state2:{out1,out2,out3} = 3'b110;
state3:{out1,out2,out3} = 3'b111;
endcase
end
endmodule
例2:
圖畫的潦草了一點…
//功能簡介:初始狀態s0下輸出3'b001,若是收到start信號爲1,進入s1;若是start爲0,保持。s1輸出一個週期的3'b010再到s2狀態,s2輸出3’b100等待step2爲1轉移到s3,不然維持。state3和state2相似。
module fsm(
input clk,
input rst_n,
input start,
input step2,
input step3,
output reg [2:0]fsm_out
);
localparam state0 = 2'b00;
localparam state1 = 2'b01;
localparam state2 = 2'b11;
localparam state3 = 2'b10;
//標準三段式 每一個週期開始時更新當前狀態
reg [1:0] state;
reg [1:0]next_state;
always@(posedge clk or negedge rst_n)
if(!rst_n)
state <= state0;
else
state <= next_state;
//根據當前狀態和輸入確認下一個週期的狀態
always@(state or start or step2 or step3)
begin
case(state)
state0:
begin
if(start)
next_state <= state1;
else
next_state <= state0;
end
state1:
begin
next_state <= state2;
end
state2:
begin
if(step2)
next_state <= state3;
else
next_state <= state2;
end
state3:
begin
if(step3)
next_state <= state0;
else
next_state <= state3;
end
default: next_state <= state0;
endcase
end
//該進程定義fsm的輸出
always@(state)
case(state)
state0:fsm_out = 3'b001;
state1:fsm_out = 3'b010;
state2:fsm_out = 3'b100;
state3:fsm_out = 3'b111;
default:fsm_out = 3'b001;//default能夠避免鎖存器
endcase
endmodule
例3:
//輸入信號clk,復位rst_n,共四個狀態idel,s1,s2,error
//ns 下一個狀態 cs 當前狀態
module state(
input clk;
input rst_n;
input i1,i2;
output reg o1,o2,err
);
reg [2:0]ns,cs;
parameter[2:0]//one hot
IDLE = 3'b000,
S1 = 3'b001,
S2 = 3'b010,
ERROR= 3'b100;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cs <= IDLE;
else
cs <= ns;
always@(rst_n or cs or i1 or i2)
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(!i1) ns <= S1;
if(!i1&&i2) ns <= ERROR;
if(i1&&i2) ns <= S2;
end
S2:
begin
if(i2) ns <= S2;
if(!i1&&!i2) ns <= ERROR;
if(i1&&!i2) ns <= IDLE;
end
ERROR:
begin
if(i1) ns <= ERROR;
if(!i1) ns <= IDLE;
end
endcase
end
always@(posedge clk or negedge rst_n)
if(!rst_n)
{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
例1:一個簡單的紅綠燈問題
module rgy
(
input clk,
input rst_n,
input [2:0]cnt,
output reg LED_R_1,
output reg LED_G_1,
output reg LED_Y_1,
output reg LED_R_2,
output reg LED_G_2,
output reg LED_Y_2
);
parameter IDLE = 0, WE_GO = 1,WE_WAIT = 2,NS_GO = 3,NS_WAIT = 4;
reg[3:0] state;
reg[3:0] next_state;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
state <= IDLE;
else
state <= next_state;
end
always@(state or cnt or rst_n)
begin
case(state)
IDLE:begin
next_state = WE_GO;
end
WE_GO:begin
if(cnt == 3)
next_state = WE_WAIT;
else
next_state = WE_GO;
end
WE_WAIT:begin
if(cnt == 0)
next_state = NS_GO;
else
next_state = WE_WAIT;
end
NS_GO:begin
if(cnt == 3)
next_state = NS_WAIT;
else
next_state = NS_GO;
end
NS_WAIT:begin
if(cnt == 0)
next_state = WE_GO;
else
next_state = NS_WAIT;
end
endcase
end
always@(posedge clk or negedge rst_n) //WE東西方向
begin
if(!rst_n)
begin
LED_R_1 <= 1;
LED_G_1 <= 0;
LED_Y_1 <= 0;
end
else case(next_state)
IDLE:begin
LED_R_1 <= 1;//紅
LED_G_1 <= 0;//綠
LED_Y_1 <= 0;//黃
end
WE_GO:begin
LED_R_1 <= 0;
LED_G_1 <= 1;
LED_Y_1 <= 0;
end
WE_WAIT:begin
LED_R_1 <= 0;
LED_G_1 <= 0;
LED_Y_1 <= 1;
end
NS_GO:begin
LED_R_1 <= 1;
LED_G_1 <= 0;
LED_Y_1 <= 0;
end
NS_WAIT:begin
LED_R_1 <= 1;
LED_G_1 <= 0;
LED_Y_1 <= 0;
end
endcase
end
always@(posedge clk or negedge rst_n) //NS
begin
if(!rst_n)
begin
LED_R_2 <= 1;
LED_G_2 <= 0;
LED_Y_2 <= 0;
end
else case(next_state)
IDLE:begin
LED_R_2 <= 1;
LED_G_2 <= 0;
LED_Y_2 <= 0;
end
WE_GO:begin
LED_R_2 <= 1;
LED_G_2 <= 0;
LED_Y_2 <= 0;
end
WE_WAIT:begin
LED_R_2 <= 1;
LED_G_2 <= 0;
LED_Y_2 <= 0;
end
NS_GO:begin
LED_R_2 <= 0;
LED_G_2 <= 1;
LED_Y_2 <= 0;
end
NS_WAIT:begin
LED_R_2 <= 0;
LED_G_2 <= 0;
LED_Y_2 <= 1;
end
endcase
end
endmodule
有點晚了 後邊我會把 飲料機的題目從新開一帖子,飲料機內容比較多而且板級驗證複習一下按鍵消抖的模塊。