状态机代码写法
一段式
在一段状态机中,使用时序逻辑既描述状态的转移又描述输入输出。
二段式
分两段状态机,在第一段状态机中描述状态的转移,在第二段中描述输入输出。
三段式
分三段。第一段中采用时序逻辑描述状态的转移,第二段中采用组合逻辑,判断转移条件,描述转移规律,第三段状态机中描述状态输出,可使用组合逻辑或者时序逻辑。
案例一(简单可乐机)
代码以及输出
//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
*/
仿真
困了,累了,懒,一天写一个都没有。。。。