• 状态机练习(饮料贩卖机程序设计)8/9


    关于状态机的基础知识可以访问以下链接学习:verilog中级语法之同步状态机原理和设计(十二)_ICer吼吼的博客-CSDN博客_同步状态机状态机https://blog.csdn.net/weixin_45680021/article/details/125286469

    补充:

    一段式、二段式、三段式状态机区别:

    一段式就是把状态,输入,输出都放在一个always里面;

    二段式就是一个always语句来实现时序逻辑,另外一个always语句来实现组合逻辑,需要定义现态和次态两个状态(current_state, next_state);

    三段式就是把二段式中组合逻辑的输出单独提出来再放一个always用非阻塞方式输出,有效去掉二段式中组合逻辑直接用阻塞方式输出存在的毛刺问题 。

    一般建议使用三段式描述法

     有限状态机(FSM):

    •    状态机是绝大部分数字控制电路的核心结构。
    •    
    moore有限状态机:输出仅依赖于内部状态,跟输入无关。
    •    mealy有限状态机:输出不仅决定于内部状态,还跟外部输入有关。
    •    有限状态机可以使用always语句和case语句描述,状态保存在寄存器中,根据寄存器不同的值(状态)执行不同的操作,case语句的多个分支则代表了不同状态的行为。

    练习: 

     两段式描述:

    1. //二段式状态机设计
    2. module fsm1(ds,rd,go,ws,clk,rst_n);
    3. output ds,rd;
    4. input go,ws;
    5. input clk, rst_n;
    6. reg ds,rd;
    7. parameter [1:0] IDLE=2'b00,
    8. READ=2'b01,
    9. DLY=2'b10,
    10. DONE=2'b11;
    11. reg [1:0] state,next;
    12. always@(posedge clk or negedge rst_n); //定义初始状态
    13. if(!rst_n)
    14. state<=IDLE;
    15. else
    16. state<=next;
    17. always@(state or go or ws) begin //定义下一个状态和输出
    18. next=2'bx;
    19. ds=1'b0;
    20. rd=1'b0;
    21. case(state)
    22. IDLE:if(go)
    23. next=READ;
    24. else
    25. next=IDLE;
    26. READ: begin
    27. next=DLY;
    28. rd=1'b1;
    29. end
    30. DLY: begin
    31. rd=1'b1;
    32. if(ws)
    33. next=READ;
    34. else
    35. next=DONE;
    36. end
    37. DONE: begin
    38. ds=1'b1;
    39. next=IDLE;
    40. end
    41. endcase
    42. end
    43. endmodule

     三段式描述:

    1. //三段式状态机设计
    2. module fsm1b(ds,rd,go,ws,clk,rst_n);
    3. output ds,rd;
    4. input go,ws;
    5. input clk,rst_n;
    6. reg ds,rd;
    7. parameter [1:0] IDLE=2'b00,
    8. READ=2'b01,
    9. DLY=2'b10,
    10. DONE=2'b11;
    11. reg [1:0] state,next;
    12. always@(posedge clk or negedge rst_n) //定义初始状态
    13. if(!rst_n)
    14. state<=IDLE;
    15. else
    16. state<=next;
    17. always@(state or go or ws) begin //状态转换
    18. next=2'bx;
    19. case(state)
    20. IDLE:
    21. if(go)
    22. next=READ;
    23. else
    24. next=IDLE;
    25. READ:
    26. next=DLY;
    27. DLY:
    28. if(ws)
    29. next=READ;
    30. else
    31. next=DONE;
    32. DONE:
    33. next=IDLE;
    34. endcase
    35. end
    36. always@(posedge clk or negedge rst_n)//输出
    37. if(!rst_n) begin
    38. ds<=1'b0;
    39. rd<=1'b0;
    40. end
    41. else begin
    42. ds<=1'b0;
    43. rd<=1'b0;
    44. end
    45. case(state)
    46. IDLE:
    47. if(go)
    48. rd<=1'b1;
    49. READ:
    50. rd<=1'b1;
    51. DLY:
    52. if(ws)
    53. rd<=1'b1;
    54. else
    55. ds<=1'b1;
    56. endcase
    57. end
    58. endmodule

    贩卖机设计

    要求:简化考虑,假设饮料只有一种价格为2.5元。 硬币有0.5元和1.0元两种,考虑找零,用Verilog描述其控制电路。

    设计步骤分解:

    1.    分析输入输出端口信号;
    2.    状态转移图;
    3.    根据状态转移图进行Verilog 语言描述;
    4.    测试代码编写,仿真; 

    1.    输入输出端口信号分析 

    输入信号: clk,rst;
    输入信号:操作开始: op_start;          //定义1开始操作输入信号
    投币币值:   coin_val;                         //定义2’b01表示0.5元; 2’b10表示1元
    输入信号:取消操作指示 : cancel_flag;           //定义1为取消操作
    输出信号:机器是否占用: hold_ind;                 //定义0为不占用,可以使用
    输出信号:取饮料信号: drinktk_ind;                 //定义1为取饮料
    输出信号:找零与退币标志信号: charge_ind;  //定义1为找零 
    输出信号:找零与退币币值:charge_val;        //定义3’b001表示找0.5元;3’b010表示找1元;3’b011表示找1.5元; 3’b100表示找2.0元;

    说明:

    1.    在S0状态下,如果检测到op_start=1,开始检测是否有投币,如果有,一次新的售货操作开始;
    2.    在状态S1/S2/S3/S4下,如果检测到cancel_flag=1,则取消操作,状态返回S0,并退回相应的币值;
    3.    在状态S5下,卖出饮料不找零;在状态S6下,卖出饮料并找零;
    4.    在状态S5和S6 操作完后,都返回状态S0,等待下一轮新的操作开始;
    5.    只有在S0 状态下,hold_ind=0,可以发起新一轮操作,其它状态下都为1; 

    RTL代码:

    1. module softdrinkFSM(clk,rst,op_start,cancel_flag,coin_val,hold_ind,charge_ind,drinktk_ind,charge_val);
    2. input clk,rst;
    3. input op_start;
    4. input cancel_flag;
    5. input [1:0] coin_val;
    6. output hold_ind,charge_ind,drinktk_ind;
    7. output [2:0] charge_val;
    8. reg hold_ind,charge_ind,drinktk_ind;
    9. reg [2:0] charge_val;
    10. reg [2:0] currentstate,nextstate;
    11. parameter S0=3'b000;
    12. parameter S1=3'b001;
    13. parameter S2=3'b010;
    14. parameter S3=3'b011;
    15. parameter S4=3'b100;
    16. parameter S5=3'b101;
    17. parameter S6=3'b110;
    18. always@(posedge clk or posedge rst)
    19. if(rst)
    20. currentstate<=0;
    21. else
    22. currentstate<=nextstate;
    23. always@(currentstate or rst or op_start or cancel_flag or coin_val)
    24. if(rst)
    25. nextstate=S0;
    26. else
    27. case(currentstate)
    28. S0:
    29. if(op_start)
    30. if(coin_val==2'b01)
    31. nextstate=S1;
    32. else if(coin_val==2'b10)
    33. nextstate=S2;
    34. S1:
    35. if(cancel_flag)
    36. nextstate=S0;
    37. else if(coin_val==2'b01)
    38. nextstate=S2;
    39. else if(coin_val==2'b10)
    40. nextstate=S3;
    41. S2:
    42. if(cancel_flag)
    43. nextstate=S0;
    44. else if(coin_val==2'b01)
    45. nextstate=S3;
    46. else if(coin_val==2'b10)
    47. nextstate=S4;
    48. S3:
    49. if(cancel_flag)
    50. nextstate=S0;
    51. else if(coin_val==2'b01)
    52. nextstate=S4;
    53. else if(coin_val==2'b10)
    54. nextstate=S5;
    55. S4:
    56. if(cancel_flag)
    57. nextstate=S0;
    58. else if(coin_val==2'b01)
    59. nextstate=S5;
    60. else if(coin_val==2'b10)
    61. nextstate=S6;
    62. S5:
    63. nextstate=S0;
    64. S6:
    65. nextstate=S0;
    66. default:
    67. nextstate=S0;
    68. endcase
    69. always@(currentstate)
    70. if(currentstate==S0)
    71. hold_ind=0;
    72. else
    73. hold_ind=1;
    74. always@(currentstate)
    75. if((currentstate==S5)||(currentstate==S6))
    76. drinktk_ind=1'b1;
    77. else
    78. drinktk_ind=1'b0;
    79. always@(currentstate or cancel_flag)
    80. if(currentstate==S0)
    81. charge_ind=1'b0;
    82. else if(currentstate==S6)
    83. charge_ind=1'b1;
    84. else if(cancel_flag)
    85. charge_ind=1'b1;
    86. else
    87. charge_ind=1'b0;
    88. always@(currentstate or cancel_flag)
    89. if(currentstate==S0)
    90. charge_val=3'b000;
    91. else if(currentstate==S6)
    92. charge_val=3'b001;
    93. else if(cancel_flag) begin
    94. case(currentstate)
    95. S1:
    96. charge_val=3'b001;
    97. S2:
    98. charge_val=3'b010;
    99. S3:
    100. charge_val=3'b011;
    101. S4:
    102. charge_val=3'b100;
    103. default:
    104. charge_val=3'b000;
    105. endcase
    106. end
    107. else
    108. charge_val=3'b000;
    109. endmodule

    TB代码:

    1. //softdrinkFSM_td
    2. module softdrinkFSM_td;
    3. reg clk,rst;
    4. reg op_start;
    5. reg cancel_flag;
    6. reg [1:0] coin_val;
    7. wire hold_ind,charge_ind,drinktk_ind;
    8. wire [2:0] charge_val;
    9. initial begin
    10. clk=0;
    11. end
    12. always
    13. #500 clk=~clk;
    14. initial begin
    15. rst=0;
    16. op_start=0;
    17. cancel_flag=0;
    18. coin_val=2'b00;
    19. #25 rst=1;
    20. #25 rst=0;
    21. //第一次:依次投入一元,一元,一元的硬币
    22. #50 op_start=1;
    23. #300 coin_val=2'b10;
    24. #1000 coin_val=2'b10;
    25. #1000 coin_val=2'b10;
    26. #1000 op_start=0;
    27. //第二次:依次投入0.5元,一元,一元的硬币
    28. #2000 op_start=1;
    29. #300 coin_val=2'b01;
    30. #1000 coin_val=2'b10;
    31. #1000 coin_val=2'b10;
    32. #1000 op_start=0;
    33. //第三次:依次投入0.5元,一元的硬币,然后取消操作
    34. #2000 op_start=1;
    35. #300 coin_val=2'b01;
    36. #1000 coin_val=2'b10;
    37. #1000 cancel_flag=1'b1;
    38. op_start=0;
    39. #1000 cancel_flag=1'b0;
    40. //第四次:依次投入0.5元,0.5元,0.5元,0.5元,一元的硬币,然后取消操作
    41. #2000 op_start=1;
    42. #300 coin_val=2'b01;
    43. #1000 coin_val=2'b01;
    44. #1000 coin_val=2'b01;
    45. #1000 coin_val=2'b01;
    46. #1000 coin_val=2'b10;
    47. #1000 op_start=0;
    48. #1000000 $stop;
    49. end
    50. softdrinkFSM init(clk,rst,op_start,cancel_flag,coin_val,hold_ind,charge_ind,drinktk_ind,charge_val);
    51. endmodule

    波形:

    第一次:

    第二次:

    第三次:

    第四次:

  • 相关阅读:
    一场先进技术与先锋企业碰撞的知识盛宴!弘玑Cyclone『超级自动化的数字内生力量』CXO私享会成功举办
    gitlub 加载慢问题处理
    Python:函数调用的实参
    Sealos 是企业节省成本的终极武器
    模拟面试01
    一招解决Unity在Inspector面板显示代码时中文乱码问题
    C#中.NET 7.0 Windows窗体应用通过EF访问新建数据库
    LINUX初级 总结
    SpringCloudAlibaba SpringCloud SpringBoot 版本对照
    大模型在金融AIGC领域的前景与应用
  • 原文地址:https://blog.csdn.net/weixin_45680021/article/details/126211764