有限状态机(FSM)的输出取决于过去状态以及当前输入,是时序逻辑电路。适合描述那些发生有先后顺序或者有逻辑规律的事情,状态机的本质就是对具有逻辑顺序或时序规律的事件进行描述的一种方法,广泛用于多种场合。
因此,掌握有限状态机的Verilog描述方式至关重要;通过许多大神前辈的博客,我了解到状态机的描述具有三种方式,反思自己之前的描述深感逻辑混乱,毫无章法,因此重新对这方面进行学习与记录
状态机:状态机描绘状态变迁的状态迁移图,体现了系统对外界事件的反应;
状态机组成六要素:状态集合,初态,终态,输入符号集,输出符号集,状态转移函数;
状态机工作四要素:现态 ,次态,输入,输出;
状态机主要分为三部分:
状态转移部分,描述状态机在时钟驱动下的状态转移这一过程(现态---次态);
状态转移条件,之前我们已经知道状态机会不断进行状态转移,但是由当前状态转移为何种状态?也就是次态的取值是什么,这个工作是状态转移条件部分来描述执行;
输出部分描述状态机的输出,即当前状态下的输出为什么;
这三部分的描述可以放在Verilog描述过程的不同部分,即对应FSM的三种描述方式;
一段式FSM描述:状态机写在1个always块,既描述状态转移,又描述状态的输入输出;(但是其各部分杂糅,在功能比较复杂的场合会比较混乱,不建议使用)
二段式FSM描述:鉴于一段式描述的缺点,两段式描述使用2个always块,一个always块利用同步时序逻辑描述状态转移,一个always块利用组合逻辑描述状态转移条件以及输出;(但是输出一般使用组合逻辑描述,而组合逻辑易产生毛刺等不稳定因素,并影响系统执行速率)
三段式FSM描述:三段式描述应运而生,通过使用3个always块,一个always块利用同步时序逻辑描述状态转移,一个always块利用组合逻辑描述状态转移条件,一个always块利用同步时序逻辑描述输出,避免了前两种描述方式的弊端;
更详细的描述见下连接:
基于Verilog HDL的有限状态机
【 FPGA 】状态机,FPGA的灵魂
按照不同描述方式实现1011序列产生,序列产生的内容详见Verilog实现序列产生器(状态转移形,移位形,计数形)
而此处只关心状态机的描述方式:
一段式描述:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: guoliang CLL
//
// Create Date: 2020/02/21 15:30:18
// Design Name:
// Module Name: seq_gen_fsm1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module seq_gen_fsm1(
input clk,
input rst_n,
output reg seq
);
// state declaration
parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
reg [1:0]state;
// 状态转移+状态转移条件+输出
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
state <= s0;
seq <= 1'b1;
end
else
begin
case(state)
s0:begin
state = s1;
seq <= 1'b1;
end
s1:begin
state = s2;
seq <= 1'b0;
end
s2:begin
state = s3;
seq <= 1'b1;
end
s3:begin
state = s0;
seq <= 1'b1;
end
default:begin
state = s0;
seq <= 1'b1;
end
endcase
end
end
endmodule
二段式描述:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: guoliang CLL
//
// Create Date: 2020/02/21 15:30:49
// Design Name:
// Module Name: seq_gen_fsm2
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module seq_gen_fsm2(
input clk,
input rst_n,
output reg seq
);
// state declaration
parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
reg [1:0]c_state,n_state;
// 状态转移
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
c_state <= s0;
end
else
begin
c_state <= n_state;
end
end
// 状态转移条件+输出
always@(c_state or rst_n)
begin
if(!rst_n)
begin
n_state = s0;
end
else
begin
case(c_state)
s0:begin
n_state = s1;
seq = 1'b1;
end
s1:begin
n_state = s2;
seq = 1'b0;
end
s2:begin
n_state = s3;
seq = 1'b1;
end
s3:begin
n_state = s0;
seq = 1'b1;
end
default:begin
n_state = s0;
seq = 1'b1;
end
endcase
end
end
endmodule
三段式描述:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: guoliang CLL
//
// Create Date: 2020/02/21 00:20:42
// Design Name:
// Module Name: seq_gen_fsm
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module seq_gen_fsm(
input clk,
input rst_n,
output reg seq
);
// state declaration
parameter s0 = 2'b0,s1 = 2'b1,s2 = 2'b10,s3 = 2'b11;
reg [1:0]c_state,n_state;
// 状态转移
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
c_state <= s0;
end
else
begin
c_state <= n_state;
end
end
// 状态转移条件
always@(c_state or rst_n)
begin
if(!rst_n)
begin
n_state = s0;
end
else
begin
case(c_state)
s0:n_state = s1;
s1:n_state = s2;
s2:n_state = s3;
s3:n_state = s0;
default:n_state = s0;
endcase
end
end
// 输出
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
seq <= 1'b0;
end
else
begin
case(n_state)
s0:seq <= 1'b1;
s1:seq <= 1'b0;
s2:seq <= 1'b1;
s3:seq <= 1'b1;
default:seq <= 1'b0;
endcase
end
end
endmodule
测试文件如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: guoliang CLL
//
// Create Date: 2020/02/21 00:35:17
// Design Name:
// Module Name: seq_gen_tsb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module seq_gen_tsb(
);
// port
reg clk;
reg rst_n;
wire seq1,seq2,seq3;
// clk
initial
begin
clk = 1'b1;
forever #10 clk = ~clk;
end
//
initial
begin
rst_n = 1'b1;
#15 rst_n = 1'b0;
#50 rst_n = 1'b1;
end
// instantation
//seq_gen_shift inst(
//seq_gen_count inst(
seq_gen_fsm1 inst(
.clk(clk),
.rst_n(rst_n),
.seq(seq1)
);
seq_gen_fsm2 inst2(
.clk(clk),
.rst_n(rst_n),
.seq(seq2)
);
seq_gen_fsm inst3(
.clk(clk),
.rst_n(rst_n),
.seq(seq3)
);
endmodule
输出结果如下:
可见,两段式与三段式描述输出一致,与理想波形一致;而一段式输出滞后一个时钟周期,原因在于一段式的描述特点,即根据当前状态进行输出的非阻塞赋值,因此输出必然滞后状态一个时钟周期;(二三段式描述为避免这一现象,按照次态选择输出,将非阻塞赋值的时间延迟通过这一方式补偿回来)
基于Verilog HDL的有限状态机
【 FPGA 】状态机,FPGA的灵魂