2022-4-1:才注意到题目要求使用状态机完成,所以补充了状态机代码。此外,之前的移位寄存器方法我也误以为是右移的,也做了修正。并且Testbench中match
和not_match
信号好像比题目要求的提前了一个周期。不过之前错误的方法居然通过了测试。希望牛客能提供更完整的测试波形供大家调试。
状态机
波形图
状态转移图
本程序的状态机在基本的三段式状态机上加入了计数器cnt
,并使用cnt
对状态转移进行约束,以确保正常工作时,状态机每6个周期循环一次。其中FAIL
状态仅在计数器cnt==6
时才会切换到别的状态,match
和not_match
也仅在cnt==6
时才进行更新; ZERO
为启动态,系统复位时,处于该状态。
程序
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
parameter ZERO=0, ONE=1, TWO=2, THREE=3, FOUR=4, FIVE=5, SIX=6, FAIL=7;
reg [2:0] state, nstate;
reg [2:0] cnt;
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cnt <= 0;
else
cnt <= cnt==6? 1: cnt+1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
state <= ZERO;
else
state <= nstate;
end
always@(*) begin
if(~rst_n)
nstate = ZERO;
else
case(state)
ZERO : nstate = data? FAIL : ONE;
ONE : nstate = data? TWO : FAIL;
TWO : nstate = data? THREE: FAIL;
THREE: nstate = data? FOUR : FAIL;
FOUR : nstate = data? FAIL : FIVE;
FIVE : nstate = data? FAIL : SIX;
SIX : nstate = data? FAIL : ONE;
FAIL : nstate = cnt==6&&data==0? ONE: FAIL;
default: nstate = ZERO;
endcase
end
always@(*) begin
if(~rst_n) begin
match = 0;
not_match = 0;
end
else begin
match = cnt==6&&state==SIX;
not_match = cnt==6&&state==FAIL;
end
end
endmodule
移位寄存器
本题要求每6个不重叠的数为一组判断是否符合要求,所以需要在移位寄存器的基础上添加一个计数器。当计数器计数到序列长度时,再判断是否match。
`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