生活随笔
收集整理的這篇文章主要介紹了
Verilog实现状态机与状态机经典示例——序列检测器、自动饮料售卖机
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文鏈接:https://blog.csdn.net/qq_34070723/article/details/100737225
作者:King阿金
目錄
1.狀態機原理與三段式狀態機
2.狀態機示例
2.1自動飲料售賣機/賣報機
2.2序列檢測器
1.狀態機原理與三段式狀態機
MOORE 與 MEALEY 狀態機的特征?
Moore 狀態機的輸出僅與當前狀態值有關, 且只在時鐘邊沿到來時才會有狀態變化。次態=f(現狀,輸入),輸出=f(現狀)
Mealy 狀態機的輸出不僅與當前狀態值有關, 而且與當前輸入值有關。次態=f(現狀,輸入),輸出=f(現狀,輸入)
描述同一個事務,mealy的狀態更少。
通用mealy三段式狀態機(建議實際工程中采用的結構)
parameter IDLE = ...parameter S0 = ......reg [x:0] curr_state;reg [x:0] next_state; always @(posedge clk or posedge asy_rst)begin if(asy_rst) curr_state <= IDLE ; else curr_state <= next_state; end always @(*)beginnext_state = 'bx; case(curr_state) IDLE: if(輸入) next_state = S0 ;else...; S0: if(輸入) next_state = ...;... default: next_state = ...;endcaseendalways@(posedge clk or posedge asy_rst)begin if(asy_rst)out<= ...; else case(curr_state)sO: if(...) out <= ...;sO: if(...) out <= ...; default: out <= ...;endcaseendalways @(*)begin if(asy_rst)out = ...; else case(curr_state)sO: if(...) out = ...;sO: if(...) out = ...; default: out = ...;endcaseend
2.狀態機示例
2.1自動飲料售賣機/賣報機
題目:商品是5分錢,只能投3種硬幣:1分,2分,5分,考慮找零。
思路1:采用狀態機,共分為5個狀態,S0-S4代表已經投入的錢,畫出狀態轉換圖(略),采用三段式mealy狀態機。
思路2:(更簡單)不采用狀態機,直接對輸入的錢進行加法運算,多余5分就輸出和找零,同時將內部加法器清零。
另一個版本:用Verilog實現接受0.5元,1元的可樂售賣機,單價2.5元,考慮找零和出貨。
module auto_sell_betterparameter I_WD = 4 , O_WD = 4)(input clk,input asy_rst,input [I_WD-1:0] i_dat,input i_val, output reg [O_WD-1:0] o_money,output reg o_goods ); parameter S0=4'b0000; parameter S1=4'b0001; parameter S2=4'b0010; parameter S3=4'b0100; parameter S4=4'b1000; //4分錢reg [3:0] curr_s;reg [3:0] next_s;//每個時鐘只產生一次狀態變化always @(posedge clk or posedge asy_rst)begin if(asy_rst) curr_s <= S0; else curr_s <= next_s; end//產生的下一狀態的組合邏輯always @(*)beginnext_s = 'dx;case(curr_s)S0: if(i_dat == 1) next_s = S1; else if(i_dat == 2) next_s = S2; else if(i_dat == 5) next_s = S0; else next_s = S0;S1: if(i_dat == 1) next_s = S2; else if(i_dat == 2) next_s = S3; else if(i_dat == 5) next_s = S0; else next_s = S1;S2: if(i_dat == 1) next_s = S3; else if(i_dat == 2) next_s = S4; else if(i_dat == 5) next_s = S0; else next_s = S2; S3: if(i_dat == 1) next_s = S4; else if(i_dat == 2) next_s = S0; else if(i_dat == 5) next_s = S0; else next_s = S3; S4: if(i_dat == 1) next_s = S0; else if(i_dat == 2) next_s = S0; else if(i_dat == 5) next_s = S0; else next_s = S4; default: next_s = S0;endcaseendalways @(posedge clk or posedge asy_rst)begin if(asy_rst)begino_money <= 0;o_goods <= 0;end else case(curr_s)S0:begino_money <= 0; if(i_dat==5) o_goods <= 1; else o_goods <= 0; endS1: begin if(i_dat==5) begin o_money <= 1; o_goods <= 1; end else begin o_money <= 0; o_goods <= 0; endendS2: begin if(i_dat==5) begin o_money <= 2; o_goods <= 1; end else begin o_money <= 0; o_goods <= 0; endendS3: begin if(i_dat==5) begin o_money <= 3; o_goods <= 1; end else if (i_dat==2) begin o_money <= 0; o_goods <= 1; end else begin o_money <= 0; o_goods <= 0; end endS4: begin if(i_dat==5) begin o_money <= 4; o_goods <= 1; end else if (i_dat==2) begin o_money <= 1; o_goods <= 1; end else if (i_dat==1) begin o_money <= 0; o_goods <= 1; end end default :begin o_money <= 0; o_goods <= 0;endendcaseend reg [3:0] add_in;reg [3:0] a_money;reg a_goods;always @(posedge clk or posedge asy_rst)begin if(asy_rst)beginadd_in <= 0;a_money <= 0;a_goods <= 0;end else if(i_val)begin if(add_in+i_dat >=5)beginadd_in <= 0;a_money <= add_in + i_dat - 5;a_goods <= 1;end elsebeginadd_in <= add_in + i_dat;a_money <= 0;a_goods <= 0; endend elsebeginadd_in <= 0;a_money <= 0;a_goods <= 0;endendendmodulemodule auto_sell_sim;parameter CLK_PERIOD = 10; parameter RST_CYCLE = 5; parameter RST_TIME = RST_CYCLE * CLK_PERIOD; reg sim_clk;reg sim_asy_rst; initialbeginsim_clk = 0;sim_asy_rst = 1; end always parameter I_WD = 4;parameter O_WD = 4;reg [I_WD-1:0]sim_dat;reg [I_WD-1:0]sim_i_dat;reg sim_i_val;always@(posedge sim_clk or posedge sim_asy_rst)begin if(sim_asy_rst)beginsim_i_dat <= 0; sim_i_val <= 0;end elsebeginsim_dat <= {$random}%6; if( sim_dat== 1 || sim_dat ==2 || sim_dat==5)beginsim_i_dat <= sim_dat; sim_i_val <= 1;end elsebeginsim_i_dat <= 0; sim_i_val <= 1;endendend wire [O_WD-1:0] o_money;wire o_goods;auto_sell_better auto_sell_better_u( .clk( sim_clk ),.asy_rst( sim_asy_rst ),.i_dat( sim_i_dat ),.i_val( sim_i_val),.o_money(o_money),.o_goods(o_goods));
2.2序列檢測器
筆試題目:如果序列長度為8,需要8個狀態,最少(3)個寄存器進行狀態轉換(mealy)。
?題目:用狀態機實現 101101 的序列檢測。
思路:
畫出mealy狀態轉換圖,并進行化簡[1],灰色表示合并為一個:
?如果采用moore狀態機,其狀態就多了,且輸出比mealy延時一個時鐘參考[1]:
module seq_detect#(parameter I_WD = 1 , O_WD = 1)(input clk,input asy_rst,input [I_WD-1:0] i_dat,input i_val,output reg [O_WD-1:0] o_detect ); parameter S0=6'b000001; parameter S1=6'b000010; parameter S2=6'b000100; parameter S3=6'b001000; parameter S4=6'b010000; parameter S5=6'b100000; reg [5:0] curr_s;reg [5:0] next_s;always @(posedge clk or posedge asy_rst)begin if(asy_rst)curr_s <= S0; elsecurr_s <= next_s; end always @(*)beginnext_s = 'dx;case(curr_s) S0: if(i_dat == 1) next_s = S1; else next_s = S0; S1: if(i_dat == 0) next_s = S2; else next_s = S1; S2: if(i_dat == 1) next_s = S3; else next_s = S0; S3: if(i_dat == 1) next_s = S4; else next_s = S2; S4: if(i_dat == 0) next_s = S5; else next_s = S1; S5: if(i_dat == 1) next_s = S0; else next_s = S0; default: next_s = S0;endcaseend always @(posedge clk or posedge asy_rst)begin if(asy_rst)begino_detect <= 0; end else case(curr_s) S0,S1,S2,S3,S4:begino_detect <= 0; end S5: begin if(i_dat ==1 ) o_detect <= 1; end default :begin o_detect <= 0; endendcaseend endmodulemodule seq_detect_sim;parameter CLK_PERIOD = 10; parameter RST_CYCLE = 5; parameter RST_TIME = RST_CYCLE * CLK_PERIOD; reg sim_clk;reg sim_asy_rst; initialbeginsim_clk = 0;sim_asy_rst = 1;#RST_TIME sim_asy_rst = 0;end always #(CLK_PERIOD/2) sim_clk = ~sim_clk;parameter I_WD = 1;parameter O_WD = 1;parameter IN_SEQ = 32'b00101101_01011000_10110111_01010101; reg [4:0]cnt;reg sim_i_val;always @(posedge sim_clk or posedge sim_asy_rst)begin if(sim_asy_rst)begincnt <= 0;sim_i_val <= 0;end elsebegincnt <= cnt +1;sim_i_val <= 1;endend wire [O_WD-1:0] o_detect;seq_detect seq_detect_u (.clk(sim_clk ),.asy_rst(sim_asy_rst ),.i_dat(IN_SEQ[cnt] ),.i_val(sim_i_val),.o_detect(o_detect));endmodule
參考資料
[1]“101101”序列檢測器Verilog設計實例與VCS仿真(mealy型和moore型)
總結
以上是生活随笔為你收集整理的Verilog实现状态机与状态机经典示例——序列检测器、自动饮料售卖机的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。