Verilog设计_序列检测

序列检测的Verilog设计。

 


一、概述

序列检测是手撕代码中经常会出现的一道题目。所谓序列检测就是将一个指定的序列从数字码流中识别出来,同时也可以实现对指定序列的计数。检测工具一般为状态机,通过状态机跳转来实现识别的过程。

状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。有限状态机(Finite State Machine)即FSM,可分为两种:

(1)输出只和状态有关,与输入无关,为Moore型状态机。

(2)输出和状态、输入都有关系,则称为Mealy型状态机。

实现序列检测也可以不使用状态机。状态机的跳转逻辑写起来会比较复杂,但是会比较直接,我们只需要关注每一步的跳转。不使用状态机的实现会更简洁,但是会使用更多的dff,尤其是当检测序列比较长的时候,会占用更多的面积,不利于低功耗的实现。

二、代码实现

(1)状态机

使用两种不同的状态机来实现,检测序列1101。并统计出现次数。

Moore型,输出只和状态有关:

module moore(
    input clk, rst_n, 
    input din, 
    output dout, 
    output reg [31:0] cnt
);

    reg [2:0] cs;
    reg [2:0] ns;
    parameter S0 = 3'b000; // 0
    parameter S1 = 3'b001; // 1
    parameter S2 = 3'b010; // 11
    parameter S3 = 3'b011; // 110 
    parameter S4 = 3'b100; // 1101

    always @(posedge clk or negedge rst_n) begin
        if(rst_n == 0)begin
            cs  <= S0;
        end
        else begin
            cs <= ns;
        end
    end

    always @(*) begin
        case (cs)
            S0: ns = (din==1)? S1:S0;
            S1: ns = (din==1)? S2:S0; 
            S2: ns = (din==1)? S2:S3; 
            S3: ns = (din==1)? S4:S0; 
            S4: ns = (din==1)? S2:S0;
            default: ns = S0;
        endcase
    end

    assign dout = (cs == S4)? 1:0;

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 32'b0;
        end
        else if(cs == S4)begin
            cnt <= cnt+1;
        end
        else begin
            cnt <= cnt;
        end
    end


endmodule

测试波形:

Mealy型,输出和状态、输入都有关系:

module mealy(
    input clk, rst_n, 
    input din, 
    output reg dout, 
    output reg [31:0] cnt
);

    reg [1:0] cs;
    reg [1:0] ns;
    parameter S0 = 3'b00; // 0
    parameter S1 = 3'b01; // 1
    parameter S2 = 3'b10; // 11
    parameter S3 = 3'b11; // 110 

    always @(posedge clk or negedge rst_n) begin
        if(rst_n == 0)begin
            cs <= S0;
        end
        else begin
            cs <= ns;
        end
    end

    always @(*) begin
        case (cs)
            S0: ns = (din==1)? S1:S0;
            S1: ns = (din==1)? S2:S0; 
            S2: ns = (din==1)? S2:S3; 
            S3: ns = (din==1)? S1:S0; 
            default: ns = S0;
        endcase
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            dout <= 0;
        end
        else if(cs == S3 && din == 1)begin
            dout <= 1;
        end
        else begin
            dout <= 0;
        end
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 32'b0;
        end
        else if(cs == S3 && din == 1)begin
            cnt <= cnt+1;
        end
        else begin
            cnt <= cnt;
        end
    end

endmodule

 测试波形:

随着检测序列的加长,状态会越来越多,状态机会越来越复杂。如果是很长的一段序列,用状态机来实现就会非常困难。

(2)参数化实现

使用参数化实现来检测序列,主体是移位寄存器。

代码实现:

module para #(parameter SEQ = 8'b1101_1101,parameter WIDTH = 8)(
    input clk,
    input rst_n,
    input din,
    output dout,
    output reg [31:0] cnt
);
	
    reg [WIDTH-1:0] in_buf;
    
    always @ (posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            in_buf <= ~{WIDTH{SEQ[WIDTH-1]}};
        end
        else begin
            in_buf <= {in_buf[WIDTH-2:0],din};
        end
    end
    
    assign dout = (in_buf == SEQ)? 1:0;

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 32'b0;
        end
        else if(in_buf == SEQ)begin
            cnt <= cnt+1;
        end
        else begin
            cnt <= cnt;
        end
    end
		
endmodule

测试波形,序列1101_1101:

需要注意in_buf定义的复位值,不能简单为0,需要根据所检测的序列来判断。例如极端情况,检测序列为0000,如果复位值也都是0,此时检测会出现错误,所以需要复位为全1。简单来说就是要判断检测序列的最高位,并相应展宽取反。

测试波形,序列0000:

in_buf的复位值为F,为了检测全0的序列。


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clock_926

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值