当前位置:   article > 正文

FPGA之状态机_fpga状态机的三个基本原则

fpga状态机的三个基本原则

 

状态机


 

1.状态机定义

状态机的本质就是对具有逻辑顺序时序规律的事件的一种描述方法,它有三个要素:状态输入输出:状态也叫做状态变量(比如可以用电机的不同转速作为状态),输出指在某一个状态的特定输出,输入指状态机中进入每个状态的条件。

有限状态机(Finite State Machine, FSM),根据状态机的输出是否与输入有关,可分为Moore型状态机和Mealy型状态机。

Moore型状态机输出仅仅与现态有关,Mealy型状态机不仅与现态有关,也与输入有关,所以会受到输入的干扰,可能会产生毛刺(Glith)的现象,所以我们通常使用的是Moore型状态机。

Mealy型状态机:

 

Moore型状态机:

 

2.状态机描述方式

状态机描述时关键是要描述清楚几个状态机的要素,即如何进行状态转移,每个状态的输出是什么,状态转移的条件等。具体描述时方法各种各样,最常见的有三种描述方式:

一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;

二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;

三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。

一般而言,推荐的FSM 描述方法是后两种。这是因为:FSM和其他设计一样,最好使用同步时序方式设计,以提高设计的稳定性,消除毛刺。状态机实现后,一般来说,状态转移部分是同步时序电路而状态的转移条件的判断是组合逻辑。

 

3.不同描述方式的好坏

一段式:虽然一个always块就可以解决问题,但描述不清晰,不利于维护修改,并且不利用附加约束,不利于综合其和布局布线器对设计的优化;

二段式:第二种描述方法同第一种描述方法相比,将同步时序和组合逻辑分别放到不同的always模块中实现,这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。在第二种方式的描述中,描述当前状态的输出用组合逻辑实现,组合逻辑很容易产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计。

三段式:

  1. 第三种描述方式与第二种相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。
  2. 多了寄存器资源,却有效的避免了重大错误,这也暗示了一个数字设计里最重要的思想,中和设计思想有的时候可以需要性能的提升,但在提升性能的同时也会增加资源占用,设计面积增大,所以两者中和往往是最优秀的设计;

 

4.状态机的优点

但是为什么要使用状态机而不使用一般时序电路呢?这是因为它具有一些一般时序电路无法比拟的优点.

  1. 用VHDL描述的状态机结构分明,易读,易懂,易排错;
  2. 相对其它时序电路而言,状态机更加稳定,运行模式类似于CPU,易于实现顺序控制等

 

5.状态机怎么叫好?

好的状态机的标准很多,最重要的几个方面如下:

  1. 状态机要安全,是指FSM不会进入死循环,特别是不会进入非预知的状态,而且由于某些扰动进入非设计状态,也能很快的恢复到正常的状态循环中来。这里 面有两层含义:其一要求该FSM的综合实现结果无毛刺等异常扰动;其二要求FSM要完备,即使受到异常扰动进入非设计状态,也能很快恢复到正常状态。
  2. 状态机的设计要满足设计的面积和速度的要求。
  3. 状态机的设计要清晰易懂、易维护。
  4.  

6.参数定义编码选择

对于格雷码和独热码,到底应该怎么选择才能达到最优综合?查阅书籍及网络资料,总结起来就是:

  1. 格雷码:适合所有状态是顺序序列,可以用格雷码来消除毛刺,但如果有复杂分支判断,则格雷码也不能达到消毛刺的目的,简单的说,格雷码适合条件不复杂,状态多的情况;
  2. 独热码:消耗较少组合逻辑,消耗更多寄存器,因此在FPGA中有利于速度和可靠性。适合条件复杂,状态少的情况。
  3. 二进制码:有过渡状态,容易跑飞。

binarygray-code适用于触发器资源较少,组合电路资源丰富的情况(CPLD),对于FPGA,适用one-hot code。这样不但充分利用FPGA丰富的触发器资源,还因为只需比较一个bit,速度快,组合电路简单。

 

7.Example

自动售货机

一段式:

  1. module auto_sell(
  2. input clk,
  3. input rst_n,
  4. input coin_one,
  5. input coin_half,
  6. output reg water,
  7. output reg coin_back
  8. );
  9. parameter ZERO = 3'b000;
  10. parameter HALF = 3'b001;
  11. parameter ONE = 3'b010;
  12. parameter ONE_HALF = 3'b011;
  13. parameter TWO = 3'b100;
  14. //一段式状态机
  15. reg [2:0] status;
  16. always@(posedge clk,negedge rst_n)begin
  17. if(!rst_n)
  18. begin
  19. status <= ZERO;
  20. water <= 0;
  21. coin_back <= 0;
  22. end
  23. else
  24. case(status)
  25. ZERO :
  26. begin
  27. water <= 0;
  28. coin_back <= 0;
  29. if(coin_half)
  30. status <= HALF;
  31. else if(coin_one)
  32. status <= ONE;
  33. else
  34. status <= status;
  35. end
  36. HALF :
  37. begin
  38. water <= 0;
  39. coin_back <= 0;
  40. if(coin_half)
  41. status <= ONE;
  42. else if(coin_one)
  43. status <= ONE_HALF;
  44. else
  45. status <= status;
  46. end
  47. ONE :
  48. begin
  49. water <= 0;
  50. coin_back <= 0;
  51. if(coin_half)
  52. status <= ONE_HALF;
  53. else if(coin_one)
  54. status <= TWO;
  55. else
  56. status <= status;
  57. end
  58. ONE_HALF :
  59. begin
  60. if(coin_half)
  61. begin
  62. status <= TWO;
  63. water <= 1'b0;
  64. coin_back <= 1'b0;
  65. end
  66. else if(coin_one)
  67. begin
  68. status <= ZERO;
  69. water <= 1'b1;
  70. coin_back <= 1'b0;
  71. end
  72. else
  73. begin
  74. status <= status;
  75. water <= 1'b0;
  76. coin_back <= 1'b0;
  77. end
  78. end
  79. TWO :
  80. begin
  81. if(coin_half)
  82. begin
  83. status <= ZERO;
  84. water <= 1'b1;
  85. coin_back <= 1'b0;
  86. end
  87. else if(coin_one)
  88. begin
  89. status <= ZERO;
  90. water <= 1'b1;
  91. coin_back <= 1'b1;
  92. end
  93. else
  94. begin
  95. status <= status;
  96. water <= 1'b0;
  97. coin_back <= 1'b0;
  98. end
  99. end
  100. default:
  101. begin
  102. status <= ZERO;
  103. water <= 1'b0;
  104. coin_back <= 1'b0;
  105. end
  106. endcase
  107. end
  108. endmodule

 

二段式写法1:

  1. module auto_sell(
  2. input clk,
  3. input rst_n,
  4. input coin_one,
  5. input coin_half,
  6. output reg water,
  7. output reg coin_back
  8. );
  9. parameter ZERO = 3'b000;
  10. parameter HALF = 3'b001;
  11. parameter ONE = 3'b010;
  12. parameter ONE_HALF = 3'b011;
  13. parameter TWO = 3'b100;
  14. //--------------------二段式 1 ok--------------------------
  15. //二段式状态机
  16. reg [2:0] c_status;
  17. reg [2:0] n_status;
  18. //状态转移
  19. always@(posedge clk,negedge rst_n)begin
  20. if(!rst_n)
  21. c_status <= ZERO;
  22. else
  23. c_status <= n_status;
  24. end
  25. //描述状态转移规律以及输出
  26. always@(posedge clk,negedge rst_n)begin
  27. if(!rst_n)
  28. begin
  29. n_status <= ZERO;
  30. water <= 1'b0;
  31. coin_back <= 1'b0;
  32. end
  33. else
  34. case(c_status)
  35. ZERO :
  36. begin
  37. water <= 1'b0;
  38. coin_back <= 1'b0;
  39. if(coin_half)
  40. n_status <= HALF;
  41. else if(coin_one)
  42. n_status <= ONE;
  43. else
  44. n_status <= ZERO;
  45. end
  46. HALF :
  47. begin
  48. water <= 1'b0;
  49. coin_back <= 1'b0;
  50. if(coin_half)
  51. n_status <= ONE;
  52. else if(coin_one)
  53. n_status <= ONE_HALF;
  54. else
  55. n_status <= HALF;
  56. end
  57. ONE :
  58. begin
  59. water <= 1'b0;
  60. coin_back <= 1'b0;
  61. if(coin_half)
  62. n_status <= ONE_HALF;
  63. else if(coin_one)
  64. n_status <= TWO;
  65. else
  66. n_status <= ONE;
  67. end
  68. ONE_HALF :
  69. begin
  70. water <= 1'b0;
  71. coin_back <= 1'b0;
  72. if(coin_half)
  73. n_status <= TWO;
  74. else if(coin_one)
  75. begin
  76. n_status <= ZERO;
  77. water <= 1'b1;
  78. coin_back <= 1'b0;
  79. end
  80. else
  81. n_status <= ONE_HALF;
  82. end
  83. TWO :
  84. begin
  85. water <= 1'b0;
  86. coin_back <= 1'b0;
  87. if(coin_half)
  88. begin
  89. n_status <= ZERO;
  90. water <= 1'b1;
  91. coin_back <= 1'b0;
  92. end
  93. else if(coin_one)
  94. begin
  95. n_status <= ZERO;
  96. water <= 1'b1;
  97. coin_back <= 1'b1;
  98. end
  99. else
  100. n_status <= TWO;
  101. end
  102. default:
  103. n_status <= ZERO;
  104. endcase
  105. end
  106. endmodule

二段式写法2:

  1. module auto_sell(
  2. input clk,
  3. input rst_n,
  4. input coin_one,
  5. input coin_half,
  6. output reg water,
  7. output reg coin_back
  8. );
  9. parameter ZERO = 3'b000;
  10. parameter HALF = 3'b001;
  11. parameter ONE = 3'b010;
  12. parameter ONE_HALF = 3'b011;
  13. parameter TWO = 3'b100;
  14. //---------------------二段式 2 ok--------------------------------------
  15. //二段式状态机
  16. reg [2:0] status;
  17. //状态转移
  18. always@(posedge clk,negedge rst_n)begin
  19. if(!rst_n)
  20. status <= ZERO;
  21. else
  22. begin
  23. case(status)
  24. ZERO :
  25. begin
  26. if(coin_half)
  27. status <= HALF;
  28. else if(coin_one)
  29. status <= ONE;
  30. else
  31. status <= ZERO;
  32. end
  33. HALF :
  34. begin
  35. if(coin_half)
  36. status <= ONE;
  37. else if(coin_one)
  38. status <= ONE_HALF;
  39. else
  40. status <= HALF;
  41. end
  42. ONE :
  43. begin
  44. if(coin_half)
  45. status <= ONE_HALF;
  46. else if(coin_one)
  47. status <= TWO;
  48. else
  49. status <= ONE;
  50. end
  51. ONE_HALF :
  52. begin
  53. if(coin_half)
  54. status <= TWO;
  55. else if(coin_one)
  56. begin
  57. status <= ZERO;
  58. end
  59. else
  60. status <= ONE_HALF;
  61. end
  62. TWO :
  63. begin
  64. if(coin_half)
  65. begin
  66. status <= ZERO;
  67. end
  68. else if(coin_one)
  69. begin
  70. status <= ZERO;
  71. end
  72. else
  73. status <= TWO;
  74. end
  75. default:
  76. status <= ZERO;
  77. endcase
  78. end
  79. end
  80. //输出 时序逻辑
  81. always@(posedge clk,negedge rst_n)begin
  82. if(!rst_n)
  83. begin
  84. water <= 1'b1;
  85. coin_back <= 1'b0;
  86. end
  87. else
  88. case(status)
  89. ONE_HALF:
  90. begin
  91. if(coin_one)
  92. begin
  93. water <= 1'b1;
  94. coin_back <= 1'b0;
  95. end
  96. else
  97. begin
  98. water <= 1'b0;
  99. coin_back <= 1'b0;
  100. end
  101. end
  102. TWO:
  103. begin
  104. if(coin_half)
  105. begin
  106. water <= 1'b1;
  107. coin_back <= 1'b0;
  108. end
  109. else if(coin_one)
  110. begin
  111. water <= 1'b1;
  112. coin_back <= 1'b1;
  113. end
  114. else
  115. begin
  116. water <= 1'b0;
  117. coin_back <= 1'b0;
  118. end
  119. end
  120. default:
  121. begin
  122. water <= 1'b0;
  123. coin_back <= 1'b0;
  124. end
  125. endcase
  126. end
  127. endmodule

三段式:

  1. module auto_sell(
  2. input clk,
  3. input rst_n,
  4. input coin_one,
  5. input coin_half,
  6. output reg water,
  7. output reg coin_back
  8. );
  9. parameter ZERO = 3'b000;
  10. parameter HALF = 3'b001;
  11. parameter ONE = 3'b010;
  12. parameter ONE_HALF = 3'b011;
  13. parameter TWO = 3'b100;
  14. //三段式状态机
  15. reg [2:0] c_status;
  16. reg [2:0] n_status;
  17. //状态转移
  18. always@(posedge clk,negedge rst_n)begin
  19. if(!rst_n)
  20. c_status <= ZERO;
  21. else
  22. c_status <= n_status;
  23. end
  24. //状态转移规律及状态输出,组合逻辑输出只与输入有关
  25. //如果有n_status = n_status,电路会出错;
  26. always@(*)begin
  27. case(c_status)
  28. ZERO :
  29. begin
  30. if(coin_half)
  31. n_status = HALF;
  32. else if(coin_one)
  33. n_status = ONE;
  34. else
  35. n_status = ZERO;
  36. end
  37. HALF :
  38. begin
  39. if(coin_half)
  40. n_status = ONE;
  41. else if(coin_one)
  42. n_status = ONE_HALF;
  43. else
  44. n_status = HALF;
  45. end
  46. ONE :
  47. begin
  48. if(coin_half)
  49. n_status = ONE_HALF;
  50. else if(coin_one)
  51. n_status = TWO;
  52. else
  53. n_status = ONE;
  54. end
  55. ONE_HALF :
  56. begin
  57. if(coin_half)
  58. n_status = TWO;
  59. else if(coin_one)
  60. n_status = ZERO;
  61. else
  62. n_status = ONE_HALF;
  63. end
  64. TWO :
  65. begin
  66. if(coin_half)
  67. n_status = ZERO;
  68. else if(coin_one)
  69. n_status = ZERO;
  70. else
  71. n_status = TWO;
  72. end
  73. default:
  74. n_status = ZERO;
  75. endcase
  76. end
  77. always@(posedge clk,negedge rst_n)begin
  78. if(!rst_n)
  79. begin
  80. water = 1'b1;
  81. coin_back = 1'b0;
  82. end
  83. else
  84. case(c_status)
  85. ONE_HALF:
  86. begin
  87. if(coin_one)
  88. begin
  89. water = 1'b1;
  90. coin_back = 1'b0;
  91. end
  92. else
  93. begin
  94. water = 1'b0;
  95. coin_back = 1'b0;
  96. end
  97. end
  98. TWO:
  99. begin
  100. if(coin_half)
  101. begin
  102. water = 1'b1;
  103. coin_back = 1'b0;
  104. end
  105. else if(coin_one)
  106. begin
  107. water = 1'b1;
  108. coin_back = 1'b1;
  109. end
  110. else
  111. begin
  112. water = 1'b0;
  113. coin_back = 1'b0;
  114. end
  115. end
  116. default:
  117. begin
  118. water = 1'b0;
  119. coin_back = 1'b0;
  120. end
  121. endcase
  122. end
  123. endmodule

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/915485
推荐阅读
相关标签
  

闽ICP备14008679号