【verilog】浅复习状态机(FSM)

状态机代码写法

一段式

在一段状态机中,使用时序逻辑既描述状态的转移又描述输入输出。

二段式

分两段状态机,在第一段状态机中描述状态的转移,在第二段中描述输入输出。

三段式

分三段。第一段中采用时序逻辑描述状态的转移,第二段中采用组合逻辑,判断转移条件,描述转移规律,第三段状态机中描述状态输出,可使用组合逻辑或者时序逻辑。

案例一(简单可乐机)

在这里插入图片描述

代码以及输出

//cola.v
module cola(
//输入信号 时钟信号 复位信号 投币
input wire clk,
input wire rst_n,
input wire money,

//输出信号
output reg cola
);
//定义状态参数 使用独热码编码
parameter IDLE = 3'b000;
parameter ONE = 3'b010;
parameter TWO = 3'b100;
//独热码 每个状态下编码只有一位是高电平 其他都是低电平 几个状态用几位编码
reg[2:0] state;
always @(posedge clk or negedge rst_n)
if(rst_n == 1'b0)//rst==1 复位信号有效
state <= IDLE;
else case(state)
	IDLE:if(money == 1'b1)
	state <= ONE;
	else
	state <= IDLE;
	ONE: if(money == 1'b1)
	state <= TWO;
	else
	state <= ONE;
	TWO:if(money == 1'b1)
	state <= IDLE;
	else
	state <= TWO;
	default:state <= IDLE;
endcase

always @ (posedge clk or negedge rst_n)//begin
if(rst_n == 1'b0)
cola <= 1'b0;
else if((state == TWO)&&(money == 1'b1))
cola <= 1'b1;
else
cola <= 1'b0;
//end
endmodule
//cola_tb.v
`timescale 1ns/1ns
module cola_tb();
reg clk;
reg rst_n;
reg money;
wire cola;
//初始化系统时钟,全局复位
initial begin
	clk = 1'b1;
	rst_n <= 1'b0;//复位有效
	#20
	rst_n <= 1'b1;//复位无效
end
//clk模拟时钟系统 每10ns电平翻转一次 周期为20ns 频率为 50mhz
always #10 clk = ~clk;
//产生输入随机数 模拟投币一元的情况
always @ (posedge clk or negedge rst_n)
if(rst_n == 1'b0)
money <= 1'b0;
else
money <= {$random}%2;//取模求余数 产生随机数 0、1
wire[2:0] state = cola0.state;
initial 
begin
	$timeformat(-9,0,"ns",6);
	$monitor("@time %t: money=%b state=%b cola=%b",$time,money,state,cola);
end
//开始实例化
cola cola0(
.clk(clk),
.rst_n(rst_n),
.money(money),
.cola(cola)
);
endmodule
/*run
# @time    0ns: money=0 state=000 cola=0
# @time   40ns: money=1 state=000 cola=0
# @time   60ns: money=1 state=010 cola=0
# @time   80ns: money=1 state=100 cola=0
run
# @time  100ns: money=1 state=000 cola=1
# @time  120ns: money=1 state=010 cola=0
# @time  140ns: money=1 state=100 cola=0
# @time  160ns: money=0 state=000 cola=1
# @time  180ns: money=1 state=000 cola=0
run
# @time  200ns: money=1 state=010 cola=0
# @time  220ns: money=0 state=100 cola=0
# @time  240ns: money=1 state=100 cola=0
# @time  260ns: money=1 state=000 cola=1
# @time  280ns: money=0 state=010 cola=0
add wave  \
sim:/cola_tb/clk \
sim:/cola_tb/rst_n \
sim:/cola_tb/money \
sim:/cola_tb/cola \
sim:/cola_tb/state
run
# @time  300ns: money=1 state=010 cola=0
# @time  320ns: money=0 state=100 cola=0
# @time  340ns: money=1 state=100 cola=0
# @time  360ns: money=0 state=000 cola=1
# @time  380ns: money=1 state=000 cola=0
run
# @time  400ns: money=1 state=010 cola=0
# @time  420ns: money=0 state=100 cola=0
# @time  440ns: money=1 state=100 cola=0
# @time  460ns: money=0 state=000 cola=1
# @time  480ns: money=0 state=000 cola=0
run
# @time  520ns: money=1 state=000 cola=0
# @time  540ns: money=0 state=010 cola=0
# @time  560ns: money=1 state=010 cola=0
# @time  580ns: money=1 state=100 cola=0
run
# @time  600ns: money=1 state=000 cola=1
# @time  620ns: money=1 state=010 cola=0
# @time  640ns: money=0 state=100 cola=0

*/


仿真

在这里插入图片描述

案例二(可以找零的可乐机)

简单分析一下它的状态:

一听可乐是2.5元
输入:0.5、1
输出:不出可乐不找零、不出可乐找零 、出可乐不找零、出可乐找零
状态:不投币(00)、投0.5元(01)、投1元(10)
不出可乐不找零(00)、出可乐找零(01)、出可乐不找零(10)

代码:

//cola2.v
module cola2(
input wire rst,
input wire clk,
input wire pi_money_half,
input wire pi_money_one,
output reg po_money, //找零
output reg po_cola//出可乐
);
//五种状态使用独热码
parameter IDLE = 5'b00001;
parameter HALF = 5'b00010;
parameter ONE = 5'b00100;
parameter ONE_HALF= 5'b01000;
parameter TWO = 5'b10000;

reg [4:0]state;
wire [1:0] pi_money;
assign  pi_money = {pi_money_one,pi_money_half};//00 01 10 
//第一段状态机,描述当前状态state如何根据输入跳转到下一个状态
always @ (posedge clk or posedge rst)begin
if(rst == 1'b1)begin
	state <= IDLE;
end
else begin
case(state)
	IDLE:begin 
		if(pi_money == 2'b01)begin//pi_one = 0 pi_half= 1 输入0.5	
		  state <= HALF;
	end
	else if(pi_money == 2'b10)begin
		state <= ONE;
	end
	else begin
		state <= IDLE;
	end
end
HALF:begin
	if(pi_money == 2'b01) begin
		state <= ONE;
	end
	else if(pi_money == 2'b10)begin
		state <= ONE_HALF;
	end
	else begin
		state <= HALF;
	end
end
ONE:begin
	if(pi_money == 2'b01)begin
		state <= ONE_HALF;
	end
	else if(pi_money == 2'b10)begin
		state <= TWO;
	end
	else begin
		state <= ONE;
	end
end
ONE_HALF:begin
	if(pi_money == 2'b01)begin
		state <= TWO;
	end
	if(pi_money == 2'b10)begin
		state <= IDLE;
	end
	else begin
		state <= ONE_HALF;
	end
end
TWO:begin
	if(pi_money == 2'b01)begin
 state <= IDLE;
end
else if(pi_money == 2'b10)begin
	state <= IDLE;
end
else begin
	state <= TWO;
end
end
default://begin
	state <= IDLE;
//end
endcase
end
end
//第二段状态机 描述当前状态state和输入pi_money如何影响po_cola的输出
always @ (posedge clk or posedge rst)begin
	if(rst == 1'b1)begin
		po_cola <= 1'b0;
	end
	else if((state == TWO&&pi_money == 2'b01)||(state == TWO&&pi_money == 2'b10)||(state == ONE_HALF&&pi_money == 2'b10))begin
		po_cola <= 1'b1;
	end
	else begin
		po_cola <= 1'b0;
	end
end
//第二段状态机 描述当前状态state和输入pi_money如何影响po_money输出
always @ (posedge clk or posedge rst)begin
	if(rst == 1'b1)begin
		po_money <= 1'b0;
	end
	else if((state == TWO)&&(pi_money == 2'b10))begin
		po_money <= 1'b1;
	end
	else begin
	po_money <= 1'b0;
end
end
endmodule

tb

//cola2_tb.v
`timescale 1ns/1ns
module cola2_tb();
reg clk;
reg rst;
reg pi_money_one;
reg pi_money_half;
reg random_data;//随机数

wire po_money;
wire po_cola;

//初始化系统时钟、全局复位
initial begin
	clk = 1'b1;
	rst <= 1'b1;
	#20 //延时20ns
	rst <= 1'b0;
end
//clk:模拟系统时钟,每10ns电平翻转一次,周期为20ns,频率50mhz
always #10 clk = ~clk;
//radom_data:产生随机数 0 1
always @(posedge clk or posedge rst)begin
	if(rst == 1'b1)begin
		random_data <= 1'b0;
	end
	else begin
		random_data <= {$random}%2;
	end
end
//pi_money_one:模拟投入一元的情况
always @(posedge clk or posedge rst)begin
	if(rst == 1'b1)begin
		pi_money_one <= 1'b0;
	end
	else begin
		pi_money_one <=random_data;
	end
end
//pi_money_half:模拟投入五毛的情况
always @(posedge clk or posedge rst)begin
	if(rst == 1'b1)begin
		pi_money_half <= 1'b0;
	end
	else begin
		pi_money_half <= ~random_data;//不可以同时投入五毛和一元
	end
end
//将rtl模块中的内部信号引入到testbench模块中观察
wire [4:0] state = cola2_0.state;
wire [1:0] pi_money = cola2_0.pi_money;

initial begin
	$timeformat(-9,0,"ns",6);
	$monitor("@time %t :pi_money_one=%b pi_money_half=%b pi_money=%b state=%b po_cola=%b po_money=%b",$time,pi_money_one,pi_money_half,pi_money,state,po_cola,po_money);
end
//例化
cola2 cola2_0(
.clk(clk),
.rst(rst),
.pi_money_one(pi_money_one),
.pi_money_half(pi_money_half),
.po_cola(po_cola),
.po_money(po_money)
);
endmodule
/*run
# @time    0ns :pi_money_one=0 pi_money_half=0 pi_money=00 state=00001 po_cola=0 po_money=0
# @time   40ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=0 po_money=0
# @time   60ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
# @time   80ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
run
# @time  100ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time  120ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time  140ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=10000 po_cola=0 po_money=0
# @time  160ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=1
# @time  180ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
run
# @time  200ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  220ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time  240ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time  260ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  280ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
run
# @time  300ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time  320ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  340ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
# @time  360ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
# @time  380ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=01000 po_cola=0 po_money=0
run
# @time  400ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  420ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time  440ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time  460ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  480ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
run
# @time  500ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00010 po_cola=0 po_money=0
# @time  520ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time  540ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  560ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
# @time  580ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
run
# @time  600ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  620ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time  640ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time  660ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=10000 po_cola=0 po_money=0
# @time  680ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
run
# @time  700ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00010 po_cola=0 po_money=0
# @time  720ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time  740ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  760ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
# @time  780ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
run
# @time  800ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time  820ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time  840ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time  860ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=10000 po_cola=0 po_money=0
# @time  880ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=1
run
# @time  900ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00010 po_cola=0 po_money=0
# @time  920ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time  940ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=10000 po_cola=0 po_money=0
# @time  960ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=1
# @time  980ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
*/

仿真

在这里插入图片描述困了,累了,懒,一天写一个都没有。。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值