功能说明:
•捕捉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;parameters0=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,dinalways @(posedge clk or negedge rst_)beginif (!rst_)state=s0;//复位信号,低电平有效,状态恢复至s0elsestate<=next_state;endalways @(state or din or rst_)//状态转换代码实现beginif (!rst_)next_state=s0;elsecase(state)s0:beginif (din==1) next_state=s1;else next_state = s0;ends1:beginif (din==1) next_state=s2;else next_state=s0;ends2:beginif (din==0) next_state=s3;else next_state=s2;ends3:beginif (din==1) next_state=s4;else next_state=s0;ends4:beginif (din==0) next_state=s5;else next_state=s2;ends5:beginif (din==1) next_state=s6;else next_state=s0;ends6:beginif (din==1) next_state=s7;else next_state=s0;ends7:beginif (din==0) next_state=s8;else next_state=s2;ends8:beginif (din==1) next_state=s1;else next_state=s4;enddefault: next_state = s0;endcaseendalways @(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信号,长度为一个时钟周期endelse;always @(posedge clk)//实现序列检测的计数beginif(!rst_)//复位信号有效,计数输出信号和溢出信号清0begincounter<=0;overflow<=0;endelse if(state == s8)counter<=counter+5'b00001;beginif (counter>=5'b10000)beginoverflow<=1;counter<=510000;endelse overflow<=0;endendendmodule
测试模块
`timescale 1 ps/ 1 psmodule 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;endinitial//复位信号begin // --> end#0 rst_=1;#20 rst_=0;#20 rst_=1; $display("Running testbench");endinitial$monitor($time,,"counter=%d overflow=%b",counter,overflow);//调用monitor函数,监控和输出参数counter和overflow的值 initial begin //产生随机的串行输入检测信号din din=0;//起始为0repeat(5000)//重复5000次,每隔10ps输入一个begin# 10 din={$random} % 2;end$stop;//调用stop函数 end endmodule
仿真结果
Monitor函数输出结果
检测到第一个11010110信号,输出一个一时钟周期宽度的flag信号
计数计到16,产生overflow溢出信号,counter值保持不变