状态机采用VerilogHDL语言编码,建议分为三个always段完成。三段式描述方法虽然代码结构复杂了一些,但是换来的优势是使FSM做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在FPGA/CPLD等可编程逻辑器件上的综合与布局布线效果更佳。
示列如下:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @ (posedge clk or negedge rst_n) //异步复位
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;//注意,使用的是非阻塞赋值
//第二个进程,组合逻辑always模块,描述状态转移条件判断或者状态转移规律
always @ (current_state) //电平触发
begin
next_state = x; //要初始化,使得系统复位后能进入正确的状态
case(current_state)
S1: if(...)
next_state = S2; //阻塞赋值
...
endcase
end
//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)
...//初始化
case(next_state)
S1:
out1 <= 1'b1; //注意是非阻塞逻辑
S2:
out2 <= 1'b1;
default:... //default的作用是免除综合工具综合出锁存器。
endcase
end
三段式并不是一定要写为3个always块,如果状态机更复杂,就不止3段了。
附一个比较好的状态机范例:
01moduleFSM(clk,rst,in,out);
02inputclk,rst;
03input[7:0]in;
04output[7:0]out;
05
06parameter[1:0]//synopsys enum code
07START=2'd0,
08SA=1,
09 SB =2,
10SC=3;
11
12reg[1:0]CS,NS;
13reg[7:0]tmp_out,out;
14
15// state transfer
16always@ (posedgeclkornegedgerst)
17begin
18if (!rst) CS<=#1START;
19else CS<=#1 NS;
20end
21
22// state transfer discipline
23always@ (inorCS)
24begin
25 NS =START;
26 case (CS)
27 START:case (in[7:6])
28 2'b11: NS =SA;
29 2'b00: NS =SC;
30 default: NS =START;
31 endcase
32 SA:if(in==8'h3c) NS = SB;
33 SB:begin
34 if (in==8'h88) NS =SC;
35 else NS =START;
36 end
37 SC:case(1'b1) //synopsys parallel_case full_case
38 (in==8'd0): NS =SA;
39 (8'd0<in&&in<8'd38): NS =START;
40 (in>8'd37): NS = SB;
41 endcase
42 endcase
43end
44
45// temp out
46always@ (CS)
47begin
48 tmp_out=8'bX;
49 case (CS)
50 START:tmp_out=8'h00;
51 SA: tmp_out=8'h08;
52 SB: tmp_out=8'h18;
53 SC: tmp_out=8'h28;
54 endcase
55end
56
57// reg out
58always@ (posedgeclkornegedgerst)
59begin
60 if (!rst) out<=#18'b0;
61 else out<=#1tmp_out;
62end
63
64endmodule
示列如下:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @ (posedge clk or negedge rst_n) //异步复位
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;//注意,使用的是非阻塞赋值
//第二个进程,组合逻辑always模块,描述状态转移条件判断或者状态转移规律
always @ (current_state) //电平触发
begin
next_state = x; //要初始化,使得系统复位后能进入正确的状态
case(current_state)
S1: if(...)
next_state = S2; //阻塞赋值
...
endcase
end
//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)
...//初始化
case(next_state)
S1:
out1 <= 1'b1; //注意是非阻塞逻辑
S2:
out2 <= 1'b1;
default:... //default的作用是免除综合工具综合出锁存器。
endcase
end
三段式并不是一定要写为3个always块,如果状态机更复杂,就不止3段了。
附一个比较好的状态机范例:
01moduleFSM(clk,rst,in,out);
02inputclk,rst;
03input[7:0]in;
04output[7:0]out;
05
06parameter[1:0]//synopsys enum code
07START=2'd0,
08SA=1,
09 SB =2,
10SC=3;
11
12reg[1:0]CS,NS;
13reg[7:0]tmp_out,out;
14
15// state transfer
16always@ (posedgeclkornegedgerst)
17begin
18if (!rst) CS<=#1START;
19else CS<=#1 NS;
20end
21
22// state transfer discipline
23always@ (inorCS)
24begin
25 NS =START;
26 case (CS)
27 START:case (in[7:6])
28 2'b11: NS =SA;
29 2'b00: NS =SC;
30 default: NS =START;
31 endcase
32 SA:if(in==8'h3c) NS = SB;
33 SB:begin
34 if (in==8'h88) NS =SC;
35 else NS =START;
36 end
37 SC:case(1'b1) //synopsys parallel_case full_case
38 (in==8'd0): NS =SA;
39 (8'd0<in&&in<8'd38): NS =START;
40 (in>8'd37): NS = SB;
41 endcase
42 endcase
43end
44
45// temp out
46always@ (CS)
47begin
48 tmp_out=8'bX;
49 case (CS)
50 START:tmp_out=8'h00;
51 SA: tmp_out=8'h08;
52 SB: tmp_out=8'h18;
53 SC: tmp_out=8'h28;
54 endcase
55end
56
57// reg out
58always@ (posedgeclkornegedgerst)
59begin
60 if (!rst) out<=#18'b0;
61 else out<=#1tmp_out;
62end
63
64endmodule