Verilog可乐售卖机(FSM)

状态机就是一种能够描述具有逻辑顺序和时序顺序事件的方法。

状态机有两大类:Mealy型和Moore型。

Moore型状态机的输出只与当前状态有关,而Mealy型状态机的输出不仅取决于当前状态,还受到输入的直接控制,并且可能与状态无关。

下面本例程使用的为Mealy状态机,因为这样使用可以有尽可能少的状态的个数,减少内存资源的占用量。

可乐售价为2.5元

投币有两种选项:投入1元或者投入5角;

当投入综合为2.5元时出可乐,当投入总和满3元时,找零0.5元。

则状态转移图如下:

Verilog代码如下

module complex_fsm
(
	input wire sys_clk,
	input wire sys_rst_n,
	input wire pi_money_half,
	input wire pi_money_one,
	output reg po_cola,
	output	reg po_money
);
//分别用0,1,2,3,4表示状态转移图中的五个状态
parameter IDLE=3'b000,HALF=3'b001,ONE=3'b010,ONE_HALF=3'b011,TWO=3'b100;
reg [2:0] state;
wire [1:0] pi_money;
//00表示没有投入,01表示投入五角,10表示投入一元
assign pi_money={pi_money_one,pi_money_half};

always@(posedge sys_clk or negedge sys_rst_n)//状态转移过程
	if(sys_rst_n==1'b0)
		state<=IDLE;
	else case(state)
		IDLE:if(pi_money==2'b01)
				state<=HALF;
			else if(pi_money==2'b10)
				state<=ONE;
			else
				state<=IDLE;
		HALF:if(pi_money==2'b01)
				state<=ONE;
			else if(pi_money==2'b10)
				state<=ONE_HALF;
			else
				state<=HALF;
		ONE:if(pi_money==2'b01)
				state<=ONE_HALF;
			else if(pi_money==2'b10)
				state<=TWO;
			else
				state<=ONE;
		ONE_HALF:if(pi_money==2'b01)
				state<=TWO;
			else if(pi_money==2'b10)
				state<=IDLE;
			else
				state<=ONE_HALF;
		TWO:if(pi_money==2'b01||pi_money==2'b10)
				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(((state==ONE_HALF)&&(pi_money==2'b10))
		||((state==TWO)&&(pi_money==2'b01))
		||((state==TWO)&&(pi_money==2'b10))
	)
		po_cola<=1'b1;
	else
		po_cola<=1'b0;
		
always@(posedge sys_clk or negedge sys_rst_n)//找零输出条件
	if(sys_rst_n==1'b0)
		po_money<=1'b0;
	else if((state==TWO)&&(pi_money==2'b10))
		po_money<=1'b1;
	else
		po_money<=1'b0;
	
endmodule

仿真测试代码如下:

`timescale 1ns / 1ns

module tb_complex_fsm();

reg sys_clk;
reg sys_rst_n;
reg pi_money_half;
reg pi_money_one;
reg random_data;
wire po_cola;
wire po_money;

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)
		random_data<=1'b0;
	else
		random_data<={$random}%2;
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n===1'b0)
		pi_money_half<=1'b0;
	else
		pi_money_half<=random_data;
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n===1'b0)
		pi_money_one<=1'b0;
	else
		pi_money_one<=~random_data;//不可能同时投入五角或者一元,所以要用取反操作
//用两根线引出来表示内部变量		
wire [1:0] pi_money=complex_fsm_inst.pi_money;
wire [4:0] state=complex_fsm_inst.state;

complex_fsm complex_fsm_inst
(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.pi_money_half(pi_money_half),
.pi_money_one(pi_money_one),
.po_cola(po_cola),
.po_money(po_money)
);

endmodule

vivado仿真波形图 

 由于时钟周期的作用,当投入五角或者一元时,输出不会立马改变,输出要等到下一个时钟周期才能产生变化。

state=0表示投入总和为0元

state=1表示投入综合为0.5元

state=2表示投入综合为1元

state=3表示投入综合为1.5元

state=4表示投入综合为2元

vivado波形缩小

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值