15.1_使用Verilog设计:一个简单的状态机设计——序列检测器(可实现重复性检测)

时间:2024-01-26 22:51:46

使用Verilog设计:一个简单的状态机设计——序列检测器(可实现重复性检测)

  • 1,一个简单的状态机设计:可重复性序列检测器
  • 2,可重复性状态机序列检测实现
    • 2.1,RTL设计代码实现
    • 2.2,tb测试代码实现
    • 2.3,生成的原理图
    • 2.4,SIM输出波形实现

1,一个简单的状态机设计:可重复性序列检测器

序列检测器的逻辑功能:
序列检测是将一个指定的序列从数字码流中识别出来。本项目要检测的序列是:10010。
设X是“数字码流的输入”,Z是“检出标记输出”;高电平是“实现指定序列”;低电平是“没有发现指定序列”。码流如下表所示。

在这里插入图片描述

由上述码流可知:该序列检测器可实现重复性检测,由此可得如下状态转移图,如图1所示:

在这里插入图片描述

2,可重复性状态机序列检测实现

结合表1码流序列和图1状态转换,可编写如下RTL代码

2.1,RTL设计代码实现

//
//	可检测重复的序列
module	seqdet(
input				i_clk,
input				x,
input				i_rst,
output				z,
output	reg	[7:0]	state
);
//	独热码来做参数
parameter		IDLE = 8'b0000_0001;	//	1,	1
parameter		A	 = 8'b0000_0010;	//	2,	2
parameter		B	 = 8'b0000_0100;	//	3,	4
parameter		C	 = 8'b0000_1000;	//	4,	8

parameter		D	 = 8'b0001_0000;	//	5,	16
parameter		E	 = 8'b0010_0000;	//	6,	32
parameter		F	 = 8'b0100_0000;	//	7,	64
parameter		G	 = 8'b1000_0000;	//	8,	128

assign	z = (state==D && x==0) ? 1 : 0;
//	当x序列 10010 最后一个 0刚到时刻,时钟沿立刻将状态变为E,此时z应该变为高

//	assign	z = (state == E) ? 1 : 0;
//	当完成 "10010" 状态的检测,即输出1.
always@(posedge i_clk or negedge i_rst)	begin
	if(!i_rst)	
		state	<= IDLE;
	else 
		case(state)
			IDLE: if(x == 1)		//	下
					state	<= A;
				  else
					state	<= IDLE;
					
			A:	if(x == 0)			//	下
					state	<= B;
				else
					state	<= A;
					
			B:	if(x == 0)			//	下
					state	<= C;
				else
					state	<= F;
					
			C:	if(x == 1)			//	下
					state	<= D;
				else
					state	<= G;
					
			D:	if(x == 0)			//	输出
					state	<= E;
				else
					state	<= A;

			E:	if(x == 0)
					state	<= C;
				else
					state	<= A;
					
			F:	if(x == 1)
					state	<= A;
				else	
					state	<= B;
					
			G:	if(x == 1)
					state	<= F;
				else
					state	<= G;
					
			default:
					state	<= IDLE;
		endcase
end

endmodule

2.2,tb测试代码实现

//	测试模块
module	tb_seqdet;
//	`define	halfperiod	20	宏定义
//	注意",宏定义的位置放哪都行。

reg		i_clk,	i_rst;
reg		[23:0]	data;

wire	[7:0]	state;
wire	z, x;

assign	x = data[23];

always 	#10		i_clk = ~i_clk;

always@(posedge i_clk)
		data <= {data[22:0], data[23]};	
		// 形成数据向左移环形流,最高位与x连接

initial	begin
		i_clk = 1;	i_rst = 1;
		
#2;		i_rst = 0;	
#30;	i_rst = 1;

data	= 24'b0000_1100_1001_0000_1001_0100;
#480;	$stop;
end

seqdet	u1_seqdet(
.i_clk		(i_clk	),
.i_rst		(i_rst	),
.x			(x		),
.z			(z		),
.state		(state	)
);

endmodule

2.3,生成的原理图

在这里插入图片描述

2.4,SIM输出波形实现

在这里插入图片描述

从波形中可看出,程序代码正确地完成了所要设计的逻辑功能。另外,seqdet.v的编写采用了可综合的Verilog HDL风格,它可以把通过综合器的综合转换为FPGA或ASIC网表,再通过布局布线工具在FPGA或ASIC上实现。