例1. 周期跳转状态机
状态机有三个状态,IDLE,S1和S2。在IDLE状态,如果en=1,则跳到S1状态,否则保持不变;在S1状态时,保持5个时钟周期后,跳到S2状态; 在S2状态,保持7个时钟周期后,跳回到IDLE状态。
-
状态转移图
-
状态转移代码
always@(*) begin
case(state_c)
IDLE: begin
if(idle2s1) state_n = S1;
else state_n = state_c;
end
S1: begin
if(s12s2) state_n = S2;
else state_n = state_c;
end
S2: begin
if(s22idle) state_n = IDLE;
else state_n = state_c;
default: state_n = state_c;
endcase
end
assign idle2s1 = state_c==IDLE && en==1;
assign s12s2 = state_c==S1 && end_cnt1;
//assign s12s2 = state_c==S1 && cnt==4;因为add_cnt1=1,所以这两种写法都行
assign s22idle = state_c==S2 && cnt==6;
- 其他信号
条件不够时,要构造信号,即cnt。
用一个计数器即可;初值:0;加1条件:S1或S2状态;结束
条件:S1时为4,S2时为6
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(state_c==S1)begin
if(add_cnt1) begin
if(end_cnt1)
cnt<=0;
else
cnt <= cnt + 1;
end
end
else if(state_c==S2)begin
if(add_cnt2) begin
if(end_cnt2)
cnt<=0;
else
cnt <= cnt + 1;
end
end
end
assign add_cnt1 = 1;
assign end_cnt1 = add_cnt && cnt== 4;
assign add_cnt2 = 1;
assign end_cnt2 = add_cnt && cnt== 6;
//因为add_cnt=1,所以计数模块可以简化为:
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(state_c==S1)begin
if(cnt== 4)
cnt<=0;
else
cnt <= cnt + 1;
end
else if(state_c==S2)begin
if(cnt== 6)
cnt<=0;
else
cnt <= cnt + 1;
end
end
例2. 信号计数跳转状态机
状态机有三个状态,IDLE,S1和S2。在IDLE状态,如果en=1,则跳
到S1状态,否则保持不变;在S1状态时,统计en=1的次数,如果达到5次,
则跳到S2状态,否则保持不变;在S2状态,统计en=1的次数,如果达到7次
,则跳回到IDLE状态,否则保持不变。(注:全部信号都是同步信号,即与
时钟同步)
和例1的区别在于,要对en=1出现的次数进行计数。
-
状态转移图
-
状态转移代码
assign s12s2 = state_c==S1 && end_cnt1;
assign s22idle = state_c==S2 && end_cnt2;
- 其他信号cnt
初值:0;加1条件:在S1或S2状态,
en=1;结束条件:S1时为4,S2时为6
assign add_cnt1 = en==1;
assign end_cnt1 = add_cnt && cnt== 4;
assign add_cnt2 = en==1;
assign end_cnt2 = add_cnt && cnt== 6;