FPGA學(xué)習(xí)筆記-三段式狀態(tài)機(jī)
????????類似多分支語句,更自由一些可以自定義多個(gè)分支的跳轉(zhuǎn)條件和每個(gè)分支下的行為,每一個(gè)分支叫做一個(gè)狀態(tài)。
????????狀態(tài)機(jī)四要素:現(xiàn)態(tài),次態(tài),條件,動(dòng)作。
????????優(yōu):方便糾錯(cuò),邏輯清晰。????????????????缺:費(fèi)時(shí)序邏輯資源。
通用格式
? ? ? ? 由三個(gè)always語句構(gòu)成,一般第一段和第三段為時(shí)序邏輯,第二段為組合邏輯。
????????第一段為定義當(dāng)前狀態(tài)到下一個(gè)狀態(tài)的轉(zhuǎn)換。(現(xiàn)態(tài)與次態(tài)的狀態(tài)切換)
????????第二段描述狀態(tài)轉(zhuǎn)換的條件。(根據(jù)現(xiàn)態(tài)和條件確定次態(tài))
????????第三段表現(xiàn)當(dāng)前狀態(tài)下的行為。(根據(jù)現(xiàn)態(tài)和條件確定每個(gè)狀態(tài)的動(dòng)作)
狀態(tài)轉(zhuǎn)換圖
????????寫狀態(tài)機(jī)之前最好提前決定好需要多少個(gè)狀態(tài),每個(gè)狀態(tài)之間切換的條件是什么理清思路再寫。

????????例如讓4個(gè)led燈每隔1s切換一個(gè)亮,就需要一個(gè)空閑態(tài)加上4個(gè)led燈分別亮的4個(gè)狀態(tài)一共5個(gè)狀態(tài)。(并不是一定要按照順序切換狀態(tài)也不是一定要有空閑態(tài),根據(jù)實(shí)際情況來)
狀態(tài)編碼
二進(jìn)制編碼:節(jié)省位寬。(十進(jìn)制的0,1,2,3)
例如:2'd0 2'd1 2'd2 2'd3?
獨(dú)熱碼:簡(jiǎn)單,譯碼快。(每個(gè)狀態(tài)一個(gè)高電平)
例如:4'b0001? 4'b0010? 4'b0100? 4'b1000
格雷碼:減少競(jìng)爭(zhēng)冒險(xiǎn)的概率。(相鄰狀態(tài)之間僅有一位變化)
例如:3'b000? 3'b001??3'b011? 3'b111? 3'b110? 3'b100? 3'b101?
競(jìng)爭(zhēng)冒險(xiǎn)
????????競(jìng)爭(zhēng):在同一個(gè)邏輯門中,有兩路相反的信號(hào)到達(dá)目標(biāo)門的時(shí)間有先有后導(dǎo)致在時(shí)間上產(chǎn)生的差異現(xiàn)象。
????????冒險(xiǎn):由競(jìng)爭(zhēng)產(chǎn)生的尖峰脈沖的現(xiàn)象。
解決辦法:并聯(lián)濾波電容(通交流,阻直流) 接入選通脈沖(使能信號(hào)) 修改邏輯設(shè)計(jì)(增加冗余項(xiàng))三種辦法。

//狀態(tài)機(jī)實(shí)現(xiàn)流水燈
`timescale 1ns / 1ps
module biji_1(
? ? input sysclk,
? ? input rst_n,
? ? output reg [3:0]led
? ? );
? ??
localparam idle=3'd0;//狀態(tài)編碼
localparam s1=3'd1;? //狀態(tài)編碼
localparam s2=3'd2;? //狀態(tài)編碼
localparam s3=3'd3;? //狀態(tài)編碼
localparam s4=3'd4;? //狀態(tài)編碼
reg [3:0] cur_state;//當(dāng)前狀態(tài)
reg [3:0] next_state;//下一個(gè)狀態(tài)
localparam delay=50_000_000;//1s
reg [31:0] cnt;//計(jì)時(shí)器
always@(posedge sysclk)//1s計(jì)時(shí)器
? ? if (!rst_n)
? ? ? ? cnt<=0;
? ? else if (cnt == delay-1)
? ? ? ? cnt<=0;
? ? else
? ? ? ? cnt<=cnt+1;
always@(posedge sysclk)//一段
? ? if (!rst_n)
? ? ? ? cur_state<=idle;
? ? else
? ? ? ? cur_state<=next_state;
always@(*)//二段
? ? if (!rst_n)
? ? ? ? next_state=idle;
? ? else
? ? ? ? case(cur_state)
? ? ? ? ? ? idle:begin
? ? ? ? ? ? ? ? if (cnt == delay-1)//條件
? ? ? ? ? ? ? ? ? ? next_state=s1;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? next_state=idle;
? ? ? ? ? ? end
? ? ? ? ? ? s1:begin
? ? ? ? ? ? ? ? if (cnt == delay-1)
? ? ? ? ? ? ? ? ? ? next_state=s2;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? next_state=s1;
? ? ? ? ? ? end??
? ? ? ? ? ? s2:begin
? ? ? ? ? ? ? ? if (cnt == delay-1)
? ? ? ? ? ? ? ? ? ? next_state=s3;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? next_state=s2;
? ? ? ? ? ? end
? ? ? ? ? ? s3:begin
? ? ? ? ? ? ? ? if (cnt == delay-1)
? ? ? ? ? ? ? ? ? ? next_state=s4;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? next_state=s3;
? ? ? ? ? ? end
? ? ? ? ? ? s4:begin
? ? ? ? ? ? ? ? if (cnt == delay-1)
? ? ? ? ? ? ? ? ? ? next_state=s1;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? next_state=s4;
? ? ? ? ? ? end
? ? ? ? default next_state=idle;
? ? ? ? endcase
always@(posedge sysclk)
? ? if (!rst_n)
? ? ? ? led<=4'b0000;
? ? else
? ? ? ? case(cur_state)
? ? ? ? ? ? idle:led<=4'b0000;
? ? ? ? ? ? s1:led<=4'b1000;
? ? ? ? ? ? s2:led<=4'b0100;
? ? ? ? ? ? s3:led<=4'b0010;
? ? ? ? ? ? s4:led<=4'b0001;
? ? ? ? default led<=4'b0000;
? ? ? ? endcase
endmodule