序列检测器

介绍

  • 目的:在数据流中检测出一定的序列;

    此处数据流在.vt文件中给data,通过移位来一个个赋值给x;例化.v文件,把x传给.v文件,在.v文件中编写二段式状态机转移程序,检测有无序列10010

  • 波形图示例

    新用到Timegen软件画波形;
    评价:波形确实好画,还可以画时序图,就是标0101有点麻烦,不好操作。
    示例中out的第二个脉冲就是容易漏掉的地方

    在这里插入图片描述

转移图

序列检测器一开始看到很容易出错(对于我而言吧):会漏掉一些情况,如转移图中红色、黑色部分。仔细多想

在这里插入图片描述

程序

它的程序还是很简单,就是几个状态的切换(前提是转移图画对了~ )发现这个时候转移图真好用(真香~)
这里用的是二段式状态机

  • SequenceDetector.v
    module SequenceDetector
    (
    	input clk,
    	input rst,
    	input x,
    	output reg z
    );
    reg [2:0] state;
    reg [2:0] next_state;
    parameter IDLE =3'd0;
    parameter A =3'd1;
    parameter B =3'd2;
    parameter C =3'd3;
    parameter D =3'd4;
    parameter E =3'd5;
    
    always @(posedge clk or posedge rst)
    	begin
    		if(rst) 
    				state <= IDLE;
    		else
    			state <= next_state;
    	end
    always @(*)
    	begin
    		case(state)
    			IDLE:
    				begin
    					if(x) begin next_state = A;  z = 1'd0; end
    					else begin next_state= IDLE; z = 1'd0; end
    				end
    			A:
    				begin
    					if(x) begin next_state = A; z = 1'd0; end
    					else begin next_state= B; z = 1'd0; end
    				end	
    			B:
    				begin
    					if(x) begin next_state = A; z = 1'd0; end
    					else begin next_state= C; z = 1'd0; end
    				end	
    			C:
    				begin
    					if(x) begin next_state = D; z = 1'd0; end
    					else begin next_state= IDLE; z = 1'd0; end
    				end	
    			D:
    				begin
    					if(x) begin next_state = A; z = 1'd0; end
    					else begin next_state= E; z = 1'd1; end
    				end	
    			E:
    				begin
    					if(x) begin next_state = A; z = 1'd0; end
    					else begin next_state= C; z = 1'd0; end
    				end	
    			default: 		
    				begin next_state= IDLE; z = 1'd0; end
    		endcase
    	end
    endmodule
    

仿真信号

  • SequenceDetector.vt

    球球你别写testbench时忘了分号了~自动仿真又检测不出来,波形出不来还一直等哈哈

    `timescale 1 ns/ 1 ns
    module SequenceDetector_vlg_tst();
    reg clk;
    reg rst;
    reg x;
                                     
    wire z;
    
    reg [23:0] data;             
    SequenceDetector i1 (
    	.clk(clk),
    	.rst(rst),
    	.x(x),
    	.z(z)
    );
    initial                                                
    	begin                                                  
    	#0 clk = 1'b0;
    	#0 rst = 1'b0;	
    	#3 rst = 1'b1;
    	#3 rst = 1'b0;
    	#1 data = 24'b1100_1001_0000_1001_1100_1001;//一开始多打了一位
    	$display("Running testbench");                       
    	end                                                    
    always #10                                                              
    	begin       
    		clk = ~clk;                                 
    	end      
    always @(posedge clk)
    	begin
    		data <= data<<1;
    		x <= data[23];
    	end
    endmodule
    
  • 仿真结果
    在这里插入图片描述
  • 几点注意
    1. 写的是clk上升沿进行data的移位,所以别被那些长长短短的波形弄糊涂,看沿处;
    2. 其实这里x的变化是比data[23]慢一个clk的:在always中进行非阻塞赋值,所以此always完后x赋值的是上一个data[23],而当前data[23]实际上等于data[22]

重点补充

  • 之前说到.v的input(默认为input wire)在.vt中必须要为reg(1),其实不是这样的,只是说一般这样用,这样用没问题。
    (1)法.vt 的x输出是有锁存的,而(2)法是没有的;
    从使用的理解上,(1)法更清晰(因为我也没理解(2)法的原理哈哈
    1. 这里对.vt 修改,如下:.v的input(默认为input wire)在.vt 中用wire(2)

    wire x;
    assign x = data[23];//assign赋值左边必须得为wire型
    always @(posedge clk)
    	begin
    		data <= data<<1;
    	end
    

    2. 波形

    且assign是阻塞赋值,data一边输出x就会改变,不会慢一个clk
    注意这里看波形图:由于写initial时里面的延时是随便设置的,所以这里x的第一个“1”码时间很短,但不是没有;

    在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值