本文主要介绍10011011的序列检测 用verilog编程,modelsim仿真的设计报告,内含文本程序和激励文件以及仿真图像
仅供参考。
序列检测器的介绍
序列检测器可用于检测一组或多组由二进制码组成的脉冲序列信号,当序列检测器连续收到一组串行二进制码后,如果这组与检测器中预先设置的码相同,则输出为1,否则输出为0.由于这种检测必须记住前一次的正确码及正确序列,直到在连续的检测中所收到的对应码相同。在检测过程中,任何一位不相等都将回到初始状态重新检测。
序列检测器的实现方式
序列检测器的设计有状态机法和移位寄存器法两种。状态机法的优点是灵活性好,可以灵活的处理输入和输出,同时可以处理较为复杂的序列检测任务,缺点是设计开发难度大,不易扩展,如果需要检测另一个序列,需要重新设计状态机的状态转移;移位寄存器法的优点是设计和开发相对简单,并且易于扩展,检测另外一个序列,只需修改输入数据,缺点是灵活性差,因为寄存器序列移位寄存器是固定的,检测模式就固定。
状态转移图
Verilog程序
module seqdet(
input clk,
input rst_n,
input seq_in,
output reg mismatch //检验序列是否匹配,匹配输出1,不匹配输出0
);
//采用独热码编译五个状态,初始IDLE状态为待机状态
//独热码相比二进制码和格雷码,方便电路设计判断、状态转移,且逻辑更简单
parameter IDLE = 9'b0_0000_0001;
parameter S1 = 9'b0_0000_0010;
parameter S2 = 9'b0_0000_0100;
parameter S3 = 9'b0_0000_1000;
parameter S4 = 9'b0_0001_0000;
parameter S5 = 9'b0_0010_0000;
parameter S6 = 9'b0_0100_0000;
parameter S7 = 9'b0_1000_0000;
parameter S8 = 9'b1_0000_0000;
//定义两个寄存器表示状态机的目前状态和下一状态
reg [8:0] curr_state;
reg [8: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?S5:S2;
S5 :next_state = seq_in?S1:S6;
S6 :next_state = seq_in?S7:S3;
S7 :next_state = seq_in?S8:S2;
S8 :next_state = seq_in?S1:S2;
default:next_state = IDLE; //养成良好代码风格,不能遗漏,防生成latch,也可以通过赋初值避免
endcase
end
end
//第三段描述状态输出(可以使用组合逻辑,也可以用时序逻辑)
//此处采用组合逻辑,同时也提供时序逻辑代码示例
//assign mismatch = (curr_state ==S8) ? 1'b0 : 1'b1; //组合逻辑描述输出
//时序逻辑描述输出
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
mismatch <= 1'b1;
end
else if(next_state == S8) begin
mismatch <= 1'b0;
end
else begin
mismatch <= 1'b1;
end
end
endmodule
Testbench程序
`timescale 1ns/1ps //仿真时间单位1ns 仿真时间精度1ps
module seqdet_tb();
//信号申明
reg clk;
reg rst_n;
reg seq_in;
wire mismatch;
initial begin
clk = 1'b0;
forever begin
#10 clk = ~clk;
end
end
initial begin
rst_n = 1'b1;
seq_in = 1'b0;
#30 rst_n = 1'b0;
seq_in = 1'b1;
#20 seq_in = 1'b1;
#20 seq_in = 1'b0;
#20 seq_in = 1'b0;
#20 seq_in = 1'b1;
#20 seq_in = 1'b1;
#20 seq_in = 1'b0;
#20 seq_in = 1'b1;
#20 seq_in = 1'b1;
#20 seq_in = 1'b0;
#20 seq_in = 1'b0;
#20 seq_in = 1'b1;
#20 seq_in = 1'b1;
#20 seq_in = 1'b0;
#20 seq_in = 1'b1;
#20 seq_in = 1'b1;
#20 seq_in = 1'b0;
end
//模块实例化(将申明的信号连接起来即可)
seqdet u_seqdet
(.clk (clk),
.rst_n (rst_n),
.seq_in (seq_in),
.mismatch (mismatch)
);
endmodule
仿真效果
如图所示
,黄色线段的为检测到的一段完整目标序列10011011,波形周期为10秒一个波,20秒一个周期;红色线段为检测到的第二个目标序列,两次检测都以置0为标记,然后复位1开始检测下一个序列。
END