输入序列不连续的序列检测

描述

题目描述:

请编写一个序列检测模块,输入信号端口为data,表示数据有效的指示信号端口为data_valid。当data_valid信号为高时,表示此刻的输入信号data有效,参与序列检测;当data_valid为低时,data无效,抛弃该时刻的输入。当输入序列的有效信号满足0110时,拉高序列匹配信号match。

模块的接口信号图如下:

模块的时序图如下:

 

 

请使用状态机实现以上功能,画出状态转移图并使用Verilog HDL编写代码实现以上功能,并编写testbench验证模块的功能.

输入描述:

clk:系统时钟信号

rst_n:异步复位信号,低电平有效

data:单比特信号,待检测的数据

data_valid:输入信号有效标志,当该信号为1时,表示输入信号有效

输出描述:

match:当输入信号data满足目标序列,该信号为1,其余时刻该信号为0

题意整理

       题目要求检测a的序列,a为单bit输入,每个时刻可能具有不同的值,且并不是每一个数据都是有效的,需要根据data_valid信号进行判断。在状态转化过程中,当data_valid为0,表示该时刻是输入数据无效,应保持在当前状态。当data_valid为1,再根据输入数据是否匹配进行下一个状态的值。

题解主体

       对于序列检测题目,常规的解法有两种:状态机法和序列缓存对比法。

状态机法的过程类似于题意理解中提到的过程:在初始状态中,在data_valid有效时逐一判断当前时刻的数值。先判断第一位是否符合,若符合则进入下一个状态,判断第二位是否符合;若第一位不符合则保持在初始状态,直到第一位匹配。如前两位匹配,则判断第三位是否符合,若第一位匹配,最新输入的数值和目标序列的第二位不匹配,则根据最新一位是否匹配第一位,进入第一位匹配状态或者初始状态。依次类推。

序列缓存对比法,则是将四个data_valid有效的数据data缓存,作为一个数组,每个时刻的输入位于数组的末尾,数组其它元素左移,把最早输入的数据移出。如果数组和目标序列相等,则说明出现目标序列。拉高match信号。

题目要求使用状态机实现,首先画出状态转移图。

 

s1_d0表示第一位0匹配,s2_d01表示前两位01匹配,s3_d011表示前三位011匹配,s4_d0110表示四位数值0110全部匹配。X表示不论data的值为0或1,都完成该状态跳变。依据状态转移图编写verilog代码:

always @(posedge clk or negedge rst_n)

begin

    if(!rst_n)

        pstate<=idle;

    else

        pstate<=nstate;

end

always @(pstate or data)

begin

    case(pstate)

        idle:

            if(data_valid && !data)

                nstate=s1_d0;              //第一位匹配

            else

                nstate=idle;

        s1_d0:

            if (data_valid)

                            begin 
                                    if (data) nstate = s2_d01;           //数据有效且为1,即前两位//01匹配,下一状态为s2_d01
                                    else nstate = s1_d0;                   //数据有效但为0,即只有第一//位0匹配,下一状态为s1_d0                                                        
                            end

                     else nstate = s1_d0;                                 //数据无效,保持在s1_d0

        s2_d01:

            if (data_valid)

                            begin  
                                    if (data) nstate = s3_d011;          //数据有效且为1,即前三位//011匹配,下一状态为s3_d011
                                    else nstate = s1_d0;                   //数据有效但为0,即只有第一//位0匹配,下一状态为s1_d0
                             end
                     else nstate = s2_d01;                               //数据无效,保持在s2_d01

        s3_d011:

            if (data_valid)

                            begin    
                                   if (!data) nstate = s4_d0110;       //数据有效且为0,即前四位//0110匹配,下一状态为s4_d0110
                                     else nstate = idle;                              //数据有效但为1,即不匹//配,下一状态为idle
                            end
                     else nstate = s3_d011;                             //数据无效,保持在s3_d011

        s4_d0110:

            if (data_valid)

                            begin    
                                if (!data) nstate = s1_d0;            //数据有效且为0,即匹配目标//序列的第一位0,下一状态为s1_d0
                                   else nstate = idle;                //数据有效但为1,不匹配目标序列,下一状态为idle
                            end
                     else nstate = idle;                              //数据无效,下一状态为idle

        default:

            nstate=idle;

        endcase

end

always @(pstate or rst_n)

begin

    if(!rst_n==1)

        match=1'b0;

    else if(pstate==s4_d0110)                                      //进入状态s4_d0110表示四位数据都匹配,把匹配指示信号match拉高

            match=1'b1;

         else

            match=1'b0;

end

 参考答案

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	input data_valid,
	output reg match
	);


reg [3:0] pstate,nstate;

parameter idle=4'd0,
		  s1_d0=4'd1,
          s2_d01=4'd2,
          s3_d011=4'd3,
          s4_d0110=4'd4;

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        pstate<=idle;
    else
        pstate<=nstate;
end

always @(pstate or data or data_valid)
begin
    case(pstate)
        idle:
            if(data_valid && !data)
                nstate=s1_d0;			//第一位匹配
            else
                nstate=idle;
        s1_d0:
            if (data_valid)
				begin	
					if (data) nstate = s2_d01;		//数据有效且为1,即前两位01匹配,下一状态为s2_d01
					else nstate = s1_d0;			//数据有效但为0,即只有第一位0匹配,下一状态为s1_d0
				end
			else nstate = s1_d0;					//数据无效,保持在s1_d0
        s2_d01:
            if (data_valid)
				begin	
					if (data) nstate = s3_d011;		//数据有效且为1,即前三位011匹配,下一状态为s3_d011
					else nstate = s1_d0;			//数据有效但为0,即只有第一位0匹配,下一状态为s1_d0
				end
			else nstate = s2_d01;					//数据无效,保持在s2_d01
        s3_d011:
            if (data_valid)
				begin	
					if (!data) nstate = s4_d0110;		//数据有效且为0,即前四位0110匹配,下一状态为s4_d0110
					else nstate = idle;					//数据有效但为1,即不匹配,下一状态为idle
				end
			else nstate = s3_d011;					//数据无效,保持在s3_d011
        s4_d0110:
            if (data_valid)
				begin	
					if (!data) nstate = s1_d0;		//数据有效且为0,即匹配目标序列的第一位0,下一状态为s1_d0
					else nstate = idle;			//数据有效但为1,不匹配目标序列,下一状态为idle
				end
			else nstate = idle;					//数据无效,下一状态为idle
        default:
            nstate=idle;
        endcase
end

always @(pstate or rst_n)
begin
    if(!rst_n==1)
        match=1'b0;
    else if(pstate==s4_d0110)						//进入状态s4_d0110表示四位数据都匹配,把匹配指示信号match拉高
            match=1'b1;
         else
            match=1'b0;
end

endmodule

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值