当前位置:   article > 正文

FPGA学习_状态机:使用vivado写一个简单的状态机程序,模拟自动售货机售卖可乐_利用有限状态机,设计一个自动售货机控制程序,完成售卖单一商品即可,

利用有限状态机,设计一个自动售货机控制程序,完成售卖单一商品即可,

一、状态机简介

FPGA中的状态机是一种基于状态转移的设计方法,它可以实现复杂的控制逻辑和状态管理。状态机通常由状态寄存器、状态转移逻辑和输出逻辑组成。

状态寄存器用于存储当前状态,状态转移逻辑用于根据输入信号和当前状态计算下一个状态,输出逻辑用于根据当前状态和输入信号计算输出信号。状态机可以实现多种功能,例如序列检测、计数器、状态控制等。

在FPGA中,状态机可以使用Verilog或VHDL等硬件描述语言进行设计和实现。我们需要定义状态寄存器、状态转移逻辑和输出逻辑,并将其综合到FPGA中。状态机的设计需要考虑时序约束、时钟域等因素,以确保正确性和可靠性。

二、分类

状态机可以根据不同的特征进行分类,常见的分类方式包括以下几种:

  1. Moore状态机和Mealy状态机:Moore状态机的输出只与当前状态有关,而Mealy状态机的输出不仅与当前状态有关,还与输入信号有关。

  2. 同步状态机和异步状态机:同步状态机的状态转移和输出逻辑都与时钟信号同步,而异步状态机的状态转移和输出逻辑不与时钟信号同步。

  3. 有限状态自动机和无限状态自动机:主要是指状态数是否是有限的。

  4. 顺序状态机和组合状态机:顺序状态机的输出不仅与当前输入有关,还与之前的输入有关,而组合状态机的输出只与当前输入有关。

  5. 硬件状态机和软件状态机:硬件状态机是在FPGA中实现的,而软件状态机是在软件中实现的。硬件状态机具有高效、低功耗、可重构等优点,而软件状态机具有灵活、易于修改等优点。

三、售货机实验

主要实现功能:除时钟和复位外,定义两种输入——0.5元和1元硬币;售卖机有5种状态——空闲、已投入0.5元到2元4种状态;定义两种输出——找零0.5元和出可乐。

四、代码

选用两段式,一段为时序逻辑描述转移,一段为组合逻辑描述输出。在进行综合时,系统会自动将这种代码识别为状态机。

  1. `timescale 1ns / 1ps //设置时间单位
  2. module cola_fsm2(
  3. input wire clk,
  4. input wire rst_n,
  5. input wire pi_money_one,
  6. input wire pi_money_half,
  7. output wire po_cola,
  8. output wire po_money
  9. );
  10. //定义参数类型
  11. reg [2:0] state;
  12. reg po_cola_p, po_money_p;
  13. wire [1:0] pi_money;
  14. //设置状态参数
  15. parameter
  16. idle=3'b000,half=3'b001,one=3'b010,onehalf=3'b011,
  17. two=3'b100;
  18. //使用拼接符赋值
  19. assign pi_money = {pi_money_one,pi_money_half};
  20. //时序逻辑描述转移
  21. always @(posedge clk or negedge rst_n)
  22. if(rst_n == 1'b0)
  23. state <= idle;
  24. else
  25. case(state)
  26. idle : if(pi_money == 2'b01)
  27. state <= half;
  28. else if(pi_money == 2'b10)
  29. state <= one;
  30. else
  31. state <= idle;
  32. half : if(pi_money == 2'b01)
  33. state <= one;
  34. else if(pi_money== 2'b10)
  35. state <= onehalf;
  36. else
  37. state <= half;
  38. one : if(pi_money == 2'b01)
  39. state <= onehalf;
  40. else if(pi_money== 2'b10)
  41. state <= two;
  42. else
  43. state <= one;
  44. onehalf:if(pi_money == 2'b01)
  45. state <= two;
  46. else if(pi_money == 2'b10)
  47. state <= idle;
  48. else
  49. state <= onehalf;
  50. two : if(pi_money == 2'b01)
  51. state <= idle;
  52. else if(pi_money== 2'b10)
  53. state <= idle;
  54. else
  55. state <= two;
  56. default: state <= idle;
  57. endcase
  58. //组合逻辑描述输出
  59. always @ (posedge clk or negedge rst_n)
  60. if (rst_n == 1'b0)
  61. state <= idle;
  62. else if (((state == two) && (pi_money == 2'b01)) || ((state==onehalf) && (pi_money==2'b10)))
  63. //使用并行块非阻塞赋值
  64. fork
  65. po_cola_p <= 1'b1;
  66. po_money_p <= 1'b0;
  67. join
  68. else if ((state == two )&& (pi_money == 2'b10))
  69. fork
  70. po_cola_p <= 1'b1;
  71. po_money_p <= 1'b1;
  72. join
  73. else
  74. fork
  75. po_cola_p <= 1'b0;
  76. po_money_p <= 1'b0;
  77. join
  78. //将寄存器值分配给输出
  79. assign po_cola=po_cola_p;
  80. assign po_money=po_money_p;
  81. endmodule

五、编写仿真文件

  1. `timescale 1ns / 1ps
  2. module cola_fsm2_tb(
  3. );
  4. reg clk,rst_n,pi_money_one,pi_money_half;
  5. reg random;
  6. wire po_money,po_cola;
  7. always #20 clk = ~clk; //产生一个以40ns为周期的时钟
  8. //在前半个时钟使复位键处于高电平
  9. initial
  10. begin
  11. rst_n <= 1'b0;
  12. clk <= 1'b1;
  13. #20
  14. rst_n <= 1'b1;
  15. end
  16. //将投币面值设置为随机数,
  17. always @(posedge clk or negedge rst_n)
  18. if(rst_n == 1'b0)
  19. random=0;
  20. else
  21. random <= {$random}%2;
  22. always @(posedge clk or negedge rst_n)
  23. if(rst_n == 1'b0)
  24. fork
  25. pi_money_half <= 1'b0;
  26. pi_money_one <= 1'b0;
  27. join
  28. else
  29. fork
  30. pi_money_one <= random;
  31. pi_money_half <= ~random;
  32. join
  33. //将状态和输入硬币与引用模块的成员连接
  34. wire [2:0] state=cola_fsm2_tb.state;
  35. wire [1:0] pi_money=cola_fsm2_tb.pi_money;
  36. initial
  37. begin
  38. $timeformat(-9,0,"ns",6);//设置仿真时间格式,-9表示时间单位为ns、精度为1ns
  39. //监视信号的值并在控制台上显示,监视的信号有变化时自动更新
  40. $monitor("time=%t,state=%b,random=%b,po_money=%b,po_cola=%b",$time,state,random,po_money,po_cola);
  41. end
  42. //引用源模块
  43. cola_fsm2 cola_fsm2_tb(
  44. .clk(clk),
  45. .rst_n(rst_n),
  46. .pi_money_one(pi_money_one),
  47. .pi_money_half(pi_money_half),
  48. .po_cola(po_cola),
  49. .po_money(po_money)
  50. );
  51. endmodule

六、仿真结果分析

 观察仿真结果可知:在第2、3个时钟周期分别投入了0.5元,第4、5个时钟周期分别投入了1元,共计3元,此时state值为4(two状态),因为是非阻塞赋值,所以在下一个时钟周期才会吐出可乐和找零0.5元,同时state跳转为0(idle状态)。

声明:此实验为野火FPGA状态机教程之二,基本架构相同,代码有所修改,欢迎交流讨论。

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

闽ICP备14008679号