FPGA的学习:状态机的实现
Posted 石小舟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FPGA的学习:状态机的实现相关的知识,希望对你有一定的参考价值。
用代码来实现时序图。
`timescale 1ns/1ns
module complex_fsm
(
input wire sys_clk , //系统时钟50MHz
input wire sys_rst_n , //全局复位
input wire pi_money_one , //投币1元
input wire pi_money_half , //投币0.5元
output reg po_money , //po_money为1时表示找零
//po_money为0时表示不找零
output reg po_cola //po_cola为1时出可乐
//po_cola为0时不出可乐
);
//只有五种状态,使用独热码
parameter IDLE = 5'b00001;
parameter HALF = 5'b00010;
parameter ONE = 5'b00100;
parameter ONE_HALF = 5'b01000;
parameter TWO = 5'b10000;
//reg define
reg [4:0] state;
//wire define
wire [1:0] pi_money;
//pi_money:为了减少变量的个数,我们用位拼接把输入的两个1bit信号拼接成1个2bit信号
//投币方式可以为:不投币(00)、投0.5元(01)、投1元(10),每次只投一个币
assign pi_money = {pi_money_one, pi_money_half};
//第一段状态机,描述当前状态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 == 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
//第二段状态机,描述当前状态state和输入pi_money如何影响po_cola输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
po_cola <= 1'b0;
else if((state == TWO && pi_money == 2'b01) || (state == TWO &&
pi_money == 2'b10) || (state == ONE_HALF && pi_money == 2'b10))
po_cola <= 1'b1;
else
po_cola <= 1'b0;
//第二段状态机,描述当前状态state和输入pi_money如何影响po_money输出
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 define
reg sys_clk;
reg sys_rst_n;
reg pi_money_one;
reg pi_money_half;
reg random_data_gen;
//wire define
wire po_cola;
wire po_money;
//初始化系统时钟、全局复位
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
//sys_clk:模拟系统时钟,每10ns电平翻转一次,周期为20ns,频率为50MHz
always #10 sys_clk = ~sys_clk;
//random_data_gen:产生非负随机数0、1
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
random_data_gen <= 1'b0;
else
random_data_gen <= {$random} % 2;
//pi_money_one:模拟投入1元的情况
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_gen;
//pi_money_half:模拟投入0.5元的情况
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pi_money_half <= 1'b0;
else
//取反是因为一次只能投一个币,即pi_money_one和pi_money_half不能同时为1
pi_money_half <= ~random_data_gen;
//将RTL模块中的内部信号引入到Testbench模块中进行观察
wire [4:0] state = complex_fsm_inst.state;
wire [1:0] pi_money = complex_fsm_inst.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
complex_fsm complex_fsm_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.pi_money_one (pi_money_one ), //input pi_money_one
.pi_money_half (pi_money_half ), //input pi_money_half
.po_cola (po_cola ), //output po_money
.po_money (po_money ) //output po_cola
);
endmodule
以上是关于FPGA的学习:状态机的实现的主要内容,如果未能解决你的问题,请参考以下文章