在verilog中状态机的一种很常用的逻辑结构,学习和理解状态机的运行规律能够帮助我们更好地书写代码,同时作为一种思想方法,在别的代码设计中也会有所帮助。
一、简介
在使用过程中我们常说的是有限状态机(Finite-State Machine,FSM),简称为状态机,表示在有限个状态以及这些状态之间的转移和动作等行为的数学模型。
二、分类
在verilog中常使用的状态机可以分为两类,分别是Moore(摩尔)状态机和Mealy(米利)状态机。两种状态机的主要区别在于****Moore状态机的输出只与当前状态有关,与当前输入无关;Mealy状态机的输出不仅与当前状态有关,还与当前的输入信号有关 。
三、设计实例
在状态机设计的过程中推荐使用三段式设计,下面是三段式状态机的基本结构:
(1)状态机第一段,时序逻辑,非阻塞赋值,传递状态机的状态 ;
(2)状态机第二段,组合逻辑,阻塞赋值 ,根据当前状态和当前输入, 确定下一个状态机的状态 ;
(3)状态机第三段,时序逻辑,非阻塞赋值,确定输出信号 。
下面介绍一个简单的状态机设计实例:一个学生,一周七天周一到周五需要上学,单周周六巩固复习这一周的知识,周日出去玩;双周周六周日出去玩。可以得到状态转移图如下:
设计代码如下:
`timescale 1ns / 1ps
module FSM(
input clk,
input rst_n,
input [2:0] week,
input odd_even,
output [1:0] activity
);
parameter learn = 2'd0;
parameter review= 2'd1;
parameter play = 2'd2;
reg [1:0] st_cur;
reg [1:0] st_next;
always @ (posedge clk or negedge rst_n)begin //Update the current status
if(!rst_n)begin
st_cur <= learn;
end
else begin
st_cur <= st_next;
end
end
always @(*)begin //Determine the next status
case(st_cur)
learn:
case(week)
3'd5: begin
if(odd_even)
st_next = review;
else
st_next = play;
end
3'd6:begin
st_next = play;
end
3'd7:begin
st_next = learn;
end
default:st_next = learn;
endcase
review: st_next = play;
play :
case(week)
3'd7: st_next = learn;
default: st_next = play;
endcase
default: st_next = st_next;
endcase
end
reg [1:0] activity_r;
always @(posedge clk or negedge rst_n)begin //Output signal
if(!rst_n)
activity_r <= 2'd0;
else
activity_r <= st_next;
end
assign activity = activity_r;
endmodule
仿真代码如下:
`timescale 1ns / 1ps
module FSM_tb;
reg clk;
reg rst_n;
reg [2:0] week;
reg odd_even;
wire [1:0] activity;
initial begin
clk <= 1'b0;
rst_n <= 1'b0;
odd_even <= 1'b0;
week <= 3'd1;
#10
rst_n <= 1'b1;
end
always #10
clk = ~clk;
always @(posedge clk)begin
week <= week + 3'd1;
if(week == 3'd7)begin
odd_even <= ~odd_even;
week <= 3'd1;
end
end
FSM fsm_inst(
.clk(clk),
.rst_n(rst_n),
.week(week),
.odd_even(odd_even),
.activity(activity)
);
endmodule
仿真结果如下图所示:
对状态机的理解需要大量的实际操作,孰能生巧,在我学习的过程中老师曾要求我们用状态机写 万年历 ,对于感兴趣的同学来说也可以进行尝试。
全部0条评论
快来发表一下你的评论吧 !