序列检测器的verilog实现

一、要求

设计一个序列检测同步时序逻辑电路,要实现的功能如下:

当已有输入码流出现序列111000或101110时输出检测信号为1,否则输出为0。在时序上检测到完整序列的下一个时钟周期输出检测结果。输入信号有效为1时表示当前输入有效,否则表示无效。之前输入依旧计入序列中并不清零,即允许序列重叠检测。例如:

输入码流(设输入数据均有效)和输出检测为

[I] 0 0 1 1 1 0 0 0 1 1 0 1 1 1 0 0 0 0

[O] 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1

模块输入输出功能定义:

名称

方向

位宽

描述

clk

I

1

系统时钟

rst_n

I

1

异步复位,低电平有效

din_vld

I

1

输入数据有效指示

din

I

1

输入数据

result

O

1

输出检测结果

二、实现(Vivado 2017.4)

1、最初的思路

我先按照一次送入6位输入信号自己做了一遍,出于对问题的理解不到位,写的程序写存在问题。如:输入应该一位一位往里送,而且在输入有效即din_vld = 0时输入不能进来,并不是输入无效时把result置0就行。以下是我最初写的程序,仅供参考。

module seq_detect(
	/*端口定义*/
	input 				clk,
	input				rst_n,
	input 				din_vld,
	input		 [5:0]	din,
	output	reg 		result
    );

reg [5:0] tmp;

always @(*)begin
	tmp <= din;
end

always @(posedge clk or negedge rst_n) begin
	tmp <= din;
	if(!rst_n) begin			//异步复位
		tmp <= 6'd0;
	end
	else if(din_vld) begin		//din_vld = 1时,检测到输入为111000或101110则result = 1
		if((tmp[5:0] == 6'b111000)|(tmp[5:0] == 6'b101110))
			result <= 1'b1;
		else					//否则result = 0
			result <= 1'b0;
	end
	else begin					//din_vld = 0时,result = 0
		result <= 1'b0;
	end
end
endmodule

testbench:

`timescale 1ns / 1ps

module tb_seq_detect();

reg			clk;
reg			rst_n;
reg			din_vld;
reg  [5:0]	din;
wire		result;

initial begin
	clk		 = 1'b0;
	rst_n 	 = 1'b0;
	din_vld	 = 1'b0;
	din 	 = 6'd0;
	#40
	din_vld  = 1'b1;
	#100
	rst_n 	 = 1'b1;
	#100
	din 	 = 6'b111000;
	#100
	din 	 = 6'b000000;
	#100
	din 	 = 6'b101110;
	#100
	din_vld	 = 1'b0;
end

always #50 clk = ~clk;

seq_detect u_seq_detect(
	.clk(clk),
	.rst_n(rst_n),
	.din(din),
	.din_vld(din_vld),
	.result(result)
);

endmodule

仿真结果:

 2.移位寄存器比较法

/*模块端口定义*/
module seq_detect(

	input 				clk,
	input				rst_n,
	input 				din_vld,
	input		 		din,
	output	reg 		result
    );
reg [5:0] tmp;

/*初始化寄存器*/
initial begin
	tmp <= 6'd0;
end

/*移位寄存器*/
always @(posedge clk or negedge rst_n) begin

	if(!rst_n)	tmp <= 6'd0;
	else if(din_vld)	tmp[5:0] <= {tmp[4:0],din};
	
end

/*条件判断产生输出*/
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) result <= 1'b0;
	else if(tmp == 6'b111000 || tmp == 6'b101110)	result <= 1'b1;
	else result <= 1'b0;
end


endmodule

 testbench:

`timescale 1ns / 1ps

module tb_seq_detect();
reg			clk;
reg			rst_n;
reg			din_vld;
reg 		din;
wire		result;

initial begin
	clk		 = 1'b0;
	rst_n 	 = 1'b0;
	din_vld	 = 1'b0;
	#10
	din 	 = 1'd0;
	#100
	rst_n 	 = 1'b1;
	din_vld  = 1'b1;	
end

always #50 clk = ~clk; //10MHz
always #2000 din_vld = ~din_vld;

/*产生随机输入*/
always @(posedge clk) begin
	 din <= {$random}%2;	
end

/*实例化测试模块*/
seq_detect u_seq_detect(
	.clk(clk),
	.rst_n(rst_n),
	.din(din),
	.din_vld(din_vld),
	.result(result)
);

endmodule

仿真结果:

可见对于输入的随机序列,在rst_n = 1且din_vld = 1的条件下,满足连续输入的6bit为111000和101110时,输出result = 1。din_vld = 0时输入无效,tmp保持原状态。

3、有限状态机FSM

/*
三段式状态机:三个always模块
1.同步时序描述状态转移;
2.组合逻辑判断状态转移条件;
3.描述状态输出
*/

/*模块端口定义*/
module seq_detect(

	input 				clk,
	input				rst_n,
	input 				din_vld,
	input		 		din,
	output	reg 		result
    );
	
reg [3:0] state, next_state;

/*
	分析: 共有12个状态,对应输入如下:
	idle:0	s1:1	s2:11	s3:111	 s4 :1110	s5 :11100	s6:111000
			s7:10	s8:101	s9:1011	 s10:10111	s11:101110

*/

/*状态编码*/
parameter idle = 4'd0, s1 = 4'd1, s2 = 4'd2, s3 = 4'd3, s4  = 4'd4,  s5  = 4'd5,
			s6 = 4'd6, s7 = 4'd7, s8 = 4'd8, s9 = 4'd9, s10 = 4'd10, s11 = 4'd11;

/*状态转移*/
always @(posedge clk or negedge rst_n) begin

	if(!rst_n) state <= idle;
	else if (din_vld) state <= next_state;
	else			  state <= state;
end

/*转移条件判断*/
always @(*) begin
	case(state)
		idle:	 next_state = din ? s1  : idle;
		s1:		 next_state = din ? s2  : s7;
		s2:		 next_state = din ? s3  : s7;
		s3:		 next_state = din ? s3  : s4;
		s4:		 next_state = din ? s8  : s5;
		s5:		 next_state = din ? s1  : s6;
		s6:		 next_state = din ? s1  : idle;
		s7:		 next_state = din ? s8  : idle;
		s8:		 next_state = din ? s9  : s7;
		s9:		 next_state = din ? s10 : s7;
		s10:	 next_state = din ? s3  : s11;
		s11:	 next_state = din ? s8  : s5;
		default: next_state = idle;
	endcase
end

/*输出描述*/
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)	result <= 1'b0;
	else if(state == s6 || state == s11) result <= 1'b1;
	else	result <= 1'b0;
end

endmodule

testbench同上。

仿真结果:

 可见输入为连续的101110和111000时,在下一个时钟周期有result = 1。

综合结果:

 2022/1/17 1:32 晚安


版权声明:本文为eroDuanDian123456原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。