状态机编写实例(三段式以及index one-hot+reverse case + synopsys FSM写法)

应用场景:编写一个自动售货机,功能如下:

共有三种纸币入口,分别支持10元,20元,50元。货物售价为80元。需要支持找钱功能。


分析:状态转换图如下所示,使用三段式状态机将如下状态图描述出来 

状态机编写实例(三段式以及index one-hot+reverse case + synopsys FSM写法)_第1张图片 标题

代码如下:


//三段式moore状态机(输出只与当前状态有关)

module aotu_vending(
				input 		clk,
				input		rst_n,
				input		Ten,
				input		Twnty,
				input		Fifty,
				output		Ok,
				output 		Ten_back,
				output		Twnty_back,
				output		Thirty_back,
				output		Fourty_back
	);
	//用格雷编码表示转态
	localparam	IDLE  = 4'b0000,
				S_10  = 4'b0001,
				S_20  = 4'b0011,
				S_30  = 4'b0010,
				S_40  = 4'b0110,
				S_50  = 4'b0111,
				S_60  = 4'b0101,
				S_70  = 4'b0100,
				S_80  = 4'b1100,
				S_90  = 4'b1101,
				S_100 = 4'b1111,
				S_110 = 4'b1110,
				S_120 = 4'b1010;
	
	reg	[3:0] current_state,next_state;
	always@(posedge clk,negedge rst_n)begin
		if(!rst_n)
			current_state <= IDLE;
		else
			current_state <= next_state;
	end
	always@(*)begin
		case(current_state)
			IDLE :begin
				if(Ten) 		next_state<=S_10;
				else if(Twnty)	next_state<=S_20;
				else if(Fifty)	next_state<=S_50;
				else			next_state<=IDLE;
			end
			S_10 :begin
				if(Ten)			next_state<=S_20;
				else if(Twnty)  next_state<=S_30;
				else if(Fifty)  next_state<=S_60;
				else            next_state<=S_10;
			end
			S_20 :begin
				if(Ten)			next_state<=S_30;
				else if(Twnty)  next_state<=S_40;
				else if(Fifty)  next_state<=S_70;
				else            next_state<=S_20;
			end
			S_30 :begin
				if(Ten)			next_state<=S_40;
				else if(Twnty)  next_state<=S_50;
				else if(Fifty)  next_state<=S_80;
				else            next_state<=S_30;
			end
			S_40 :begin
				if(Ten)			next_state<=S_50;
				else if(Twnty)  next_state<=S_60;
				else if(Fifty)  next_state<=S_90;
				else            next_state<=S_40;
			end
			S_50 :begin
				if(Ten)			next_state<=S_60;
				else if(Twnty)  next_state<=S_70;
				else if(Fifty)  next_state<=S_100;
				else            next_state<=S_50;
			end
			S_60 :begin
				if(Ten)			next_state<=S_70;
				else if(Twnty)  next_state<=S_80;
				else if(Fifty)  next_state<=S_110;
				else            next_state<=S_60;
			end
			S_70 :begin
				if(Ten)			next_state<=S_80;
				else if(Twnty)  next_state<=S_90;
				else if(Fifty)  next_state<=S_120;
				else            next_state<=S_70;
			end
			S_80 :				next_state<=IDLE;
			S_90 :				next_state<=IDLE;
			S_100:				next_state<=IDLE;
			S_110:				next_state<=IDLE;
			S_120:				next_state<=IDLE;
			default:			next_state<=IDLE;
		endcase
	end
	
	assign Ok          = (current_state[3]==1'b1)?1'b1:1'b0;
	assign Ten_back    = (current_state==S_90)   ?1'b1:1'b0;
	assign Twnty_back  = (current_state==S_100)  ?1'b1:1'b0;
	assign Thirty_back = (current_state==S_110)  ?1'b1:1'b0;
	assign Fourty_back = (current_state==S_120)  ?1'b1:1'b0;
	
endmodule

产生随机测试向量,测试电路

`timescale 1ns/1ns
//============================================================
module aotu_vending_tb;

	parameter cycle_time=10;
	integer i;
	reg clk,rst_n,Ten,Twnty,Fifty;
	wire Ok,Ten_back,Twnty_back,Thirty_back,Fourty_back;
	
	reg [2:0]random_in;
	reg [3:0]in_time;
	
	always #(cycle_time/2) clk=~clk;
	initial begin
		clk=0;
		rst_n=0;
		random_in=3'b001;
		#(2*cycle_time);
		rst_n=1;
	end
	initial begin
		Ten=0;
		Twnty=0;
		Fifty=0;
		#(4*cycle_time);
		repeat(30)begin
			in_time = 2+{$random}%3;			   //产生2到4的随机整数min+{$random}%(max-min+1)
			for(i=0;i

状态机编写实例(三段式以及index one-hot+reverse case + synopsys FSM写法)_第2张图片

//(使用 index one-hot + reverse case + synopsys FSM 语法)

module aotu_vending1(
				input 			clk,
				input			rst_n,
				input			Ten,
				input			Twnty,
				input			Fifty,
				output		reg Ok,
				output 		reg Ten_back,
				output		reg Twnty_back,
				output		reg Thirty_back,
				output		reg Fourty_back
	);
	localparam	[3:0]	// synopsys enum code
						IDLE  = 4'd0,
						S_10  = 4'd1,
						S_20  = 4'd2,
						S_30  = 4'd3,
						S_40  = 4'd4,
						S_50  = 4'd5,
						S_60  = 4'd6,
						S_70  = 4'd7,
						S_80  = 4'd8,
						S_90  = 4'd9,
						S_100 = 4'd10,
						S_110 = 4'd11,
						S_120 = 4'd12,
						ERROR = 4'd13;
	// synopsys state_vector state					
	reg	[13:0]  // synopsys enum code
				current_state,next_state;
	always@(posedge clk,negedge rst_n)begin
		if(!rst_n)
			current_state		<= 14'd0;
			current_state[IDLE] <= 1'b1;
		else
			current_state <= next_state;
	end
	always@(*)begin
		next_state = 14'd0;
		case(1'b1) // synopsys full_case parallel_case
			current_state[IDLE] :begin
				if(Ten) 		next_state[S_10]<=1'b1;
				else if(Twnty)	next_state[S_20]<=1'b1;
				else if(Fifty)	next_state[S_50]<=1'b1;
				else			next_state[IDLE]<=1'b1;
			end
			current_state[S_10] :begin
				if(Ten)			next_state[S_20]<=1'b1;
				else if(Twnty)  next_state[S_30]<=1'b1;
				else if(Fifty)  next_state[S_60]<=1'b1;
				else            next_state[S_10]<=1'b1;
			end
			current_state[S_20] :begin
				if(Ten)			next_state[S_30]<=1'b1;
				else if(Twnty)  next_state[S_40]<=1'b1;
				else if(Fifty)  next_state[S_70]<=1'b1;
				else            next_state[S_20]<=1'b1;
			end
			current_state[S_30] :begin
				if(Ten)			next_state[S_40]<=1'b1;
				else if(Twnty)  next_state[S_50]<=1'b1;
				else if(Fifty)  next_state[S_80]<=1'b1;
				else            next_state[S_30]<=1'b1;
			end
			current_state[S_40] :begin
				if(Ten)			next_state[S_50]<=1'b1;
				else if(Twnty)  next_state[S_60]<=1'b1;
				else if(Fifty)  next_state[S_90]<=1'b1;
				else            next_state[S_40]<=1'b1;
			end
			current_state[S_50] :begin
				if(Ten)			next_state[S_60]<=1'b1;
				else if(Twnty)  next_state[S_70]<=1'b1;
				else if(Fifty)  next_state[S_100]<=1'b1;
				else            next_state[S_50]<=1'b1;
			end
			current_state[S_60] :begin
				if(Ten)			next_state[S_70]<=1'b1;
				else if(Twnty)  next_state[S_80]<=1'b1;
				else if(Fifty)  next_state[S_110]<=1'b1;
				else            next_state[S_60]<=1'b1;
			end
			current_state[S_70] :begin
				if(Ten)			next_state[S_80]<=1'b1;
				else if(Twnty)  next_state[S_90]<=1'b1;
				else if(Fifty)  next_state[S_120]<=1'b1;
				else            next_state[S_70]<=1'b1;
			end
			current_state[S_80] :	next_state[IDLE]<=1'b1;
			current_state[S_90] :	next_state[IDLE]<=1'b1;
			current_state[S_100]:	next_state[IDLE]<=1'b1;
			current_state[S_110]:	next_state[IDLE]<=1'b1;
			current_state[S_120]:	next_state[IDLE]<=1'b1;
			current_state[ERROR]:   next_state[IDLE]<=1'b1;
		endcase
	end
	always@(posedge clk,negedge rst_n)begin
		if(!rst_n)begin
			Ok<=1'b0;
			Ten_back<=1'b0;
			Twnty_back<=1'b0;
			Thirty_back<=1'b0;
			Fourty_back<=1'b0;
		end
		else begin
			case(1'b1)
				next_state[S_80]: begin OK<=1'b1;end
				next_state[S_90]: begin OK<=1'b1;Ten_back<=1'b1;end
				next_state[S_100]:begin OK<=1'b1;Twnty_back<=1'b1;end
				next_state[S_110]:begin OK<=1'b1;Thirty_back<=1'b1;end
				next_state[S_120]:begin OK<=1'b1;Fourty_back<=1'b1;end
				default:begin
					Ok<=1'b0;
					Ten_back<=1'b0;
					Twnty_back<=1'b0;
					Thirty_back<=1'b0;
					Fourty_back<=1'b0;
				end
			endcase
		end
	end
	
endmodule

 

你可能感兴趣的:(verilog,HDL高级数字设计)