序列产生和检测(FSM状态机)
提示:FSM有限状态机,是FPGA和数字IC相关岗位必须要掌握的知识点,在笔试和面试中都非常常见。
文章目录
前言
笔试题目:
一、了解状态机:什么是摩尔型状态机,什么是米利型状态机,两者的区别是什么?一段式、二段式、三段式状态机的区别?
二、使用状态机产生序列“1101_0110”,串行循环输出该序列;
三、使用状态机检测“1101”,串行输入的测试序列为“11101101011010”,输出信号为valid有效信号,检测到时输出高,否则为低,考虑序列叠加情况,比如“1101101”,则有两个“1101”,即:
11101101011010,在第5个时钟检测到序列,下一个时钟输出高电平;
11101101011010,在第8个时钟检测到序列,下一个时钟输出高电平;
11101101011010,在第13个时钟检测到序列,下一个时钟输出高电平;
给出WORD或PDF版本的报告,包括但不限于文字说明、代码、仿真测试图等。
一、状态机基本概念
状态机:状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按预先设定的状态进行转移,是协调相关动作、完成特定操作的控制中心、有限状态机称FSM,主要分为两类:
- Moore状态机:输出只和状态有关即只取决当前状态,与输入无关;
- Mealy状态机:输出不仅和状态有关即不仅取决当前状态,而且和输入有关;
重点:实现相同的功能时,Mealy型比Moore型节省一个状态,Mealy型比Moore型超前一个时钟周期。
- 一段式:一个always块,既描述状态转移,又描述状态的输入输出,当前状态用寄存器输出。
- 二段式:两个always块,时序逻辑和组合逻辑分开,一个always块采用同步时序描述状态转移;另一个采用组合逻辑判断状态转移条件,描述状态转移规律及输出,当前状态用组合逻辑输出,可能出现竞争冒险,产生毛刺,而且不利于约束。
- 三段式:三个always块,一个always块采用同步时序描述状态转移;一个采用组合逻辑判断状态转移条件,描述状态转移规律;第三个使用同步时序描述状态输出,寄存器输出。
二、使用状态机产生序列“1101_0110”,串行循环输出该序列
1.引入基础笔试题
-
欲产生序列信号1101_0111,则至少需要 ______级触发器?
8bit的状态可以用2^3=8 来表示,至少需3级触发器。
-
欲产生序列信号1101_0111,如果用移位寄存器,则至少需要 ______级触发器?
需要5级触发器。11010111左移位循环举例:
4级:1101–1010—0101—1011—0111—1111—1111—1110—1101,出现重复,不可以
5级:11010—10101—01011—10111—11111—11110—11101—11010,没有重复,可以。
2.FSM产生序列信号
循环移位产生序列信号11010110代码如下(示例):
module FSM2
(
input wire sys_clk ,
input wire sys_rst_n ,
output reg data_1 ,
output wire data
);
reg [7:0] data_reg = 8'b1101_0110 ;
always @ ( posedge sys_clk or negedge sys_rst_n )
if( !sys_rst_n )
data_reg <= 8'b1101_0110;
else
data_reg <= {
data_reg[6:0],data_reg[7]};//位拼接符号实现循环移位
assign data = data_reg[7];//阻塞赋值(=),右侧有变化就立即变化
//非阻塞赋值(<=),右侧有变化,下一个时钟沿变化
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
data_1 <= 1'b0 ;
else
data_1 <= data_reg[7] ;
endmodule
sim仿真代码(示例):
`timescale 1ns/1ns
module tb_FSM2();
reg sys_clk ;
reg sys_rst_n ;
wire data_1 ;
wire data;
initial begin
sys_clk = 1'b0 ;
sys_rst_n <= 1'b0;
#30
sys_rst_n <= 1'b1;
#800
$stop;
end
always#10 sys_clk = ~sys_clk;
FSM2 FSM2_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n) ,
.data_1 (data_1 ) ,
. data ( data )
);
endmodule
三、FSM序列检测序列“1101”
- IDEL:初始状态,检测到1则去S1(1),否则保持IDEL;
- S1 (1): 检测到1则来到S2(11),否则回到IDEL;
- S2 (11): 检测到0则来到S3(110),否则保持S2;
- S3 (110): 检测到1则来到S4(1101),否则回到IDEL;
- S4 (1101):检测到1则来到S2(11),否则回到IDEL。
使用Moore状态机最终输出和输入无关,只要S4有输入就输出1,故采用Moore型三段式FSM有限状态机。
FSM检测1101序列(示例):
module FSM
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire data_in ,
output reg data_valid
);
parameter IDEL = 5'b00001 ,
S1 = 5'b00010 ,
S2 = 5'b00100 ,
S3 = 5'b01000 ,
S4 = 5'b10000 ;
reg[4:0] current_state ;
reg[4:0] next_state ;
//第一段同步时序逻辑,描述状态切换
always@(posedge sys_clk)
if(!sys_rst_n)
current_state <= IDEL ;
else
current_state <= next_state ;
//第二段组合逻辑,判断状态转移条件和规律.这里=和<=没区别
always@(*)
if(!sys_rst_n)
next_state <= IDEL ;
else
case(current_state)
IDEL :if(data_in == 1) next_state <= S1; else next_state <= IDEL;
S1 :if(data_in == 1) next_state <= S2; else next_state <= IDEL;
S2 :if(data_in == 0) next_state <= S3; else next_state <= S2 ;
S3 :if(data_in == 1) next_state <= S4; else next_state <= IDEL;
S4 :if(data_in == 1) next_state <= S2; else next_state <= IDEL;
default : next_state <= IDEL ;
endcase
//第三段同步时序逻辑,描述状态输出,Moore型输出:只要S4有输入就输出1
always@(posedge sys_clk)
if(!sys_rst_n)
data_valid <= 1'b0;
else
case(next_state)
S4 :data_valid <= 1'b1;
default :data_valid <= 1'b0;
endcase
endmodule
sim仿真代码,串行输入的测试序列“11101101011010”,状态机检测“1101”,(示例):
`timescale 1ns/1ns
module tb_FSM();
reg sys_clk ;
reg sys_rst_n ;
reg data_in ;
wire data_valid;
initial begin
sys_clk = 1'b0 ;
sys_rst_n <= 1'b0;
data_in <= 1'b0 ;
#30
sys_rst_n <= 1'b1;
#30
data_in <= 1'b1 ; #20;//延迟是一个周期
data_in <= 1'b1 ; #20;
data_in <= 1'b1 ; #20;
data_in <= 1'b0 ; #20;
data_in <= 1'b1 ; #20;
data_in <= 1'b1 ; #20;
data_in <= 1'b0 ; #20;
data_in <= 1'b1 ; #20;
data_in <= 1'b0 ; #20;
data_in <= 1'b1 ; #20;
data_in <= 1'b1 ; #20;
data_in <= 1'b0 ; #20;
data_in <= 1'b1 ; #20;
data_in <= 1'b0 ; #20;
#150
$stop;
end
always#10 sys_clk = ~sys_clk;
FSM FSM_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.data_in (data_in ) ,
.data_valid(data_valid)
);
endmodule
总结
在序列产生处:通过位拼接符号实现循环移位
在序列产生处:阻塞赋值和非阻塞赋值的区别,两个信号都进行了对比
在序列检测处:三段式状态机写代码的特点
在序列检测处:第三段时,Moore状态机和Mealy状态机输出的区别
刚开始仿真效果没有对上,最后发现:data_in输入之后的延迟没有和时钟周期同步,不是20ns。