序列检测器原理及其实现(单次检测及目标序列计数)

序列检测

序列检测主要功能是:将一个指定的序列从数字码流中识别出来,当然也可以实现对指定序列的计数。

序列检测的工具是状态机。

输出只和状态有关,而与输入无关,称为Moore状态机;
输出不仅和状态有关而且和输入有关系,称为Mealy状态机

在进行序列检测之前,需要我们画出状态转换表或者状态转换图。

本次假设我们需要检测 110010

我们画出以下状态表

S0为空闲状态
x为下个输入
在这里插入图片描述
这样我们就可以利用状态机写出代码

可看到,我们在最后有个S6的下一个状态没写,S6的下个状态写什么可以实现不一样的功能。
1、S6的所有下个状态(不论输入的是什么)都为S6,则实现的是序列检测,检测到序列就保持当前状态。
2、当在S6的状态下,如果输入0后转到S0,输入1的时候转到S1,那么就可以实现序列多次检测,也就是检测序列的个数。

1、序列检测

Verilog代码

module check_bit(
	input							clk,
	input							rst_n,
	
	input							din,			// 数据输入
	
	output	reg	[5:0]				current_state,
	output							Y				// 是否检测到序列
	);
	
	
	localparam	IDLE 	= 6'b000000;
	localparam	S1 		= 6'b000001;
	localparam	S11		= 6'b000010;
	localparam	S110 	= 6'b000100;
	localparam	S1100 	= 6'b001000;
	localparam	S11001 	= 6'b010000;
	localparam	S110010 = 6'b100000;
	
	reg	[5:0]			next_state;
	
	
	assign Y = (current_state == S110010);
	
	
	/******状态转移******/
	always@(posedge clk or negedge rst_n) begin	
		if(!rst_n)
			current_state <= IDLE;
		else	
			current_state <= next_state;
	end
	
	/******序列检测******/
	always@(*) begin
		if(!rst_n)
			next_state <= IDLE;
		else 
			case(current_state)
				IDLE		: 	next_state <= din? S1:IDLE;
				S1			:	next_state <= din? S11:IDLE;
				S11			:	next_state <= din? S11:S110;
				S110		:	next_state <= din? S1:S1100;
				S1100		:	next_state <= din? S11001:IDLE;
				S11001		:	next_state <= din? S11:S110010;
				S110010		:	next_state <= S110010;
				//S110010	:	next_state <= din?S1:IDLE;
				default		:	next_state <= IDLE;
			endcase
	end
	
	
endmodule

testbench文件

`timescale 1ns/1ns
`define clk_period 20



module check_bit_tb();

	reg				clk;
	reg				rst_n;
	wire			din;
	reg		[23:0]	data;    
	wire			Y;
	wire	[5:0]	state;
	
	assign din = data[23];

	check_bit check_bit(
		.clk				(clk),
		.rst_n			(rst_n),
		.din				(din),
		.Y					(Y),
		.current_state	(state)
		);
	
	initial clk = 1;
	always #(`clk_period/2) clk = ~clk;
	always @(posedge clk)
		data={data[22:0],data[23]};//移位输出码流
	initial begin
		rst_n = 0;
		#20;
		rst_n = 1;
		#20;
		data=20'b1010_1001_1100_1001_0100;//码流数据
		#(`clk_period*500)$STOP;//运行500个时钟周期后停止仿真
	end
	
endmodule

在这里插入图片描述

由图中可以看到,检测到110010后,Y输出1

2、序列计数

如果需要对序列进行计数,只需要在代码的case中改变S110010的状态转移,变为注释的那一行,并使用计数器计数就行了。

源代码

module check_bit(
	input							clk,
	input							rst_n,
	
	input							din,			// 数据输入
	
	output	reg	[5:0]		current_state,
	output	reg	[7:0]		Y_cnt = 0,			// 序列计数
	output						Y				// 是否检测到序列
	);
	
	
	localparam	IDLE 		= 6'b000000;
	localparam	S1 		= 6'b000001;
	localparam	S11		= 6'b000010;
	localparam	S110 		= 6'b000100;
	localparam	S1100 	= 6'b001000;
	localparam	S11001 	= 6'b010000;
	localparam	S110010 	= 6'b100000;
	
	//reg	[5:0]			current_state;
	reg	[5:0]			next_state;

	
	
	assign Y = (current_state == S110010);
	
	/******序列计数******/
	always@(posedge clk or negedge rst_n) begin	
		if(!rst_n)
			Y_cnt <= 8'd0;
		else if(current_state == S110010)
			Y_cnt <= Y_cnt + 1'b1;
		else 
			Y_cnt <= Y_cnt;
	end
	
	
	/******状态转移******/
	always@(posedge clk or negedge rst_n) begin	
		if(!rst_n)
			current_state <= IDLE;
		else	
			current_state <= next_state;
	end

	
	/******序列检测******/
	always@(*) begin
		if(!rst_n)
			next_state <= IDLE;
		else 
			case(current_state)
				IDLE		: 	next_state <= din? S1:IDLE;
				S1			:	next_state <= din? S11:IDLE;
				S11		:	next_state <= din? S11:S110;
				S110		:	next_state <= din? S1:S1100;
				S1100		:	next_state <= din? S11001:IDLE;
				S11001	:	next_state <= din? S11:S110010;
				S110010	:	next_state <= din? S1:IDLE;
				//S110010	:	next_state <= IDLE;
				default	:	next_state <= IDLE;
			endcase
	end
	
	
endmodule

testbench文件

`timescale 1ns/1ns
`define clk_period 20



module check_bit_tb();

	reg				clk;
	reg				rst_n;
	wire			din;
	reg		[39:0	]data;    
	wire			Y;
	wire	[5:0]	state;
	wire	[7:0]	Y_cnt;
	
	assign din = data[39];

	check_bit check_bit(
		.clk			(clk),
		.rst_n			(rst_n),
		.din			(din),
		.Y				(Y),
		.Y_cnt			(Y_cnt),
		.current_state	(state)
		);
	
	initial clk = 1;
	always #(`clk_period/2) clk = ~clk;
	always @(posedge clk)
		//#2 data={data[22:0],data[23]};//移位输出码流
		data={data[38:0],data[39]};//移位输出码流
	initial begin
		rst_n = 0;
		#2;
		rst_n = 1;
		#3;
		data=40'b1100_1001_1100_1001_0100_1100_1011_0010_1100_1011;//码流数据
		#(`clk_period*40)	data = 40'dz;//运行500个时钟周期后停止输入数据
	end
	
	
	
endmodule

在这里插入图片描述

在tb文件中,输入序列为1100_1001_1100_1001_0100_1100_1011_0010_1100_1011
共有5个序列
在下图中,仿真计数得到的序列也为5个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值