状态机

数字系统有两大类有限状态机(Finite State MachineFSM):Moore状态机和Mealy状态机。

Moore状态机

  其最大特点是输出只由当前状态确定,与输入无关。Moore状态机的状态图中的每一个状态都包含一个输出信号。这是一个典型的Moore状态机的状态跳转图,xyz是输入,abc是输出。

 

Mealy状态机

  它的输出不仅与当前状态有关系,而且与它的输入也有关系,因而在状态图中每条转移边需要包含输入和输出的信息。

 

状态编码

  数字逻辑系统状态机设计中常见的编码方式有:二进制码(Binary码)、格雷码(Gray码)、独热码(One-hot码)以及二一十进制码(BCD码)。

  格雷码的特点:相邻的两个码组之间仅有一位不同。

普通二进制码与格雷码之间可以相互转换。

  二进制码转换为格雷码:从最右边一位起,一次与左边一位异或,作为对应格雷码该位的值,最左边的一位不变(相当于最左边是0)。

  格雷码转换为二进制码:从左边第二位起,将每一位与左边一位解码后的值异或,作为该解码后的值(最左边的一位依然不变)。

  独热码又分为独热1码和独热0码,是一种特殊的二进制编码方式。当任何一种状态有且仅有一个1时,就是独热1码,相反任何一种状态有且仅有一个0时,就是独热0码。

状态机的描述

  状态机有三种描述方式:一段式状态机、两段式状态机、三段式状态机。下面就用一个小例子来看看三种方式是如何实现的。

(各种图片,各种坑爹啊 - -!)

 

一段式状态机

  当把整个状态机卸载一个always模块中,并且这个模块既包含状态转移,又含有组合逻辑输入/输出时,称为一段式状态机。不推荐采用这种状态机,因为从代码风格方面来讲,一般都会要求把组合逻辑和时序逻辑分开;从代码维护和升级来说,组合逻辑和书序逻辑混合在一起不利于代码维护和修改,也不利于约束。

1. //一段式状态机来实现:在异步复位信号的控制下,一段式状态机进入IDLE

2. //状态,q_sig4被复位,一旦sig1或者sig2有效,状态机进入WAIT状态,如果

3. //sig1和sig2同时有效,那么状态机进入DONE状态,

4. //如果sig4还有效,那么q_sig4置位,同时状态机进入IDLE状态。

5. 

6. module one_seg_fsm(clk,reset,sig1,sig2,sig3,q_sig4,q_sm_state);

7. //数据声明部分

8. input clk,reset,sig1,sig2,sig3;

9. 

10. output reg       q_sig4;

11. output reg [1:0] q_sm_state;

12. 

13. //参数声明

14. parameter  IDLE       = 2'b00;

15. parameter  WAIT       = 2'b01;

16. parameter  DONE       = 2'b10;

17. 

18. //状态跳转逻辑程序设计

19. always @(posedge clk or posedge reset)

20.    begin

21.        if(reset)

22.        begin

23.            q_sig4     <= 0;

24.            q_sm_state <= IDLE;

25.        end

26.      else 

27.          begin

28.              case(q_sm_state) 

29.                    IDLE: begin

30.                               if(sig1 || sig2)

31.                                    begin

32.                                        q_sm_state <= WAIT;

33.                                        q_sig4 <= 1'b0;

34.                                    end

35.                                   else

36.                                       begin

37.                                           q_sm_state <= IDLE;

38.                                           q_sig4 <= 1'b0;

39.                                     end

40.                            end

41.                    WAIT: begin

42.                              if(sig2 && sig3)

43.                                  begin

44.                                      q_sm_state <= DONE;

45.                                      q_sig4     <= 1'b0;

46.                                end

47.                              else

48.                                  begin

49.                                      q_sm_state <= WAIT;

50.                                      q_sig4     <= 1'b0;

51.                                end

52.                           end       

53.                                      

54.                    DONE:begin

55.                             if(sig3)

56.                                 begin

57.                                     q_sm_state <= IDLE;

58.                                     q_sig4     <= 1'b1;

59.                                 end

60.                             else

61.                                 begin

62.                                     q_sm_state <= DONE;

63.                                     q_sig4     <= 1'b0;

64.                                 end

65.                            end

66.                     

67.                  default: begin

68.                               q_sm_state <= IDLE;

69.                               q_sig4     <= 0;

70.                             end

71.            endcase   

72.      end

73.    end

74. endmodule

复制代码

两段式状态机

  所谓的两段式状态机就是采用一个always语句来实现时序逻辑,另外一个always语句来实现组合逻辑,提高了代码的可读性,易于维护。不同于一段式状态机的是,它需要定义两个状态----现态和次态,然后通过现态和次态的转换来实现时序逻辑。

1. //本例主要采用两段式状态机:在异步复位信号的控制下,一段式状态机进入IDLE

2. //状态,q_sig4被复位,一旦sig1或者sig2有效,状态机进入WAIT状态,如果sig1和sig2同时有效,那么

3. //状态机进入DONE状态,如果sig4还有效,那么q_sig4置位,同时状态机进入IDLE状态。

4. 

5. module two_seg_fsm(clk,reset,sig1,sig2,sig3,q_sig4);

6. //数据声明部分

7. input clk,reset,sig1,sig2,sig3;

8. 

9. output reg       q_sig4;

10. 

11. reg [1:0]    current_state, next_state;

12. 

13. //参数声明

14. parameter  IDLE       = 2'b00;

15. parameter  WAIT       = 2'b01;

16. parameter  DONE       = 2'b10;

17. 

18. //状态跳转程序设计

19. always @(posedge clk or posedge reset)

20.   if(reset)

21.       current_state <= IDLE;

22.   else

23.       current_state <= next_state;

24.       

25. //状态逻辑输出

26. always @(current_state or sig1 or sig2 or sig3)

27.    begin

28.        case(current_state)

29.        IDLE: begin

30.                               if(sig1 || sig2)

31.                                    begin

32.                                        next_state = WAIT;

33.                                        q_sig4    = 1'b0;

34.                                    end

35.                                   else

36.                                       begin

37.                                           next_state = IDLE;

38.                                           q_sig4     = 1'b0;

39.                                     end

40.                            end

41.                    WAIT: begin

42.                              if(sig2 && sig3)

43.                                  begin

44.                                      next_state = DONE;

45.                                      q_sig4     = 1'b0;

46.                                end

47.                              else

48.                                  begin

49.                                      next_state = WAIT;

50.                                      q_sig4     = 1'b0;

51.                                end

52.                           end       

53.                                      

54.                    DONE:begin

55.                             if(sig3)

56.                                 begin

57.                                     next_state = IDLE;

58.                                     q_sig4     = 1'b1;

59.                                 end

60.                             else

61.                                 begin

62.                                     next_state = DONE;

63.                                     q_sig4     = 1'b0;

64.                                 end

65.                            end

66.                     

67.                  default: begin

68.                               next_state = IDLE;

69.                               q_sig4     = 0;

70.                             end

71.            endcase   

72.      

73.    end

74. endmodule

复制代码

三段式状态机

  三段式状态机与两段式状态机的区别:两段式直接采用组合逻辑输出,而三段式则通过在组合逻辑后再增加一级寄存器来实现时序逻辑输出。这样做的好处是可以有效地滤去租个逻辑输出的毛刺,同时可以有效地进行时序计算与约束,另外对于总线形式的输出信号来说,容易使总线数据对其,从而减小总线数据间的偏移,减小接收端数据采样出错的频率。

  三段式状态机的基本格式是:第一个always语句实现同步状态跳转;第二个always语句实现组合逻辑;第三个always语句实现同步输出。

1. //本例主要采用三段式状态机:在异步复位信号的控制下,一段式状态机进入IDLE

2. //状态,q_sig4被复位,一旦sig1或者sig2有效,状态机进入WAIT状态,如果sig1和sig2同时有效,那么

3. //状态机进入DONE状态,如果sig4还有效,那么q_sig4置位,同时状态机进入IDLE状态。

4. 

5. module three_seg_fsm(clk,reset,sig1,sig2,sig3,q_sig4);

6. //数据声明部分

7. input clk,reset,sig1,sig2,sig3;

8. 

9. output reg       q_sig4;

10. 

11. reg [1:0]    current_state, next_state;

12. 

13. //参数声明

14. parameter  IDLE       = 2'b00;

15. parameter  WAIT       = 2'b01;

16. parameter  DONE       = 2'b10;

17. 

18. //状态跳转程序设计

19. always @(posedge clk or posedge reset)

20.   if(reset)

21.       current_state <= IDLE;

22.   else

23.       current_state <= next_state;

24.       

25. //状态跳转输出

26. always @(current_state or sig1 or sig2 or sig3)

27.    begin

28.        case(current_state)

29.        IDLE: begin

30.                               if(sig1 || sig2)

31.                                    begin

32.                                        next_state = WAIT;                                      

33.                                    end

34.                                   else

35.                                       begin

36.                                           next_state = IDLE;                                         

37.                                     end

38.                            end

39.                    WAIT: begin

40.                              if(sig2 && sig3)

41.                                  begin

42.                                      next_state = DONE;                                    

43.                                end

44.                              else

45.                                  begin

46.                                      next_state = WAIT;                                    

47.                                end

48.                           end       

49.                                      

50.                    DONE:begin

51.                             if(sig3)

52.                                 begin

53.                                     next_state = IDLE;                                   

54.                                 end

55.                             else

56.                                 begin

57.                                     next_state = DONE;                                   

58.                                 end

59.                            end

60.                     

61.                  default: begin

62.                               next_state = IDLE;                             

63.                             end

64.            endcase       

65.    end

66.    

67.    //逻辑输出

68.    always @(posedge clk or posedge reset)

69.      if(reset)

70.          q_sig4 <= 1'b0;

71.      else

72.          begin

73.              case(next_state)

74.                  IDLE,

75.                  WAIT: q_sig4 <= 1'b0;

76.                  DONE: q_sig4 <= 1'b1;

77.                  default: q_sig4 <= 1'b0;

78.            endcase

79.          end

80.          

81. endmodule

复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值