verilog实现序列检测(状态机和移位寄存器实现)
前言
用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 = 3b000, B = 3b001, C = 3b010, D = 3b011, E = 3b100; 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 = 24b1100_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 = 4b1010;//check_sequence reg [3:0] buffer; assign check_rst = (buffer == check_sq)? 1:0; always @(posedge clk or negedge rst) begin if (!rst) buffer <= 4b0000; else buffer <= { buffer[2:0],ina}; end endmodule
仿真波形如下:
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
Verilog学习-可综合语句