对于序列检测,常见的方法有状态机和序列缓存两种方法。本文主要针对序列缓存的方法来实现。
1、输入序列连续的序列检测
a为单bit输入,序列检测“0111_0001”,若检测到该序列,则match信号为高。
时序图如下图:
代码:
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [7:0] a_reg;
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
begin
a_reg <=8'b0000_0000;
//match <= 'd0;
end
//else if(a_reg ==8'b0111_0001)
//match <='d1;
else
begin
//match <= 'd0;
a_reg <= {a_reg[6:0],a};
end
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
match <='d0;
else if(a_reg == 8'b0111_0001)
match <='d1;
else
match <='d0;
end
endmodule
注意,需要两个always块,若只有一个always块,match为高后不会在变低。
2、含有无关项序列检测
检测序列“011_XXX_110”,只要前三位和后三位相同,match信号即变高。
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [8:0] a_reg;
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
a_reg <= 9'b0000_0000_0;
else
a_reg <= {a_reg[7:0],a};
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
match <= 'd0;
else if(a_reg[8:6]==3'b011&&a_reg[2:0]==3'b110)
match <= 'd1;
else
match <= 'd0;
end
endmodule
3、不重叠序列检测
6个输入信号为一组,检测序列’001_110’。只要一组序列中有一位不相同,直接跳到下一组信号进行判断。若匹配,则match信号为高,若不匹配,则not_match信号为高。
最终时序图要求:
代码如下:
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
reg [2:0] cnt;
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
cnt <='d0;
else if(cnt =='d5)
cnt <= 'd0;
else
cnt <= cnt +'d1;
end
reg [5:0] data_reg;
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
data_reg <= 6'b000_000;
else
data_reg <={data_reg[4:0],data};
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
begin
match <= 'd0;
not_match <= 'd0;
end
else if(cnt =='d5&&data_reg ==6'b001_110)
match <='d1;
else if(cnt =='d5&&data_reg != 6'b001_110)
not_match <='d1;
else
begin
match <='d0;
not_match <='d0;
end
end
endmodule
4、带有使能信号的序列检测
模块接口如下图所示:
输入信号为data,当data_valid使能信号为高时,此时输入的data有效,检测到序列“0110”时,match为高。
时序图要求:
代码
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output reg match
);
reg [3:0] data_reg;
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
data_reg <=4'b0000;
else if(data_valid)
data_reg <={data_reg[2:0],data};
else
data_reg <= data_reg;
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n ==1'b0)
match <='d0;
else if(data_reg[2:0] ==3'b011&&data_valid&&data=='d0)
match <='d1;
else
match <= 'd0;
end
endmodule