基于FPGA的序列检测器设计(状态机)
1. 项目介绍
序列检测器是一种能够检测输入的一串二进制代码的电路,当该二进制代码与事先设定的码组一致时,检测电路输出高电平,否则输出低电平。序列检测器多用于通信系统中对同步码的检测,或者是对所需信号的提取,这在数字通信领域中有着广泛的运用,如下图所示101序列检测器(可重叠)。
2. 设计要求
采用状态机设计一个“1010110”序列检测器,其功能是检测到一个7位的二进制序列“1010110”,输出一个时钟周期的高脉冲,其他情况下为0。当遇到“…………1010110_10110……………..”时,后面的一个也认为满足检测要求。
3. 设计分析
序列检测器检测的关键在于正确码的收到必须是连续的,这就要求检测器必须记住前一次的正确码及正确序列,直到在连续的检测中所收到的每一位码都与预置数的对应码相同。在检测过程中,任何一位不相同都将回到初始状态重新开始检测。
(1)系统架构图
系统端口及其意义
- clk:系统时钟,50MHz;
- rst_n: 系统复位信号,低电平有效;
- idata: 串行输入信号
- flag:当检测到 “1010110”,输出一个时钟周期的高脉冲,其他时刻为0;
(2)状态划分
本系统采用状态机进行设计,将“1010110”序列检测过程划分为7个状态:
- S0: 未检测到有效信号的状态;
- S1: 检测到“1”信号;
- S2: 检测到“10”信号;
- S3: 检测到“101”信号;
- S4: 检测到“1010”信号;
- S5: 检测到“10101”信号;
- S6: 检测到“101011”信号;
这里当遇到“…………1010110_10110……………..”时,后面的一个也认为满足检测要求,前面出现的信号可重复使用,会出现一个时钟周期的高电平。
4. 设计实现
1 module sequence1010110( 2 input wire clk, 3 input wire rst_n, 4 input wire idata, 5 6 output reg flag 7 ); 8 9 localparam S0 = 7'b000_0001; 10 localparam S1 = 7'b000_0010; 11 localparam S2 = 7'b000_0100; 12 localparam S3 = 7'b000_1000; 13 localparam S4 = 7'b001_0000; 14 localparam S5 = 7'b010_0000; 15 localparam S6 = 7'b100_0000; 16 17 reg [6:0] c_state; 18 reg [6:0] n_state; 19 20 always@(posedge clk or negedge rst_n)begin 21 if(rst_n == 1'b0) 22 c_state <= S0; 23 else 24 c_state <= n_state; 25 end 26 27 always@(*)begin 28 case(c_state) 29 S0 : begin 30 if(idata == 1'b1) 31 n_state = S1; 32 else 33 n_state = S0; 34 end 35 36 S1: begin 37 if(idata == 1'b1) 38 n_state = S1; 39 else 40 n_state = S2; 41 end 42 43 S2: begin 44 if(idata == 1'b1) 45 n_state = S3; 46 else 47 n_state = S0; 48 end 49 50 S3: begin 51 if(idata == 1'b1) 52 n_state = S1; 53 else 54 n_state = S4; 55 end 56 57 S4: begin 58 if(idata == 1'b1) 59 n_state = S5; 60 else 61 n_state = S0; 62 end 63 64 S5: begin 65 if(idata == 1'b1) 66 n_state = S6; 67 else 68 n_state = S4; 69 end 70 71 S6: begin 72 if(idata == 1'b1) 73 n_state = S1; 74 else 75 n_state = S2; 76 end 77 78 default : n_state = S0; 79 endcase 80 end 81 82 always@(posedge clk or negedge rst_n)begin 83 if(rst_n == 1'b0) 84 flag <= 1'b0; 85 else 86 if((c_state == S6)&&(idata == 1'b0)) 87 flag <= 1'b1; 88 else 89 flag <= 1'b0; 90 91 end 92 93 endmodule
5. 仿真验证
1 `timescale 1ns/1ps 2 3 module sequence1010110_tb(); 4 5 reg clk; 6 reg rst_n; 7 reg idata; 8 9 wire flag; 10 11 reg [15:0] ascii_state; 12 wire [6:0] tb_state; 13 14 assign tb_state = sequence1010110_inst.c_state; 15 16 always@(*)begin 17 case(tb_state) 18 7'b000_0001 : ascii_state = "S0"; 19 7'b000_0010 : ascii_state = "S1"; 20 7'b000_0100 : ascii_state = "S2"; 21 7'b000_1000 : ascii_state = "S3"; 22 7'b001_0000 : ascii_state = "S4"; 23 7'b010_0000 : ascii_state = "S5"; 24 7'b100_0000 : ascii_state = "S6"; 25 default : ascii_state = "NO"; 26 endcase 27 end 28 29 sequence1010110 sequence1010110_inst( 30 .clk (clk), 31 .rst_n (rst_n), 32 .idata (idata), 33 34 .flag (flag) 35 ); 36 37 initial clk = 1'b0; 38 always #10 clk = ~clk; 39 40 initial begin 41 rst_n = 1'b0; idata = 1'b0; 42 #101; 43 rst_n = 1'b1; 44 #50; 45 repeat(100)begin 46 @(posedge clk); #2; 47 idata = {$random}%2; 48 end 49 50 @(posedge clk); #2; idata = 1'b1; 51 @(posedge clk); #2; idata = 1'b0; 52 @(posedge clk); #2; idata = 1'b1; 53 @(posedge clk); #2; idata = 1'b0; 54 @(posedge clk); #2; idata = 1'b1; 55 @(posedge clk); #2; idata = 1'b1; 56 @(posedge clk); #2; idata = 1'b0; 57 @(posedge clk); #2; idata = 1'b1; 58 @(posedge clk); #2; idata = 1'b0; 59 @(posedge clk); #2; idata = 1'b1; 60 @(posedge clk); #2; idata = 1'b1; 61 @(posedge clk); #2; idata = 1'b0; 62 @(posedge clk); #2; idata = 1'b1; 63 @(posedge clk); #2; idata = 1'b1; 64 65 #200; $stop; 66 end 67 68 endmodule
6. 参考资料