FPGA基礎——旅鼠遊戲(FSM)

FSM(Finite State Machine)異步

分爲2大類:ui

第一類,若輸出只和狀態有關而與輸入無關,則稱爲Moore狀態機spa

第二類,輸出不只和狀態有關並且和輸入有關係,則稱爲Mealy狀態機3d

Mealy狀態機,常採用一段式寫法,只用了一個always語句,全部的狀態轉移,判斷狀態轉移條件,數據輸出都在一個always語句裏,缺點是若是狀態太多,會使整段程序顯的冗長。code

Moore狀態機,常採用三段式的寫法,狀態轉移用了一個always語句,判斷狀態轉移條件是組合邏輯always @(*),採用了一個always語句,數據輸出也是單獨的 always語句,這樣寫起來比較直觀清晰,狀態不少時也不會顯得繁瑣。blog


1. 旅鼠遊戲介紹遊戲

  在《旅鼠》這款遊戲中,小動物的大腦至關簡單。簡單到咱們要用一個有限狀態機來創建模型。在《旅鼠》的2D世界中,旅鼠可能會處於兩種狀態之一:向左走或向右走。若是碰到障礙物,它會改變方向。特別是,若是一隻旅鼠被撞到左邊,它就會向右走。若是它在右邊被撞到,它就會向左走。若是它同時在兩邊碰撞,它仍然會改變方向。ci

                                                    

 

 

  實現一個Moore狀態機,它有兩個狀態、兩個輸入和一個輸出來模擬這種行爲。input

 

 1 module top_module (  2     input clk,  3     input areset,    //異步復位  4     input bump_left,    5     input bump_right,  6     output walk_left,  7     output walk_right  8 );  9 
10     
11 // 狀態參數設置,常見:二進制碼、格雷碼、獨熱碼、BCD碼 12 parameter WL=0, WR=1; 13 reg state;  //當前狀態 14 reg next;   //下個狀態  15 16 17 // Combinational always block for state transition logic. Given the current state and inputs, 18 // what should be next state be? 19 // Combinational always block: Use blocking assignments. 20 always@(*) begin 21 case (state) 22 WL: next = bump_left ? WR : WL; 23 WR: next = bump_right ? WL : WR; 24 endcase 25 end 26 27 28 // Combinational always block for state transition logic. Given the current state and inputs, 29 // what should be next state be? 30 // Combinational always block: Use blocking assignments. 31 always @(posedge clk, posedge areset) begin 32 if (areset) state <= WL; 33 else state <= next; 34 end 35 36 37 // 輸出組合邏輯。 38 // In more complex circuits, a combinational always block may be more suitable. 39 assign walk_left = (state==WL); 40 assign walk_right = (state==WR); 41 42 43 endmodule

 2.旅鼠遊戲補充it

除了左右行走,旅鼠還會在地面消失時摔倒(可能會發出「啊!」的聲音)。除了左右行走和顛簸時改變方向外,當地面=0時,旅鼠還會摔倒並說「啊!」當地面從新出現(地面=1)時,旅鼠會繼續沿著墜落前的方向行走。摔倒時被撞不會影響行走方向,在地面消失(但尚未摔倒)的同一週期內被撞,或摔倒時地面從新出現,也不會影響行走危難。

 

 

除了行走和跌倒,有時候還會讓旅鼠作一些有用的事情,好比挖(當挖=1時它就開始挖了)。若是旅鼠正在地面上行走(地面=1而且沒有掉下來),它能夠繼續挖掘,直到它到達另外一邊(地面=0)。在這一點上,由於沒有地面,它會掉下來(啊!),而後在它再次撞擊地面時繼續朝原來的方向走。就像摔倒同樣,在挖的時候被撞到是沒有影響的,在摔倒或沒有地面的時候被告知挖也被忽略了。

 

 

 

 

雖然旅鼠能夠走路、摔倒和挖洞,但旅鼠並不是無懈可擊。若是旅鼠跌倒的時間過長就會撞到地面,它可能會GG。特別是,若是旅鼠跌倒超過20個時鐘週期,而後擊中地面,它將GG和中止行走,掉落,或挖掘(全部4個輸出變成0),永遠(或直到FSM重置)。旅鼠在落地前墜落的距離沒有上限。旅鼠只有在撞擊地面時纔會GG;它們不會在半空中GG。

                                                    

 

 

 1 module top_module(  2     input clk,  3     input areset,    // Freshly brainwashed Lemmings walk left.
 4     input bump_left,  5     input bump_right,  6     input ground,  7     input dig,  8     output walk_left,  9     output walk_right, 10     output aaah, 11     output digging ); 12     parameter LEFT = 4'd0, RIGHT = 4'd1, FALL_L = 4'd2, FALL_R = 4'd3; 13     parameter DIG_L = 4'd4, DIG_R = 4'd5, DYING = 4'd6, SPLAT = 4'd7; 14     reg    [3:0] current_state; 15     reg [3:0] next_state; 16     reg cnt_start; 17     reg [4:0]cnt_fall; 18     
19     always@(posedge clk or posedge areset)begin
20         if(areset)begin
21             current_state <= LEFT; 22         end
23         else begin
24             current_state <= next_state; 25         end
26     end
27     
28     always@(*)begin
29         case(current_state) 30             LEFT:begin
31                 next_state = ground ? (dig ? DIG_L : (bump_left ? RIGHT : LEFT)) : FALL_L; 32             end
33             RIGHT:begin
34                 next_state = ground ? (dig ? DIG_R : (bump_right ? LEFT : RIGHT)) : FALL_R; 35             end
36             FALL_L:begin
37                 next_state = ground ? LEFT : ((cnt_fall==5'd20)?DYING:FALL_L);
38             end
39             FALL_R:begin
40                 next_state = ground ? RIGHT : ((cnt_fall==5'd20)?DYING:FALL_R);
41             end
42             DIG_L:begin
43                 next_state = ground ? DIG_L : FALL_L; 44             end
45             DIG_R:begin
46                 next_state = ground ? DIG_R : FALL_R; 47             end
48             DYING:begin
49                 next_state = ground ? SPLAT : DYING; 50             end
51             SPLAT:begin
52                 next_state = SPLAT; 53             end
54             default:begin
55                 next_state = LEFT; 56             end
57         endcase
58     end    
59     
60     always@(posedge clk or posedge areset)begin
61         if(areset) 62             cnt_fall <= 0; 63         else if(cnt_start) 64             cnt_fall <= cnt_fall+1'b1;
65         else
66             cnt_fall <= 0; 67     end
68 
69     assign cnt_start = (next_state==FALL_L) || (next_state==FALL_R); 70     
71     assign walk_left = (current_state == LEFT); 72     assign walk_right = (current_state == RIGHT); 73     assign digging = (current_state == DIG_L || current_state == DIG_R); 74     assign aaah = (current_state == FALL_L || current_state == FALL_R || current_state == DYING); 75 
76 endmodule
相關文章
相關標籤/搜索