学fpga(状态机)
Posted 费晓行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学fpga(状态机)相关的知识,希望对你有一定的参考价值。
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
软件开发中也用状态机,但软件开发除了状态机,还有多线程、网络、并发、数据库、GUI、线程互斥等很多东西。而fpga的状态机则使用的纯粹的多,范围也广的多。一个复杂的功能,如果没有模块的切分,没有状态机的设计,大概率是没有办法完整跑起来的。
可以用一个范例来说明状态机。假设有一个自动贩卖机。贩卖机有两个入口,两个出口。两个入口中,一个是投币入口,一个取消入口。两个出口,一个代表出货的出口,另外一个代表退币的出口。我们可以画一个图表示一下。
可以继续假设我们有一个商品,比如说是一瓶可乐,三块。一次投币只能投一块钱。连续投三次之后,就可以从出货口那里得到商品。在这过程中,如果按下了quit,那么就会吐出之前所有的硬币,重新开始。大家可以思考一下,这中间会有几个状态,
一开始没有硬币的时候,可以默认为idle状态。后面慢慢投币了,那么就有coin1、coin2、coin3三种状态。idle、coin1、coin2有两个输入,即投币和取消。而coin3只是一个过渡状态,在这个状态,输出商品后,马上就恢复到idle状态了。
状态机设计好了,下面就是进行verilog模块切分了,这里投币和取消的输入,我们可以用key来代替。
从上面的图形中,可以发现整个系统有3个模块组成。两个按键模块,一个状态机模块。按键模块主要是同一个模块实例化两次,再设计一个状态机模块就可以了。目前状态机模块主要采用的方法是三段论,第一个是状态切换,第二个是状态判断,第三个不同状态下的输入输出判断。
always@(posedge clk or posedge rst)
if(rst)
state <= IDLE_STATE;
else
state <= next_state;
always @(*)
next_state = IDLE_STATE;
case state
IDLE_STATE:
if(flag1)
next_state = COIN1_STATE;
else
next_state = state;
COIN1_STATE:
if(flag1)
next_state = COIN2_STATE;
else if(flag2)
next_state = IDLE_STATE;
else
next_state = state;
COIN2_STATE:
if(flag1)
next_state = COIN3_STATE;
else if(flag2)
next_state = IDLE_STATE;
else
next_state = state;
COIN3_STATE:
next_state = IDLE_STATE;
default:
next_state = IDLE_STATE;
有了状态,不管是输出商品,还是退币处理,这就好办了。
always @(posedge clk or posedge rst)
if(rst)
product <= 1'b0;
else if(state == COIN3_STATE)
product <= 1'b1;
else
product <= 1'b0;
always @(posedge clk or posedge rst)
if(rst)
coin <= 1'b0;
else if(flag2 && (state == COIN1_STATE || state == COIN2_STATE)
coin <= 1'b1;
else
coin <= 1'b0;
上面这两部分就是完整的状态机处理流程,剩下来的就是集成工作。有兴趣的同学可以把这段代码port到fpga开发板上面,实际测试一下。
module store(clk, rst, key1, key2, product, coin)
input clk;
input rst;
input key1;
input key2;
output produt;
output coin;
wire clk;
wire rst;
wire key1;
wire key2;
reg product;
reg coin;
wire flag1;
wire flag2;
key key1(
.clk(clk),
.rst(rst),
.key(key1),
.flag(flag1)
);
key key2(
.clk(clk),
.rst(rst),
.key(key2),
.flag(flag2)
);
state_machine sm(
.clk(clk),
.rst(rst),
.flag1(flag1),
.flag2(flag2),
.product(product),
.coin(coin)
);
endmodule();
以上是关于学fpga(状态机)的主要内容,如果未能解决你的问题,请参考以下文章