状态机在FPGA的设计中是至关重要的,使用的频率也很高,废话不多说在这里介绍一下三段式状态机如何设计。
设计状态机首先要清楚状态有几种,状态转移图是怎样的,各个状态的输出是怎样的。了解了这三样之后就可以开始设计实验所需要的状态机。
三段式状态机的设计步骤为:
- State Tranfer Logic 状态传输逻辑
- State Transfer Block 状态传输块
- State Output 状态输出
本次以数字时钟中的时间设置模块为模板来讲解状态机是如何产生的。 本次的状态转移图为:
状态转移条件为:
状态传输逻辑设计:这一步的设计主要是设定好各个状态之间的传输条件,即在哪种激励有效时状态发生变化。
parameter HC=4'b0001, MC=4'b0010, SC=4'b0100, TD=4'b1000; // i.e. Hour Change, Minute Change, Second Change, Time set Donereg [3:0] state,next_state;//设计思路,1、状态转换条件 2、状态传输3、状态输出//State Tranfer Logic (phase 1)状态传输逻辑always @(ok_press) begincase(state) HC: beginif(ok_press) next_state = MC;else next_state = HC;endMC: beginif(ok_press) next_state = SC;else next_state = MC;endSC: beginif(ok_press) next_state = TD;else next_state = SC;endTD: beginnext_state = HC; enddefault:state=HC;endcaseend
状态传输块:这部分的设定更新目前状态的值。
always @(posedge i_clk_5MHz) beginif((~i_rstn)||(~i_ena))state <= HC; //初始状态 复位端低有效else state <= next_state; end
状态输出:这部分设置好各个状态下的输出。
// State Output (phase 3) 状态输出always @(posedge i_clk_5MHz) begin// in default we disable and reset all counter 在默认情况下我们禁用并重置所有计数器if(~i_rstn)begino_set_done <= 0;set_hour <= 0;set_min <= 0;set_sec <= 0; // show a bar on LCD displayendcase(state)HC: begino_set_done<=0;if(up_press) beginset_hour <= (set_hour>=5'd23) ? 0 : set_hour+1;endelse beginset_hour <= set_hour;endendMC: beginif(up_press) beginset_min <= (set_min>=6'd59) ? 0 : set_min+1;endelse beginset_min <= set_min;endendSC: beginif(up_press) beginset_sec <= (set_sec>=6'd59) ? 0 : set_sec+1;endelse beginset_sec <= set_sec;endendTD: begino_set_done<=1;enddefault:state<=HC;endcaseend
在实验中用到了case语句,需要说明的是在实验中我们使用的是四位的位宽来表示state,我们的状态有四种,所以在实验中有多余的case是没有被使用的在这种情况下我们需要加入default语句来说明在其他的case条件下我们的state是怎样的。