0. 前言
对于序列检测的题目,一般可以用两种方法完成:状态机 或者 移位寄存器。
可以参考一下这篇博客,这是我之前写的,现在为了刷题,规整了一下,里边讲解的很清楚了,这里我就不多说了,直接传送门。
1. 题目VL25 输入序列连续的序列检测
1.1 题目描述
请编写一个序列检测模块,检测输入信号a是否满足01110001序列,当信号满足该序列,给出指示信号match。
1.1.1 信号示意图
1.1.2 波形示意图
1.1.3 输入描述
clk:系统时钟信号
rst_n:异步复位信号,低电平有效
a:单比特信号,待检测的数据
1.1.4 输出描述
match:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0
1.2 解题思路
该题的状态转移图如下所示:
其实,这类题写出状态转移图就简单了不少,剩下的就交给状态机,哈哈哈!!!
1.3 代码实现
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
parameter
s0 = 8'b0000_0001,
s1 = 8'b0000_0010,
s2 = 8'b0000_0100,
s3 = 8'b0000_1000,
s4 = 8'b0001_0000,
s5 = 8'b0010_0000,
s6 = 8'b0100_0000,
s7 = 8'b1000_0000;
reg [7:0] cur_state, nex_state;
// step one
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
cur_state <= 8'd0;
end
else begin
cur_state <= nex_state;
end
end
//step two
always @ (*) begin
case(cur_state)
s0 : nex_state = a ? s1 : s0;
s1 : nex_state = a ? s2 : s0;
s2 : nex_state = a ? s3 : s0;
s3 : nex_state = a ? s0 : s4;
s4 : nex_state = a ? s1 : s5;
s5 : nex_state = a ? s1 : s6;
s6 : nex_state = a ? s7 : s0;
s7 : nex_state = s0;
default : nex_state = s0;
endcase
end
//step three
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
match <= 1'b0;
end
else begin
match <= (cur_state == s7) ? 1'b1 : 1'b0;
end
end
// assign match = (cur_state == s7) ? 1'b1 : 1'b0;
endmodule
1.4 测试文件
待更新。。。
1.5 仿真波形
待更新。。。
2. VL26 含有无关项的序列检测
2.1 题目描述
请编写一个序列检测模块,检测输入信号a是否满足011XXX110序列(长度为9位数据,前三位是011,后三位是110,中间三位不做要求),当信号满足该序列,给出指示信号match。
2.1.1 信号示意图
2.1.2 波形示意图
2.1.3 输入描述
clk:系统时钟信号
rst_n:异步复位信号,低电平有效
a:单比特信号,待检测的数据
2.1.4 输出描述
match:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0
2.2 解题思路
该题的状态转移图如下所示:
这个题相比于上一个题而言,多了几个不定态,那变化的地方就是这几个不定态的状态转移图有些变化,只不过不用再判断这几个不定态的输入,就可以直接确定它的下一个状态了,反而简单了不少。
这个题我给出了两种解法,可以参考一下!
2.3 代码实现
2.3.1 状态机法
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
// ============================状态机法==========================================================
// /*
parameter
IDLE = 10'b00_0000_0001,
s0 = 10'b00_0000_0010,
s1 = 10'b00_0000_0100,
s2 = 10'b00_0000_1000,
s3 = 10'b00_0001_0000,
s4 = 10'b00_0010_0000,
s5 = 10'b00_0100_0000,
s6 = 10'b00_1000_0000,
s7 = 10'b01_0000_0000,
s8 = 10'b10_0000_0000;
reg [9:0] cur_state, nex_state;
// step one
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
cur_state <= IDLE;
end
else begin
cur_state <= nex_state;
end
end
//step two
always @ (*) begin
case(cur_state)
IDLE : nex_state = a ? IDLE : s0;
s0 : nex_state = a ? s1 : s0;
s1 : nex_state = a ? s2 : s0;
s2 : nex_state = s3;
s3 : nex_state = s4;
s4 : nex_state = s5;
s5 : nex_state = a ? s6 : s0;
s6 : nex_state = a ? s7 : s0;
s7 : nex_state = a ? s0 : s8;
s8 : nex_state = a ? IDLE : s0;
default : nex_state = IDLE;
endcase
end
//step three
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
match <= 1'b0;
end
else begin
match <= (cur_state == s8 && a == 0) ? 1'b1 : 1'b0;
end
end
endmodule
2.3.2 移位寄存器法
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
//==================================寄存器法==================================================
reg [8:0] val;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
val <= 9'b0;
end else begin
val <= {val[7:0],a};
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
match <= 1'b0;
end
else begin
casex (val)
9'b011xxx110 : match <= 1'b1;
default : match <= 1'b0;
endcase
end
end
endmodule
2.4 测试文件
待更新。。。
2.5 仿真波形
待更新。。。
3. VL27 不重叠序列检测
3.1 题目描述
请编写一个序列检测模块,检测输入信号(a)是否满足011100序列, 要求以每六个输入为一组,不检测重复序列,例如第一位数据不符合,则不考虑后五位。一直到第七位数据即下一组信号的第一位开始检测。当信号满足该序列,给出指示信号match。当不满足时给出指示信号not_match。
3.1.1 信号示意图
3.1.2 波形示意图
3.1.3 输入描述
clk:系统时钟信号
rst_n:异步复位信号,低电平有效
a:单比特信号,待检测的数据
3.1.4 输出描述
match:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0
not_match:当输入信号a不满足目标序列,该信号为1,其余时刻该信号为0
3.2 解题思路
该题的状态转移图如下所示:
这个题必须使用计数器+状态机(寄存器)来实现,因为题目要求从第一位到第六位。只要有一位不符合那只能等到第七位再进行为期6个数的判断了。
这个题我给出了两种解法,可以参考一下!
3.3 代码实现
3.3.1 状态机法
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
/*
=============================状态机法===================================================
*/
parameter
IDLE = 7'b000_0001,
s0 = 7'b000_0010,
s1 = 7'b000_0100,
s2 = 7'b000_1000,
s3 = 7'b001_0000,
s4 = 7'b010_0000,
s5 = 7'b100_0000;
reg [6:0] cur_state, nex_state;
reg [2:0] cnt;
//计数器
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
cnt <= 3'd0;
end
else if(cnt == 3'd5) begin
cnt <= 3'd0;
end
else begin
cnt <= cnt + 3'd1;
end
end
// step one
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
cur_state <= IDLE;
end
else begin
cur_state <= nex_state;
end
end
//step two
always @ (*) begin
case(cur_state)
IDLE : nex_state = data ? IDLE : s0;
s0 : nex_state = data ? s1 : s0;
s1 : nex_state = data ? s2 : s0;
s2 : nex_state = data ? s3 : s0;
s3 : nex_state = data ? IDLE : s4;
s4 : nex_state = data ? s1 : s5;
s5 : nex_state = data ? s1 : s0;
default : nex_state = IDLE;
endcase
end
//step three
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
match <= 1'b0;
not_match <= 1'b0;
end
else if(cnt == 3'd5) begin
if(cur_state == s4 && data == 0) begin
match <= 1'b1;
not_match <= 1'b0;
end
else begin
match <= 1'b0;
not_match <= 1'b1;
end
end
else begin
match <= 1'b0;
not_match <= 1'b0;
end
end
endmodule
3.3.2 移位寄存器法
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
/*
=============================寄存器法===================================================
*/
reg [2:0] cnt;
reg [5:0] data_r;
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cnt <= 0;
else
cnt <= cnt==5? 0: cnt+1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
data_r <= 6'b0;
else
data_r <= {data_r[4:0], data};
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
match <= 1'b0;
not_match <= 1'b0;
end
else begin
match <= (cnt==5) && ({data_r[4:0], data}==6'b011100);
not_match <= (cnt==5) && ({data_r[4:0], data}!=6'b011100);
end
end
endmodule
3.4 测试文件
待更新。。。
3.5 仿真波形
待更新。。。
4. VL28 输入序列不连续的序列检测
4.1 题目描述
请编写一个序列检测模块,输入信号端口为data,表示数据有效的指示信号端口为data_valid。当data_valid信号为高时,表示此刻的输入信号data有效,参与序列检测;当data_valid为低时,data无效,抛弃该时刻的输入。当输入序列的有效信号满足0110时,拉高序列匹配信号match。
4.1.1 信号示意图
4.1.2 波形示意图
4.1.3 输入描述
clk:系统时钟信号
rst_n:异步复位信号,低电平有效
data:单比特信号,待检测的数据
data_valid:输入信号有效标志,当该信号为1时,表示输入信号有效
4.1.4 输出描述
match:当输入信号data满足目标序列,该信号为1,其余时刻该信号为0
4.2 解题思路
该题的状态转移图如下所示:
这个题和之前的题目不一样的地方在于,有一个有效位判断数据是否有效,这其实就是在状态转移条件那里加一个判断有效无效就行,有效,那就转移,无效,拉到,就是干!!!
这个题我给出了两种解法,可以参考一下!
4.3 代码实现
4.3.1 状态机法
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output reg match
);
// ============================状态机法==========================================================
parameter
IDLE = 5'b0_0001,
s0 = 5'b0_0010,
s1 = 5'b0_0100,
s2 = 5'b0_1000,
s3 = 5'b1_0000;
reg [4:0] cur_state, nex_state;
// step one
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
cur_state <= IDLE;
end
else begin
cur_state <= nex_state;
end
end
//step two
always @ (*) begin
case(cur_state)
IDLE : begin
if(data_valid) begin
nex_state = data ? IDLE : s0;
end
else begin
nex_state = cur_state;
end
end
s0 : begin
if(data_valid) begin
nex_state = data ? s1 : s0;
end
else begin
nex_state = cur_state;
end
end
s1 : begin
if(data_valid) begin
nex_state = data ? s2 : s0;
end
else begin
nex_state = cur_state;
end
end
s2 : begin
if(data_valid) begin
nex_state = data ? IDLE : s3;
end
else begin
nex_state = cur_state;
end
end
s3 : begin
if(data_valid) begin
nex_state = data ? IDLE : s0;
end
else begin
nex_state = cur_state;
end
end
default : begin
if(data_valid) begin
nex_state = IDLE;
end
else begin
nex_state = cur_state;
end
end
endcase
end
//step three
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
match <= 1'b0;
end
else begin
match <= (cur_state == s2 && data == 0) ? 1'b1 : 1'b0; //这个是米粒型的(次态与输入和现态有关)
end
end
endmodule
4.3.2 移位寄存器法
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output reg match
);
// ============================寄存器法==========================================================
reg [3:0] shift_reg;
//shift_reg
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
shift_reg <= 4'd0;
end
else begin
if(data_valid) begin //这里很关键!!!
shift_reg <= {shift_reg[2:0], data};
end
end
end
//compare
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
match <= 1'b0;
end
else begin
if(data_valid && shift_reg[2:0] == 3'b011 && !data) begin
match <= 1'b1;
end
else begin
match <= 1'b0;
end
end
end
endmodule
4.4 测试文件
待更新。。。
4.5 仿真波形
待更新。。。
声明
本人所有系列的文章,仅供学习,不可商用,如有侵权,请告知,立删!!!
本人主要是记录学习过程,以供自己回头复习,再就是提供给后人参考,不喜勿喷!!!
如果觉得对你有用的话,记得收藏+评论!!!