功能说明:
•捕捉11010110序列
•在捕捉到每个序列后产生一个1时钟周期的标记信号
•对捕捉到序列个数进行计数并输出
•计数上限为16,计数满后值保持不变,产生计数慢的溢出信号
•允许序列的嵌套
设计思路:
采用mealy型有限状态机
状态图如下所示
在状态转换图中,状态与状态之间的跳变的判定条件实现了序列的嵌套,具体如图上所示。
代码实现
设计模块
`timescale 1 ps/ 1 ps //产生flag信号时需要用到
module detect_11010110(clk,rst_,din,counter,overflow,flag );
//输入——din串行输入检测信号,clk时钟信号,rst_复位信号
//输出——counter计数信号,overflow计数溢出信号,flag标记信号
input din,clk,rst_;
output counter,overflow,flag;
//检测到的序列的数目
reg [4:0] counter;
//数目大于16,溢出,捕捉到序列后产生一个1时钟周期的标记信号
reg overflow,flag;
reg [3:0] state,next_state;
parameter
s0=4'b0000,s1=4'b0001,s2=4'b0010,s3=4'b0011,s4=4'b0100,s5=4'b0101,s6=4'b0110,s7=4'b0111,s8=4'b1000;//参数分别对应初状态和状态一至八
//敏感信号:clk上升沿,rst_下降沿,state,next_state,din
always @(posedge clk or negedge rst_)
begin
if (!rst_)
state=s0;//复位信号,低电平有效,状态恢复至s0
else
state<=next_state;
end
always @(state or din or rst_)//状态转换代码实现
begin
if (!rst_)
next_state=s0;
else
case(state)
s0:begin
if (din==1) next_state=s1;
else next_state = s0;
end
s1:begin
if (din==1) next_state=s2;
else next_state=s0;
end
s2:begin
if (din==0) next_state=s3;
else next_state=s2;
end
s3:begin
if (din==1) next_state=s4;
else next_state=s0;
end
s4:begin
if (din==0) next_state=s5;
else next_state=s2;
end
s5:begin
if (din==1) next_state=s6;
else next_state=s0;
end
s6:begin
if (din==1) next_state=s7;
else next_state=s0;
end
s7:begin
if (din==0) next_state=s8;
else next_state=s2;
end
s8:begin
if (din==1) next_state=s1;
else next_state=s4;
end
default: next_state = s0;
endcase
end
always @(posedge clk or negedge rst_)
if(!rst_)
flag<=1'b0;
else if(state == s8)
begin
#10 flag<=1'b1;
#10 flag<=1'b0;//检测到序列11010110后输出一个flag信号,长度为一个时钟周期
end
else;
always @(posedge clk)//实现序列检测的计数
begin
if(!rst_)//复位信号有效,计数输出信号和溢出信号清0
begin
counter<=0;
overflow<=0;
end
else if(state == s8)
counter<=counter+5'b00001;
begin
if (counter>=5'b10000)
begin
overflow<=1;
counter<=510000;
end
else overflow<=0;
end
end
endmodule
测试模块
`timescale 1 ps/ 1 ps
module detect_11010110_vlg_tst();
reg clk;
reg din;
reg rst_;
// wires
wire [4:0] counter;
wire flag;
wire overflow;
detect_11010110 i1 (
.clk(clk),
.counter(counter),
.din(din),
.flag(flag),
.overflow(overflow),
.rst_(rst_)
);
initial //时钟信号,时钟周期为10
begin
// code that executes only once
// insert code here --> begin
#0 clk=0;
forever #5 clk=~clk;
end
initial//复位信号
begin
// --> end
#0 rst_=1;
#20 rst_=0;
#20 rst_=1;
$display("Running testbench");
end
initial
$monitor($time,,"counter=%d overflow=%b",counter,overflow);
//调用monitor函数,监控和输出参数counter和overflow的值
initial
begin
//产生随机的串行输入检测信号din
din=0;//起始为0
repeat(5000)//重复5000次,每隔10ps输入一个
begin
# 10 din={$random} % 2;
end
$stop;//调用stop函数
end
endmodule
仿真结果
Monitor函数输出结果
检测到第一个11010110信号,输出一个一时钟周期宽度的flag信号
计数计到16,产生overflow溢出信号,counter值保持不变