,但1是1001的第一个数,所以进入S1状态。
S3:代表目前已经有了3个匹配的数据。
seq_in = 1时,当前序列为1001,与要求序列匹配,进入S4状态;
seq_in = 0时,当前序列为1000,与要求序列不配,0与初始状态匹配,所以进入IDLE状态。
S4:最终状态,代表目前已经得到了匹配的序列,输出信号翻转。
seq_in = 1时,当前序列为10011,1与要求序列的第一个数匹配,所以进入S1状态;
seq_in = 0时,当前序列为10010,10与要求的前两个数匹配,所以进入S2状态。
第二步:根据流程转换分析画出状态机的状态转移图,如下图所示:
第三步:根据状态机转移图用经典三段式(或者二段式)写出verilog代码
3.12verilog代码
//使用状态机设计检测“1001”的序列检测器
//可重叠检测序列“1001”
module sequence_detect03(
input clk ,
input rst_n,
input seq_in,
output reg mismatch //检验序列是否匹配,匹配输出0,不匹配输出0
);
//采用独热码编译五个状态,初始IDLE状态为待机状态
//独热码相比二进制码和格雷码,方便电路设计判断、状态转移,且逻辑更简单
parameter IDLE = 5'b00001;
parameter S1 = 5'b00010;
parameter S2 = 5'b00100;
parameter S3 = 5'b01000;
parameter S4 = 5'b10000;
//定义两个寄存器表示状态机的目前状态和下一状态
reg [4:0] curr_state;
reg [4:0] next_state;
//第一段使用时序逻辑描述状态转移
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
curr_state <= IDLE;
end
else begin
curr_state <= next_state;
end
end
//第二段使用组合逻辑判断状态转移条件
always@(*) begin
if(!rst_n) begin
next_state <= IDLE;
end
else begin
case(curr_state)
IDLE :next_state = seq_in?S1:IDLE;
S1 :next_state = seq_in?S1:S2;
S2 :next_state = seq_in?S1:S3;
S3 :next_state = seq_in?S4:IDLE;
S4 :next_state = seq_in?S1:S2;
default:next_state = IDLE; //养成良好代码风格,不能遗漏,防生成latch,也可以通过赋初值避免
endcase
end
end
//第三段描述状态输出(可以使用组合逻辑,也可以用时序逻辑)
//此处采用时序逻辑,同时也提供组合逻辑代码示例
always@(posedge clk or negedge rst_n) begin //时序逻辑描述输出
if(!rst_n) begin
mismatch <= 1'b1;
end
else if(next_state == S4) begin
mismatch <= 1'b0;
end
else begin
mismatch <= 1'b1;
end
end
//assign mismatch = (curr_state ==S4) ? 1'b0 : 1'b1; //组合逻辑描述输出
endmodule
3.13Testbench
`timescale 1ns/1ps //仿真时间单位1ns 仿真时间精度1ps
module sequence_detect03_tb();
//信号申明
reg clk;
reg rst_n;
reg seq_in;
wire mismatch;
//复位信号生成
//输入信号生成,输入信号为“1001001001001”
//时钟信号与复位信号赋初值
initial begin
clk = 0;
rst_n = 1;
#5 rst_n = 0;
#10 rst_n = 1;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
end
//时钟信号生成
always #5 clk = ~clk;
//模块实例化(将申明的信号连接起来即可)
sequence_detect03 u_sequence_detect03(
.clk (clk),
.rst_n (rst_n),
.seq_in (seq_in),
.mismatch (mismatch)
);
endmodule
3.14仿真结果
输入序列1001001001001,根据可重复检测理论上可检测四次信号翻转,从仿真结果可以看到mismatch发生四次翻转,且第二次翻转的1001中的第一个1来自第一组1001中最后一个1,即发生重叠亦可检测。
3.2非重叠检测
3.21 非重叠检测方法
题目:设计一个序列检测器,用来检测序列 1001,用状态机完成电路,可重复检测序列1001
第一步,分析状态机状态转移,分析如下:
IDLE: 初始状态,代表目前没有接收到满足要求的数据。
seq_in = 1时,等于1001中的第一个数,进入S1状态;
seq_in = 0时,保持状态。
S1:代表目前已经有了1个匹配的数据。
seq_in = 0时,当前序列为10,等于1001中的前两个数,进入S2状态;
seq_in = 1时,当前序列为11,不是1001的前两个数,但1是1001的第一个数,所以保持S1状态。
S2:代表目前已经有了2个匹配的数据。
seq_in = 0时,当前序列为100,等于1001中的前三个数,进入S3状态;
seq_in = 1时,当前序列为101,不是1001的前三个数,但1是1001的第一个数,所以进入S1状态。
S3:代表目前已经有了3个匹配的数据。
seq_in = 1时,当前序列为1001,与要求序列匹配,进入S4状态;
seq_in = 0时,当前序列为1000,与要求序列不配,0与初始状态匹配,所以进入IDLE状态。
S4:最终状态,代表目前已经得到了匹配的序列,输出信号翻转。
seq_in = 1时,当前序列为10011,1与要求序列的第一个数匹配,所以进入S1状态;
seq_in = 0时,当前序列为10010,10与要求的前两个数匹配,但是要求非重叠检测,所以进入IDLE状态。
第二步:根据流程转换分析画出状态机的状态转移图,如下图所示
第三步:根据状态机转移图用经典三段式(或者二段式)写出verilog代码
3.22verilog代码
//使用状态机设计检测“10