牛客网Verilog刷题——VL27
- 题目
- 答案
题目
请编写一个序列检测模块,检测输入信号(a)是否满足011100序列, 要求以每六个输入为一组,不检测重复序列,例如第一位数据不符合,则不考虑后五位。一直到第七位数据即下一组信号的第一位开始检测。当信号满足该序列,给出指示信号match。当不满足时给出指示信号not_match。
模块的接口信号图如下:
模块的时序图如下:
请使用Verilog HDL实现以上功能,要求使用状态机实现,画出状态转化图。
信号 | 类型 | 输入/输出 | 位宽 | 描述 |
---|---|---|---|---|
clk | wire | Intput | 1 | 系统时钟信号 |
rst_n | wire | Intput | 1 | 异步复位信号,低电平有效 |
a | wire | Intput | 1 | 单比特信号,待检测的数据 |
match | reg | Output | 1 | 当输入信号a满足目标序列,该信号为1,其余时刻该信号为0 |
not_match | reg | Output | 1 | 当输入信号a不满足目标序列,该信号为1,其余时刻该信号为0 |
答案
题目中要求使用状态机实现,可以画出其状态转换图。
根据状态转换图,编写Verilog代码,如下。
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
//状态机实现
reg [2:0] curr_state;
reg [2:0] next_state;
reg [5:0] r_data;
always @(posedge clk or negedge rst_n)
if(!rst_n)
curr_state <= 3'd0;
else
curr_state <= next_state;
always @(*) begin
next_state = 3'd0;
case(curr_state)
3'd0: next_state = 3'd1;
3'd1: next_state = 3'd2;
3'd2: next_state = 3'd3;
3'd3: next_state = 3'd4;
3'd4: next_state = 3'd5;
3'd5: next_state = 3'd0;
default: next_state = 3'd0;
endcase
end
always @(posedge clk or negedge rst_n)
if(!rst_n) begin
r_data <= 6'd0;
match <= 1'b0;
not_match <= 1'b0;
end
else
case(curr_state)
3'd0,3'd1,3'd2,3'd3,3'd4:
begin
r_data[curr_state] <= data;
match <= 1'b0;
not_match <= 1'b0;
end
3'd5:
begin
r_data[curr_state] <= data;
if(r_data[4:0] == 5'b01110 && data == 1'b0)
match <= 1'b1;
else
match <= 1'b0;
if(r_data[4:0] != 5'b01110 && data != 1'b0)
not_match <= 1'b1;
else
not_match <= 1'b0;
end
default:
begin
r_data <= 6'd0;
match <= 1'b0;
not_match <= 1'b0;
end
endcase
endmodule
另外,我们还可以用计数器+移位寄存器的方式进行实现,如下。
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
//采用移位寄存器+计数器实现
reg [2:0] r_cnt;
reg [5:0] r_data;
always @(posedge clk or negedge rst_n)
if(!rst_n)
r_cnt <= 3'd0;
else if(r_cnt == 3'd5)
r_cnt <= 3'd0;
else
r_cnt <= r_cnt + 1'b1;
always @(posedge clk or negedge rst_n)
if(!rst_n)
r_data <= 6'd0;
else
r_data <= {r_data,data};
always @(posedge clk or negedge rst_n)
if(!rst_n) begin
match <= 1'b0;
not_match <= 1'b0;
end
else if(r_cnt == 3'd5)
if(data == 1'b0 && r_data[4:0] == 4'b01110) begin
match <= 1'b1;
not_match <= 1'b0;
end
else begin
match <= 1'b0;
not_match <= 1'b1;
end
else begin
match <= 1'b0;
not_match <= 1'b0;
end
endmodule