IC基础(五):序列检测器

时间:2024-03-23 13:56:58

参考:https://blog.csdn.net/Reborn_Lee/article/details/85763185
序列检测器经常出现在笔试题目当中,其实其中的主要思想还是状态机的设计,因此本文也借着序列检测器这一点,讲讲状态机的设计。

一、序列检测器要是实现什么功能?
序列检测器主要是实现输入的一串序列是否是特定的序列。比如设计一个序列检测器,检测序列“11001”,检测到就输出1,否则输出0。

二、设计状态机来检测序列

首先要设计状态机,最好是先把状态转换图先画出来,有了状态转换图一切设计就很好办了。

IC基础(五):序列检测器
根据状态转换图很容易就写出状态机了。状态机代码如下。

源文件:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/04/01 16:29:18
// Design Name: 
// Module Name: seq_det_moore
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module seq_det_moore(
input		Clk,
input		Rst_n,
input		Din,
output		reg	Dout
    );
    
    //
    localparam		  [2:0] S0 = 3'b000;
    localparam	      [2:0] S1 = 3'b001;
    localparam		  [2:0] S2 = 3'b010;
    localparam       [2:0] S3 = 3'b011;
    localparam       [2:0] S4 = 3'b100;
    localparam       [2:0] S5 = 3'b101;
    
    reg	[2:0] Current_State;
    reg	[2:0] Next_State;
    
    [email protected](posedge Clk or negedge Rst_n)begin
    	if(!Rst_n)begin
    		Current_State <= S0;
    	end
    	else begin
    		Current_State <= Next_State;
    	end
    end
    
    [email protected](Current_State or Din)begin
    	case(Current_State)
    		S0:begin
    			if(Din==1'b1)
    				Next_State = S1;
    			else
    				Next_State = S0;
    		end
    		S1:begin
    			if(Din==1'b1)
    				Next_State = S2;
    			else
    				Next_State = S0;
    		end
    		S2:begin
    			if(Din==1'b0)
    				Next_State = S3;
    			else
    				Next_State = S2;
    		end
    		S3:begin
    			if(Din==1'b0)
    				Next_State = S4;
    			else
    				Next_State = S1;
    		end
    		S4:begin
    			if(Din==1'b1)
    				Next_State = S5;
    			else
    				Next_State = S0;
    		end
    		S5:begin
    			if(Din==1'b1)
    				Next_State = S1;
    			else
    				Next_State = S0;
    		end
    		
    		default:
    			Next_State = S0;
    	endcase
    end
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 //这里有四种四处方式,使用时需要去掉对应的注释
///////////////////////////////////////////////////////////////////////////////////////////////////////////  	
//第一种组合状态输出
[email protected](Current_State) begin
	if(Current_State==S5)
		Dout = 1'b1;
	else
		Dout = 1'b0;
end

//第二种组合状态输出
// 	[email protected](posedge Clk) begin
//	if(Current_State==S5)
//		Dout = 1'b1;
//	else
//		Dout = 1'b0;
//end

//第三种组合状态输出
//[email protected](posedge Clk) begin
//		if(Next_State==S5)
//			Dout = 1'b1;
//		else
//			Dout = 1'b0;
//end
	
//第四种组合状态输出
//[email protected](Next_State) begin
//		if(Next_State==S5)
//			Dout = 1'b1;
//		else
//			Dout = 1'b0;
//	end
endmodule

测试文件:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/04/01 16:53:46
// Design Name: 
// Module Name: tb_seq
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_seq;

reg		Clk;
reg		Rst_n;
reg		Din;
reg	 [20:0] din_mid;
wire		Dout;
integer i;
parameter		CLK_PERIOD = 10;

always # (CLK_PERIOD/2) Clk = ~Clk;

initial begin
Clk = 0;
end

initial begin
	Rst_n = 1'b0;
	din_mid = 21'b1100_0101_1100_1010_11101;
	Din = 0;
	#20;
	Rst_n = 1'b1;
	#5;
	for(i=20;i>=0;i=i-1) begin
		#CLK_PERIOD;
		Din = din_mid[i];
	end
end

seq_det_moore uut(
.Clk(Clk),
.Rst_n(Rst_n),
.Din(Din),
.Dout(Dout)
    );
    
endmodule

第一种组合输出的波形图:

//1
//[email protected](Current_State) begin
//	if(Current_State==S5)
//		Dout = 1'b1;
//	else
//		Dout = 1'b0;
//end

IC基础(五):序列检测器
第二种组合输出的波形图:

//2
// 	[email protected](posedge Clk) begin
//	if(Current_State==S5)
//		Dout = 1'b1;
//	else
//		Dout = 1'b0;
//end

IC基础(五):序列检测器

第三种组合输出波形图:

////3
//[email protected](posedge Clk) begin
//		if(Next_State==S5)
//			Dout = 1'b1;
//		else
//			Dout = 1'b0;
//end

IC基础(五):序列检测器

第四种组合输出波形图:

////4
//[email protected](Next_State) begin
//		if(Next_State==S5)
//			Dout = 1'b1;
//		else
//			Dout = 1'b0;
//	end

IC基础(五):序列检测器

三、状态机的输出的写法
借助这个序列检测器说一下状态机如何写,只说三段式状态机。

1、说明部分(也就是定义各种状态)

    localparam		  [2:0] S0 = 3'b000;
    localparam	      [2:0] S1 = 3'b001;
    localparam		  [2:0] S2 = 3'b010;
    localparam        [2:0] S3 = 3'b011;
    localparam        [2:0] S4 = 3'b100;
    localparam        [2:0] S5 = 3'b101;
    
    reg	[2:0] Current_State;
    reg	[2:0] Next_State;

2、三段状态机
第一段,次态到现态的转换。

    [email protected](posedge Clk or negedge Rst_n)begin
    	if(!Rst_n)begin
    		Current_State <= S0;
    	end
    	else begin
    		Current_State <= Next_State;
    	end
    end

第二段:状态译码过程
[email protected](敏感表),敏感表中是输入和当前状态。这个过程只能是组合逻辑,里面的赋值用‘=’号。

    [email protected](Current_State or Din)begin
    	case(Current_State)
    		S0:begin
    			if(Din==1'b1)
    				Next_State = S1;
    			else
    				Next_State = S0;
    		end
    		S1:begin
    			if(Din==1'b1)
    				Next_State = S2;
    			else
    				Next_State = S0;
    		end
    		S2:begin
    			if(Din==1'b0)
    				Next_State = S3;
    			else
    				Next_State = S2;
    		end
    		S3:begin
    			if(Din==1'b0)
    				Next_State = S4;
    			else
    				Next_State = S1;
    		end
    		S4:begin
    			if(Din==1'b1)
    				Next_State = S5;
    			else
    				Next_State = S0;
    		end
    		S5:begin
    			if(Din==1'b1)
    				Next_State = S1;
    			else
    				Next_State = S0;
    		end
    		
    		default:
    			Next_State = S0;
    	endcase
    end

第三段:输出过程
这一段的输出有很多种写法,主要分为当前状态和下一状态输出,也就是在上面讨论的四种输出波形。其中,常用的输出方式如下:

第一种:

[email protected](Current_State) begin
	if(Current_State==S5)
		Dout = 1'b1;
	else
		Dout = 1'b0;
end

第二种:

////3
//[email protected](posedge Clk) begin
//		if(Next_State==S5)
//			Dout = 1'b1;
//		else
//			Dout = 1'b0;
//end

这两种输出波形是一样的,都是在当前周期输出结果。

如果要延缓一个周期就需要用种方式:

// 	[email protected](posedge Clk) begin
//	if(Current_State==S5)
//		Dout = 1'b1;
//	else
//		Dout = 1'b0;
//end