【FPGA】状态机的理论学习与实战演练(1元硬币可乐机系统)

一、理论部分

状态机的作用:FPGA为并行执行的,若想处理具有前后顺序的事件,则需要用到状态机。
在这里插入图片描述
Moore型状态机:输出只与当前状态有关,而与输入无关。
Mealy型状态机:输出与当前状态、输入均有关。
共同点是状态的跳转都只和输入有关。

二、模块框图

在这里插入图片描述
包含三个输入信号:系统时钟(sys_clk)、复位信号(sys_rst_n)以及投币信号(pi_money)。
一个输出信号:输出可乐(po_cola)。

三、状态转移图

(一次投币信号算作投币一元,故每三次投币信号才能输出一个可乐)
在这里插入图片描述
“/”左边为输入,右边为输出。
Mealy型状态机状态转移图:
在这里插入图片描述
Moore型状态机状态转移图:
在这里插入图片描述
因Mealy型状态机更节省逻辑资源,故使用Mealy型状态机完成本实验。

四、波形图

1、时钟与复位信号

在这里插入图片描述

2、投币信号

(随机画出)
在这里插入图片描述

3、状态信号

在这里插入图片描述

4、输出信号

在这里插入图片描述

五、代码部分

1、三种码型

独热码:
综合时节省组合逻辑的资源,但位宽较长。
在这里插入图片描述
二进制码:
位宽少,因此减少了寄存器资源的使用,但综合器综合时无法进行比较器的优化,因此使用的组合逻辑资源较多。
在这里插入图片描述
格雷码(相邻参数只有一个比特不同,例如00与01,01与11):
状态数较多(位宽较大)时使用,寄存器资源使用较少,组合逻辑资源使用较多,
在这里插入图片描述
以上三种编码均可,因FPGA中组合逻辑资源较少,相对来说寄存器资源较多,所以使用独热码较好,此实验采用独热码。

总结:
低速系统中,如果状态机状态的个数小于四个,使用二进制码;
状态个数介于4~24个,使用独热码,
状态个数大于24个,使用格雷码。
高速系统中,无论状态个数是多少,最好都使用独热码。

2、状态机的三种写法

一段式:
在一段的状态机中使用时序逻辑,即描述状态的转移,又描述状态的输出。
较难表述大型状态机。

二段式:
分两段状态机,第一段状态机中使用时序逻辑描述状态的转移;在第二段状态机中使用组合逻辑描述数据的输出。
结构和理想的理论模型完全吻合,但第二段为组合逻辑,部分情况无法准确描述。

三段式:
第一段状态机中使用时序逻辑描述状态转移;第二段状态机中采用组合逻辑判断状态转移条件,描述状态转移规律;第三段状态机中描述状态转移输出,组合逻辑与时序逻辑均可。

此实验采用新式二段式状态机,均使用时序逻辑进行描述。
第一个always块描述状态的转移,第二个always块描述输出信号。

3、Verilog代码

module simple_fsm
(
input wire sys_clk,
input wire sys_rst_n,
input wire pi_money,

output reg po_cola
);
parameter IDLE = 3'b001;
parameter ONE  = 3'b010;
parameter TWO  = 3'b100;

reg [2:0] state;

always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0)
		  state <= IDLE;
		else case(state)
		  IDLE: if(pi_money == 1'b1)
		           state <= ONE;
				  else
				     state <= IDLE;
		  ONE:  if(pi_money == 1'b1)
		           state <= TWO;
				  else
				     state <= ONE;
		  TWO:  if(pi_money == 1'b1)
		           state <= IDLE;
				  else
				     state <= TWO;
		  default:state <= IDLE;
	  endcase
				  	  
always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0)
		  po_cola <= 1'b0;
		else if((pi_money == 1'b1)&&(state == TWO))
		  po_cola <= 1'b1;
		else
		  po_cola <= 1'b0;
		  
endmodule

4、tb仿真代码

`timescale 1ns/1ns
module tb_simple_fsm();
reg sys_clk;
reg sys_rst_n;
reg pi_money;

wire po_cola;

initial
    begin
	    sys_clk = 1'b1;
		 sys_rst_n <= 1'b0;
		 #20
		 sys_rst_n <= 1'b1;
	 end
	 
always #10 sys_clk = ~sys_clk;

always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0)
		   pi_money <= 1'b0;
		else
		   pi_money <= {$random} % 2;
			
wire [2:0] state = simple_fsm_inst.state;

initial
     begin
	     $timeformat(-9,0,"ns",6);
		  $monitor("@time %t:pi_money=%b,state=%b,po_cola=%b",$time,pi_money,state,po_cola);
	  end
	  

simple_fsm simple_fsm_inst
(
   .sys_clk(sys_clk),
	.sys_rst_n(sys_rst_n),
	.pi_money(pi_money),
	
	.po_cola(po_cola)
);
endmodule

六、结果及仿真

1、综合器综合出的状态转移图

在这里插入图片描述
在这里插入图片描述

2、仿真波形

在这里插入图片描述
经分析,与开始手动绘制的波形图吻合,结果正确,此处不再上传上板验证结果。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值