序列检测器二

101101序列检测器

module seqdet
(
   input wire x,
   input wire clk,
   input wire rst_n,
   output reg z
);
//用verilog设计一个 101101 序列的检测器
reg [4:0] cs,ns;
localparam [4:0]	IDLE	=5'd0,
						  A 	=5'd1,
						  B 	=5'd2,
						  C 	=5'd3,
						  D 	=5'd4,
						  E 	=5'd5,
						  F   =5'd6;
//状态转移
always @ (posedge clk,negedge rst_n)
	if(!rst_n)
		cs	<= IDLE;
	else
		cs <= ns;
//组合逻辑,产生下一状态译码逻辑,判断条件为cs当前状态
always @ (*)
begin
	ns = 5'bx;
	case(cs)
		IDLE:
			begin
				if(x==1)
					ns = A;
				else
					ns = IDLE;
			end
		A:
			begin
				if(x==0)
					ns = B;
				else
					ns = A;
			end
		B:
			begin
				if(x==1)
					ns = C;
				else
					ns = IDLE;
			end
		C:
			begin
				if(x==1)
					ns = D;
				else
					ns = B;
			end
		D:
			begin
				if(x==0)
					ns = E;
				else
					ns = A;
			end
		E:
			begin
				if(x==1)
					ns = F;
				else
					ns = IDLE;
			end
		F:
			begin
				if(x==1)
					ns = D;
				else
					ns = B;
			end
		default:
			ns = IDLE;
	endcase
end
//第三段always--状态寄存输出,判断条件是ns即下一个状态

always @ (posedge clk,negedge rst_n)
begin
	if(!rst_n)
		z <= 1'b0;
	else
		begin
		case(ns)
			IDLE,A,B,C,D,E :	z <= 1'b0;
			F				   :	z <= 1'b1;
			default:	z <= 1'b0;
		endcase
		end
end

//assign z = (ns==F);

endmodule  
特别注意,在三段式FSM描述中,判断状态转移的always模块的case语句判断条件是cs,而在同步时序FSM的寄存输出的always模块中的case语句判断条件是下一个状态ns。
测试代码:
`timescale 1ns/1ns
module seqdet_tb;
localparam T =20;
reg clk,rst;
reg [23:0] data;
wire z,x;
//wire [4:0] q;

assign x = data[23];

initial
begin
    clk =0;
    rst =1;
    #2 rst =0;
    #30 rst =1;
    data =20'b1000_1101_0110_1011_0100;
    #(T*1000) $stop;
end

always #T clk = ~clk;

always @ (posedge clk)
   #2 data = {data[22:0],data[23]};
   
seqdet U1
(
   .x(x),
   .z(z),
   .clk(clk),
 //  .q(q),
   .rst_n(rst)
);

endmodule

最后的输出Z被寄存了,故而输出相对延迟了一个时钟周期

若最后的输出代码改为:

module seqdet
(
   input wire x,
   input wire clk,
   input wire rst_n,
   output wire z
);
//用verilog设计一个 101101 序列的检测器
reg [4:0] cs,ns;
localparam [4:0]	IDLE	=5'd0,
						  A 	=5'd1,
						  B 	=5'd2,
						  C 	=5'd3,
						  D 	=5'd4,
						  E 	=5'd5,
						  F   =5'd6;
//状态转移
always @ (posedge clk,negedge rst_n)
	if(!rst_n)
		cs	<= IDLE;
	else
		cs <= ns;
//组合逻辑,产生下一状态译码逻辑,判断条件为cs当前状态
always @ (*)
begin
	ns = 5'bx;
	case(cs)
		IDLE:
			begin
				if(x==1)
					ns = A;
				else
					ns = IDLE;
			end
		A:
			begin
				if(x==0)
					ns = B;
				else
					ns = A;
			end
		B:
			begin
				if(x==1)
					ns = C;
				else
					ns = IDLE;
			end
		C:
			begin
				if(x==1)
					ns = D;
				else
					ns = B;
			end
		D:
			begin
				if(x==0)
					ns = E;
				else
					ns = A;
			end
		E:
			begin
				if(x==1)
					ns = F;
				else
					ns = IDLE;
			end
		F:
			begin
				if(x==1)
					ns = D;
				else
					ns = B;
			end
		default:
			ns = IDLE;
	endcase
end
//第三段always--状态寄存输出,判断条件是ns即下一个状态
/*
always @ (posedge clk,negedge rst_n)
begin
	if(!rst_n)
		z <= 1'b0;
	else
		begin
		case(ns)
			IDLE,A,B,C,D,E :	z <= 1'b0;
			F				   :	z <= 1'b1;
			default:	z <= 1'b0;
		endcase
		end
end
*/
assign z = (ns==F);

endmodule  
 

posted on 2011-09-12 12:18  齐威王  阅读(3118)  评论(3编辑  收藏  举报

导航