状态机的描述方法案例分析(一段式、二段式、三段式)

举报
李锐博恩 发表于 2021/07/15 06:29:58 2021/07/15
【摘要】 上篇博文讲了:FPGA中有限状态机的状态编码采用格雷码还是独热码? 那篇博文讲了状态机的状态编码是用格雷码还是独热码的问题,以及两者之间的优劣。状态机的描述方式采用的是一段式描述方式,也就是将整个状态机全部写到一个always模块中去。 这篇博文仍用上篇博文的案例,说说状态机的描述方法。一段式的描述方法、二段式以及三段式,并比较三者之间的功能仿真情况,最后真心吐露这个案例...

上篇博文讲了:FPGA中有限状态机的状态编码采用格雷码还是独热码?

那篇博文讲了状态机的状态编码是用格雷码还是独热码的问题,以及两者之间的优劣。状态机的描述方式采用的是一段式描述方式,也就是将整个状态机全部写到一个always模块中去。

这篇博文仍用上篇博文的案例,说说状态机的描述方法。一段式的描述方法、二段式以及三段式,并比较三者之间的功能仿真情况,最后真心吐露这个案例的状态转移图的疑问?不能把有问题的地方回避,我想我不要做这样的人。


首先看看状态机的描述方法,和编码方式,这两段描述借鉴:基于Verilog HDL的有限状态机,人家说的不错,我也懒着码字了。

状态机的描述方法

状态机的描述方法多种多样,将整个状态机写到1个always 模块里,在该模块中既描述状态转移,又描述状态的输入和输出,这种写法一般被称为一段式FSM 描述方法;

还有一种写法是使用两个always模块,其中一个always 模块采用同步时序的方式描述状态转移,而另一个模块采用组合逻辑的方式判断状态转移条件,描述状态转移规律,这种写法被称为两段式FSM 描述方法;

还有一种写法是在两段式描述方法的基础上发展而来的,这种写法使用3 个always模块,一个always 模块采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件,描述状态转移规律,第三个always 模块使用同步时序电路描述每个状态的输出,这种写法称为三段式写法。

 

状态机的状态编码

二进制码(Binary)和格雷码(Gray)属于压缩状态编码,这种编码的优点是使用的状态向量最少,但是需要较多的逻辑资源用来状态译码。二进制码从一个状态转换到相邻状态时,可能有多个比特位发生变化,易产生中间状态转移问题,状态机的速度也要比采用其它编码方式慢。格雷码两个相邻的码值仅有一位就可区分,这将会减少电路中相邻物理信号线同时变化的情况,因而可以减少电路中的电噪声。Johnson码也有同样的特点,但是要用较多的位数。

独热码(One-hot)指对任意给定的状态,状态寄存器中只有l位为1,其余位都为0。n状态的有限状态机需要n个触发器,但这种有限状态机只需对寄存器中的一位进行译码,简化了译码逻辑电路,额外触发器占用的面积可用译码电路省下来的面积抵消。当设计中加入更多的状态时,译码逻辑没有变得更加复杂,有限状态机的速度仅取决于到某特定状态的转移数量,而其它类型有限状态机在状态增加时速度会明显下降。独热码还具有设计简单、修改灵活、易于综合和调试等优点。独热码相对于二进制码,速度快但占用面积大。


给出实际案例:

下面是一个状态转移图,我们接下来就这个状态转移图来用不同的描述方式来描述。

1)一段式描述方法:


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 21:27:04 09/02/2018
  7. // Design Name:
  8. // Module Name: fsm
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module fsm(
  22. input Clock,
  23. input rst_n,
  24. input A,
  25. output F,
  26. output G
  27. );
  28. reg F, G;
  29. reg [3:0] state;
  30. parameter Idle = 4'b1000, Start = 4'b0100, Stop = 4'b0010, Clear = 4'b0001;
  31. always @(posedge Clock) begin
  32. if(!rst_n) begin
  33. state <= Idle;
  34. F <= 1'b0;
  35. G <= 1'b0;
  36. end
  37. else
  38. case(state)
  39. Idle: begin
  40. if(A) begin
  41. state <= Start;
  42. G <= 1'b0;
  43. end
  44. else
  45. state <= Idle;
  46. end
  47. Start: begin
  48. if(!A)
  49. state <= Stop;
  50. else
  51. state <= Start;
  52. end
  53. Stop: begin
  54. if(A) begin
  55. state <= Clear;
  56. F <= 1'b1;
  57. end
  58. else
  59. state <= Stop;
  60. end
  61. Clear: begin
  62. if(!A)begin
  63. state <= Idle;
  64. F <= 1'b0;
  65. G <= 1'b1;
  66. end
  67. else
  68. state <= Clear;
  69. end
  70. default: state <= Idle;
  71. endcase
  72. end
  73. endmodule

给出测试文件,测试文件在这个案例中通用:


  
  1. `timescale 1ns / 1ps
  2. // Company:
  3. // Engineer:
  4. //
  5. // Create Date: 23:39:28 09/02/2018
  6. // Design Name: fsm
  7. // Module Name: G:/modelsim_file/fsm01/fsm_tb.v
  8. // Project Name: fsm01
  9. // Target Device:
  10. // Tool versions:
  11. // Description:
  12. //
  13. // Verilog Test Fixture created by ISE for module: fsm
  14. //
  15. // Dependencies:
  16. //
  17. // Revision:
  18. // Revision 0.01 - File Created
  19. // Additional Comments:
  20. //
  21. module fsm_tb;
  22. // Inputs
  23. reg Clock;
  24. reg rst_n;
  25. reg A;
  26. // Outputs
  27. wire F;
  28. wire G;
  29. // Instantiate the Unit Under Test (UUT)
  30. fsm uut (
  31. .Clock(Clock),
  32. .rst_n(rst_n),
  33. .A(A),
  34. .F(F),
  35. .G(G)
  36. );
  37. initial begin
  38. // Initialize Inputs
  39. rst_n = 0;
  40. A = 0;
  41. #30 A = 1;
  42. rst_n = 1;
  43. #30 A = 0;
  44. #20 A = 1;
  45. #20 A = 0;
  46. // Wait 100 ns for global reset to finish
  47. #100;
  48. end
  49. initial begin
  50. Clock = 0;
  51. forever #10 Clock = ~Clock;
  52. end
  53. endmodule

功能仿真:

两段式描述方法:


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 21:27:04 09/02/2018
  7. // Design Name:
  8. // Module Name: fsm
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module fsm(
  22. input Clock,
  23. input rst_n,
  24. input A,
  25. output F,
  26. output G
  27. );
  28. reg F, G;
  29. reg [3:0] pre_state;
  30. reg [3:0] next_state;
  31. parameter Idle = 4'b1000, Start = 4'b0100, Stop = 4'b0010, Clear = 4'b0001;
  32. //第一个过程,同步时序always块,描述状态转移方程
  33. always @(posedge Clock) begin
  34. if(!rst_n)
  35. pre_state <= Idle;
  36. else
  37. pre_state <= next_state;
  38. end
  39. //第二个过程,组合逻辑always块,描述激励方程以及输出方程
  40. always @(pre_state or A or rst_n) begin
  41. case(pre_state)
  42. Idle:begin
  43. if(!rst_n) begin
  44. next_state = Idle;
  45. F = 1'b0;
  46. G = 1'b0;
  47. end
  48. else if(A) begin
  49. next_state = Start;
  50. G = 1'b0;
  51. end
  52. else begin
  53. next_state = Idle;
  54. end
  55. end
  56. Start: begin
  57. if(!rst_n) begin
  58. next_state = Idle;
  59. F = 1'b0;
  60. G = 1'b0;
  61. end
  62. else if(!A) begin
  63. next_state = Stop;
  64. end
  65. else begin
  66. next_state = Start;
  67. end
  68. end
  69. Stop: begin
  70. if(!rst_n) begin
  71. next_state = Idle;
  72. F = 1'b0;
  73. G = 1'b0;
  74. end
  75. else if(A) begin
  76. next_state = Clear;
  77. F = 1'b1;
  78. end
  79. else begin
  80. next_state = Stop;
  81. end
  82. end
  83. Clear: begin
  84. if(!rst_n) begin
  85. next_state = Idle;
  86. F = 1'b0;
  87. G = 1'b0;
  88. end
  89. else if(!A) begin
  90. next_state = Idle;
  91. F = 0;
  92. G = 1;
  93. end
  94. else begin
  95. next_state = Clear;
  96. end
  97. end
  98. default: begin
  99. next_state = Idle;
  100. end
  101. endcase
  102. end
  103. endmodule

三段式描述:


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 21:27:04 09/02/2018
  7. // Design Name:
  8. // Module Name: fsm
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module fsm(
  22. input Clock,
  23. input rst_n,
  24. input A,
  25. output F,
  26. output G
  27. );
  28. reg F, G;
  29. reg [3:0] pre_state;
  30. reg [3:0] next_state;
  31. parameter Idle = 4'b1000, Start = 4'b0100, Stop = 4'b0010, Clear = 4'b0001;
  32. //第一个过程,同步时序always块,描述状态转移方程
  33. always @(posedge Clock) begin
  34. if(!rst_n)
  35. pre_state <= Idle;
  36. else
  37. pre_state <= next_state;
  38. end
  39. //第二个过程,组合逻辑always块,描述激励方程
  40. always @(pre_state or A or rst_n) begin
  41. case(pre_state)
  42. Idle: begin
  43. if(!rst_n) next_state = Idle;
  44. else if(A) next_state = Start;
  45. else next_state = Idle;
  46. end
  47. Start: begin
  48. if(!rst_n) next_state = Idle;
  49. else if(!A) next_state = Stop;
  50. else next_state = Start;
  51. end
  52. Stop: begin
  53. if(!rst_n) next_state = Idle;
  54. else if(A) next_state = Clear;
  55. else next_state = Stop;
  56. end
  57. Clear: begin
  58. if(!rst_n) next_state = Idle;
  59. else if(!A) next_state = Idle;
  60. else next_state = Clear;
  61. end
  62. default: next_state = Idle;
  63. endcase
  64. end
  65. //第三个always块,描述输出方程
  66. always @(pre_state or A or rst_n) begin
  67. case(pre_state)
  68. Idle:begin
  69. if(!rst_n) begin
  70. F = 1'b0;
  71. G = 1'b0;
  72. end
  73. else if(A) begin
  74. G = 1'b0;
  75. end
  76. else begin
  77. ;
  78. end
  79. end
  80. Start: begin
  81. if(!rst_n) begin
  82. F = 1'b0;
  83. G = 1'b0;
  84. end
  85. else if(!A) begin
  86. ;
  87. end
  88. else begin
  89. ;
  90. end
  91. end
  92. Stop: begin
  93. if(!rst_n) begin
  94. F = 1'b0;
  95. G = 1'b0;
  96. end
  97. else if(A) begin
  98. F = 1'b1;
  99. end
  100. else begin
  101. ;
  102. end
  103. end
  104. Clear: begin
  105. if(!rst_n) begin
  106. F = 1'b0;
  107. G = 1'b0;
  108. end
  109. else if(!A) begin
  110. F = 0;
  111. G = 1;
  112. end
  113. else begin
  114. ;
  115. end
  116. end
  117. default: begin
  118. ;
  119. end
  120. endcase
  121. end
  122. endmodule

功能仿真:


可见,三种描述方式的仿真图都是一样的,说明了完成同样的功能。

但是从代码的简洁度来看,就这个小状态转移图来说,无疑,一段式的描述方式是最为简单的。但是随着项目的复杂度增高,这种描述方式不便于维护和阅读。

所以呢?要综合来看,不能说哪一种一定好,哪一种一定坏,要根据实际情况而定。

最后我要提出的问题,就是Clear这个状态向Idle这个状态转移的条件:从状态图上看,注意图中的状态图的复位我用rst_n代替,这样更人性化!继续:从状态图上看,是!rst_n或!A有效时,向Idle状态转移,并且输出是F = 0 ,且 G =1;

但是从原作者的一段式代码中,我们可以看出,复位信号rst_n的优先级别要高,如果复位了,那么状态肯定转向Idle,且此时,输出F=0且G=0.这明显和状态转移图中的意思不一样啊,我们推测状态转移图写法有误,所以这里我个人默认复位信号有限,其次是输入A和当前状态决定输出。也就是说,如果复位信号无效时,当前状态为Clear且 !A有效,那么输出就是F = 0 ,且 G =1,并且状态转向Idle.

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/82347216

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。