前言
用Verilog描述一个可综合的序列检测器用于检测输入数据码流中的特定序列。本文介绍了使用状态机来直接描述和采用移位寄存器的方式进行检测的两种方法。同时,也给出了tb文件和仿真波形图。
状态机方法
本文实现了对序列“1010”的检测,第一种方法我们采用状态机的写法进行检测。
首先画出状态转移图,如下:
含义描述如下:A状态相当于idle状态,此刻若输入一个1,则会转移至下一状态,否则保持此状态,同理,当依次输入1010时,状态转移至E,且输出为1,表示检测到序列1010,随后若再次输入1,则会重新跳转至A状态,开始新的序列检测。
下面给出代码:
//check_sequence FSM
`timescale 1ns/1ns
module tb();
wire out;
reg clk, rst;
reg data_in;
check_sequence dut(.clk(clk),
.rst(rst),
.ina(data_in),
.out(out)
);
initial begin
clk <= 0;
forever begin
#5 clk <= ~clk;
end
end
initial begin//给出一段码流数据
#20 data_in = 1;
#20 data_in = 0;
#20 data_in = 1;
#20 data_in = 0;
#20 data_in = 0;
#20 data_in = 0;
#20 data_in = 1;
#20 data_in = 0;
#20 data_in = 1;
#20 data_in = 0;
#500 $stop;
$display("check finished");
end
initial begin
#10 rst <= 0;
#20 rst <= 1;
end
endmodule
module check_sequence(input clk, input rst, input ina, output out);
reg[1:0] state, next_state;
reg out;
parameter A = 3'b000, B = 3'b001, C = 3'b010, D = 3'b011, E = 3'b100;
always @(posedge clk or negedge rst)
if (!rst)
state <= A;
else
state <= next_state;
always @(state or ina)//state transition
begin
next_state <= A;
case(state)
A: begin
if (ina == 1)
next_state <= B;
else
next_state <= A;
out <= 0;
end
B: begin
if (ina==1)
next_state <= B;
else
next_state <= C;
out <= 0;
end
C: begin
if (ina==1)
next_state <= D;
else
next_state <= C;
out <= 0;
end
D: begin
if (ina==1)
next_state <= D;
else
next_state <= E;
out <= 1;
end
E: begin
if (ina==1)
next_state <= A;
else
next_state <= E;
out <= 0;
end
default: next_state <= A;
endcase
end
endmodule
仿真波形如下:
可以看到,当检测到1010时,out信号会拉高。
移位寄存器方法
此方法的基本思路就是利用移位寄存器作为检测窗口,每进来一个数就跟目标序列进行比较。
直接给出代码如下:
//shift regeister detection
//test sequence: 1010
`timescale 1ns/1ns
module tb();
wire check_rst, ina;
reg clk, rst;
reg [23:0] data;//give data in sequence
assign ina = data[23];
check_sequence1 dut(.clk(clk),
.rst(rst),
.check_rst(check_rst),
.ina(ina)
);
initial begin
clk <= 0;
forever begin
#5 clk <= ~clk;
end
end
initial begin
#10 rst <= 0;
repeat(2) @(posedge clk);
rst <= 1;
end
initial begin
data = 24'b1100_1010_0011_1101_1010_1011;
#500 $stop;
end
always @(posedge clk) begin
#2 data = {data[22:0],data[23]};
end
endmodule
module check_sequence1 (input ina, input clk, input rst, output check_rst);
parameter check_sq = 4'b1010;//check_sequence
reg [3:0] buffer;
assign check_rst = (buffer == check_sq)? 1:0;
always @(posedge clk or negedge rst) begin
if (!rst)
buffer <= 4'b0000;
else
buffer <= {buffer[2:0],ina};
end
endmodule
仿真波形如下: