序列检测简介及代码实现
序列检测器包含两种,一种是移位寄存器,另一种时状态机,还有重复序列和不重复序列检测。重点关注和了解如何用状态机去实现。
序列检测器就是将指定的序列从数字码流 中检测出来,收到输出1,否则输出0
移位寄存器解法
重复序列检测1101序列
module seq_detect1(
input clk ,
input rst_n ,
input din ,
output flg ,
);
reg [3:0] din_t ;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
din_t <= 4'b0 ;
else
din_t <= {din_t[2:0] ,din};
end
assign flg = (din_t==4'b1101) ? 1'b1 :1'b0 ;
endmodule
不重复序列检测1101
module seq_detect2(
input clk ,
input rst_n ,
input din ,
output flg ,
);
reg [1:0] cnt;
reg [3:0] din_t ;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 1'b0;
else if(cnt==2'd3)
cnt <= 1'b0;
else
cnt <= cnt+1'b1;
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
din_t <= 4'b0 ;
else
din_t <= {din_t[2:0] ,din};
end
assign flg = (din_t==4'b1101) && (cnt==2'd3)? 1'b1 :1'b0 ;
endmodule
状态机解法
此处采用的状态机是三段式Moore状态机的写法
重复序列检测1101
module seq_detect3 (
input clk ,
input rst_n,
input din ,
output reg flag ,
);
reg [4:0] cur_state;
reg [4:0] next_state ;
localparam IDLE = 5'b00001;
localparam SEQ1 = 5'b00010;
localparam SEQ11 = 5'b00100;
localparam SEQ110 = 5'b01000;
localparam SEQ1101 = 5'b10000 ;
//状态机三段式
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cur_state <= IDLE;
else
cur_state <= next_state ;
end
always@(*)
begin
case(cur_state)
IDLE : next_state = din ? SEQ1 : IDLE;
SEQ1 : next_state = din ? SEQ11 : IDLE ;
SEQ11: next_state = din ? SEQ11 : SEQ110 ;
SEQ110 : next_state = din ? SEQ1101 : IDLE ;
SEQ1101 :next_state = din ? SEQ11 : IDLE ;
default : next_state = IDLE ;
endcase
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
flag <= 1'b0 ;
else if(cur_state==SEQ1101)
flag <= 1'b1;
else
flag <= 1'b0 ;
end
endmodule
不重复序列检测1101
module seq_detect4 (
input clk ,
input rst_n,
input din ,
output reg flag ,
);
reg [4:0] cur_state;
reg [4:0] next_state ;
localparam IDLE = 5'b00001;
localparam SEQ1 = 5'b00010;
localparam SEQ11 = 5'b00100;
localparam SEQ110 = 5'b01000;
localparam SEQ1101 = 5'b10000 ;
//状态机三段式
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cur_state <= IDLE;
else
cur_state <= next_state ;
end
always@(*)
begin
case(cur_state)
IDLE : next_state = din ? SEQ1 : IDLE;
SEQ1 : next_state = din ? SEQ11 : IDLE ;
SEQ11: next_state = din ? IDLE : SEQ110 ;
SEQ110 : next_state = din ? SEQ1101 : IDLE ;
SEQ1101 :next_state = IDLE ;
default : next_state = IDLE ;
endcase
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
flag <= 1'b0 ;
else if(cur_state==SEQ1101)
flag <= 1'b1;
else
flag <= 1'b0 ;
end
endmodule