明德扬至简设计法--四段式状态机,让FPGA代码更简洁更高效
- mdykjLV.工兵
- 2017/2/15 14:56:48
四段式状态机
在FPGA中,相信有FPGA学习经验的都能了解,现在流行的状态机设计,一般可分为一段式、两段式和三段式,如果不了解的,可以自行百度。
上面的三种设计法虽然很流行,但设计时仍然要考虑很多因素,导致总是要反反复复调试才能设计成功。这不符合明德扬一次考虑一个因素、一次性设计正确的设计理念。为此,明德扬特推出四段式状态机的写法。
四段式不是指三个always代码,而是四段程序。使用四段式的写法,可参照明德扬GVIM特色指令Ztj产生的状态机模板。
第一段,同步时序的always模块,格式化描述次态迁移到现态寄存器。
1 always@(posedge clk or negedge rst_n)begin
2 if(!rst_n)begin
3 state_c <= IDLE;
4 end
5 else begin
6 state_c <= state_n;
7 end
8end
第二段,组合逻辑的always模块,描述状态转移条件判断。注意转移条件用信号来表示,信号名要按明德扬规则来命名。
1 always@(*)begin
2 case(state_c)
3 IDLE:begin
4 if(idle2s1_start)begin
5 state_n = S1;
6 end
7 else begin
8 state_n = state_c;
9 end
10 end
11 S1:begin
12 if(s12s2_start)begin
13 state_n = S2;
14 end
15 else begin
16 state_n = state_c;
17 end
18 end
19 S2:begin
20 if(s22idl)begin
21 state_n = IDLE;
22 end
23 else begin
24 state_n = state_c;
25 end
26 end
27 default:begin
28 state_n = IDLE;
29 end
30 endcase
31end
32
33assign idle2s1_start = state_c==IDLE && ;
34assign s12s2_start = state_c==S1 && ;
35assign s22idl_start = state_c==S2 && ;
第三段,用assign定义转移条件。注意条件一定要加上现态。
1 assign idle2s1_start = state_c==IDLE && ;
2assign s12s2_start = state_c==S1 && ;
3assign s22idl_start = state_c==S2 && ;
第四段,设计输出信号。明德扬规范要求一个always设计一个信号,因此有多少个输出信号,就有多少个always。
1 always @(posedge clk or negedge rst_n)begin
2 if(!rst_n)begin
3 out1 <=1'b0
4 end
5 else if(state_c==S1)begin
6 out1 <= 1'b1;
7 end
8 else begin
9 out1 <= 1'b0;
10 end
11end
明德扬四段式状态机符合一次只考虑一个因素的设计理念。第一段代码,照抄格式,完全不用想其他的。第二段代码,只考虑状态之间的跳转,也就是说各个状态机之间跳转关系。第三段代码,只考虑跳转条件。第三段,每个信号逐个设计。
明德扬为了保证一次设计正确,还制定了一些规范。例如第二段的跳转条件,只准用信号名代替,并且制定了跳转条件的命名规范,1是解决了命名困难的问题,2是对转移条件一目了然,如idl2s1_start,就可以看出是IDLE跳到S1状态的条件。 还有,明德扬规定转移条件的格式,一定是“ 当前状态&&具体条件”,以防想不到的情况出现。有了这些规范的保证,无论多复杂的场合,任何设计都能有条理、有步骤地一次性设计正确。
在FPGA中,相信有FPGA学习经验的都能了解,现在流行的状态机设计,一般可分为一段式、两段式和三段式,如果不了解的,可以自行百度。
上面的三种设计法虽然很流行,但设计时仍然要考虑很多因素,导致总是要反反复复调试才能设计成功。这不符合明德扬一次考虑一个因素、一次性设计正确的设计理念。为此,明德扬特推出四段式状态机的写法。
四段式不是指三个always代码,而是四段程序。使用四段式的写法,可参照明德扬GVIM特色指令Ztj产生的状态机模板。
第一段,同步时序的always模块,格式化描述次态迁移到现态寄存器。
1 always@(posedge clk or negedge rst_n)begin
2 if(!rst_n)begin
3 state_c <= IDLE;
4 end
5 else begin
6 state_c <= state_n;
7 end
8end
第二段,组合逻辑的always模块,描述状态转移条件判断。注意转移条件用信号来表示,信号名要按明德扬规则来命名。
1 always@(*)begin
2 case(state_c)
3 IDLE:begin
4 if(idle2s1_start)begin
5 state_n = S1;
6 end
7 else begin
8 state_n = state_c;
9 end
10 end
11 S1:begin
12 if(s12s2_start)begin
13 state_n = S2;
14 end
15 else begin
16 state_n = state_c;
17 end
18 end
19 S2:begin
20 if(s22idl)begin
21 state_n = IDLE;
22 end
23 else begin
24 state_n = state_c;
25 end
26 end
27 default:begin
28 state_n = IDLE;
29 end
30 endcase
31end
32
33assign idle2s1_start = state_c==IDLE && ;
34assign s12s2_start = state_c==S1 && ;
35assign s22idl_start = state_c==S2 && ;
第三段,用assign定义转移条件。注意条件一定要加上现态。
1 assign idle2s1_start = state_c==IDLE && ;
2assign s12s2_start = state_c==S1 && ;
3assign s22idl_start = state_c==S2 && ;
第四段,设计输出信号。明德扬规范要求一个always设计一个信号,因此有多少个输出信号,就有多少个always。
1 always @(posedge clk or negedge rst_n)begin
2 if(!rst_n)begin
3 out1 <=1'b0
4 end
5 else if(state_c==S1)begin
6 out1 <= 1'b1;
7 end
8 else begin
9 out1 <= 1'b0;
10 end
11end
明德扬四段式状态机符合一次只考虑一个因素的设计理念。第一段代码,照抄格式,完全不用想其他的。第二段代码,只考虑状态之间的跳转,也就是说各个状态机之间跳转关系。第三段代码,只考虑跳转条件。第三段,每个信号逐个设计。
明德扬为了保证一次设计正确,还制定了一些规范。例如第二段的跳转条件,只准用信号名代替,并且制定了跳转条件的命名规范,1是解决了命名困难的问题,2是对转移条件一目了然,如idl2s1_start,就可以看出是IDLE跳到S1状态的条件。 还有,明德扬规定转移条件的格式,一定是“ 当前状态&&具体条件”,以防想不到的情况出现。有了这些规范的保证,无论多复杂的场合,任何设计都能有条理、有步骤地一次性设计正确。

校园资讯