欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章
状态机是fpga设计中极其重要的一种技巧,状态机通过不同的状态迁移来完成特定的逻辑操作,掌握状态机的写法可以使fpga的开发事半功倍。
状态机的分类
Moore型状态机:状态机的变化只与当前的状态有关
Mealy型状态机:状态机的变化不仅与当前的状态有关,还与输入有关
如何创建状态机
状态机的创建可以分为一段式,两段式和三段式
一段式:主要是讲所有的状态变化以及导致的输出变化都写在了一个always模块中。
两段式:一个always模块采用同步时序描述状态转移;另一个always模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出。
三段式:一个always模块采用同步时序描述状态转移;一个always模块采用组合逻辑判断状态转移条件,描述状态转移规律;另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。
举个例子:从循环输入的字母中做连续检测,当连续检测到“hello”时,将led灯进行状态的翻转,继续进行下一次的检测。
一段式的编写方式:
1 module hello( 2 input clk,//系统时钟信号 50mHz 3 input rst_n,//系统复位信号,低电平有效 4 input [7:0] data,//连续输入的字母 5 output reg led//led灯 6 ); 7 8 //设置需要改变的状态 9 parameter checkh = 5'b0000_1, 10 checke = 5'b0001_0, 11 checkla = 5'b0010_0, 12 checklb = 5'b0100_0, 13 checko = 5'b1000_0; 14 15 reg [4:0]state; 16 17 always @(posedge clk or negedge rst_n) 18 if(!rst_n) 19 begin 20 led <= 1'b0; 21 state <= checkh; 22 end 23 else 24 begin 25 case (state) 26 checkh: 27 if(data == "h") state <= checke; 28 else state <= checkh; 29 checke: 30 if(data == "e") state <= checkla; 31 else state <= checkh; 32 checkla: 33 if(data == "l") state <= checklb; 34 else state <= checkh; 35 checklb: 36 if(data == "l") state <= checko; 37 else state <= checkh; 38 checko: 39 if(data == "o") 40 begin 41 led <= ~led; 42 state <= checkh; 43 end 44 else state <= checkh; 45 default:state <= checkh; 46 endcase 47 end 48 49 endmodule
二段式的编写方式:
1 module hello( 2 input clk, 3 input rst_n, 4 input [7:0] data, 5 output reg led 6 ); 7 8 parameter checkh = 5'b0000_1, 9 checke = 5'b0001_0, 10 checkla = 5'b0010_0, 11 checklb = 5'b0100_0, 12 checko = 5'b1000_0; 13 14 reg [4:0] cstate; // 当前状态 15 reg [4:0] nstate; // 下一状态 16 17 always @(posedge clk or negedge rst_n) 18 if(!rst_n) 19 cstate <= checkh; 20 else 21 cstate <= nstate; 22 23 always @(cstate or data) 24 case (cstate) 25 checkh: 26 if(data == "h") nstate <= checke; 27 else nstate <= checkh; 28 checke: 29 if(data == "e") nstate <= checkla; 30 else nstate <= checkh; 31 checkla: 32 if(data == "l") nstate <= checklb; 33 else nstate <= checkh; 34 checklb: 35 if(data == "l") nstate <= checko; 36 else nstate <= checkh; 37 checko: 38 if(data == "o") 39 begin 40 led <= ~led; 41 nstate <= checkh; 42 end 43 else nstate <= checkh; 44 default:nstate <= checkh; 45 endcase 46 47 endmodule
三段式的编写方式:
1 module hello( 2 input clk, 3 input rst_n, 4 input [7:0] data, 5 output reg led 6 ); 7 8 parameter checkh = 5'b0000_1, 9 checke = 5'b0001_0, 10 checkla = 5'b0010_0, 11 checklb = 5'b0100_0, 12 checko = 5'b1000_0; 13 14 reg [4:0] cstate; // 当前状态 15 reg [4:0] nstate; // 下一状态 16 17 //复位信号,clk的处理(主要是对初始状态进行赋值操作) 18 always @(posedge clk or negedge rst_n) 19 if(!rst_n) 20 cstate <= checkh; 21 else 22 cstate <= nstate; 23 24 //状态迁移的处理 25 always @(cstate or data) 26 case (cstate) 27 checkh: 28 if(data == "h") nstate <= checke; 29 else nstate <= checkh; 30 checke: 31 if(data == "e") nstate <= checkla; 32 else nstate <= checkh; 33 checkla: 34 if(data == "l") nstate <= checklb; 35 else nstate <= checkh; 36 checklb: 37 if(data == "l") nstate <= checko; 38 else nstate <= checkh; 39 checko: 40 if(data == "o") 41 begin 42 nstate <= checkh; 43 end 44 else nstate <= checkh; 45 default:nstate <= checkh; 46 endcase 47 48 //输出数据的处理 49 always @(posedge clk or negedge rst_n) 50 if(!rst_n) 51 led <= 1'b1; 52 53 else 54 case (cstate) 55 checko: 56 if(data == "o") 57 led <= ~led; 58 default; 59 endcase 60 61 endmodule