【FPGA】Verilog状态机设计

状态机是fpga设计中极其重要的一种技巧,掌握状态机的写法可以使fpga的开发事半功倍。

下面记录一下状态机的基本知识理论。


【FPGA】Verilog状态机设计_第1张图片


【FPGA】Verilog状态机设计_第2张图片


实例:

【FPGA】Verilog状态机设计_第3张图片



三种状态机实现代码:

// 一段式状态机

module style1_fsm(i_clk, rst_n, i1, i2, o1, o2, err);

input i_clk, rst_n, i1, i2;
output o1, o2, err;

parameter [3:0] IDLE = 4'b0001,
		S1   = 4'b0010,
		S2   = 4'b0100,
		ERROR= 4'b1000;

reg o1, o2, err;
reg [3:0] state;

always @(posedge i_clk or negedge rst_n) 
begin
	if(!rst_n) begin
		state <= IDLE;
		{o1, o2, err} <= 3'b000;
	end
	else
		case(state)
		IDLE:	begin
				if(!i1) begin
					{o1, o2, err} <= 3'b000;
					state <= IDLE;
				end
				if(i1 & i2) begin					
					{o1, o2, err} <= 3'b100;
					state <= S1;
				end
				if(i1 & !i2) begin					
					{o1, o2, err} <= 3'b111;
					state <= ERROR;
				end
			end
		S1:	begin
				if(!i2) begin					
					{o1, o2, err} <= 3'b100;
					state <= S1;
				end
				if(i1 & i2) begin					
					{o1, o2, err} <= 3'b010;
					state <= S2;
				end
				if(!i1 & i2) begin					
					{o1, o2, err} <= 3'b111;
					state <= ERROR;
				end
			end
		S2:	begin
				if(i2) begin					
					{o1, o2, err} <= 3'b010;
					state <= S2;
				end
				if(i1 & !i2) begin					
					{o1, o2, err} <= 3'b000;
					state <= IDLE;
				end
				if(!i1 & !i2) begin					
					{o1, o2, err} <= 3'b111;
					state <= ERROR;
				end
			end
		ERROR:	begin
				if(i1) begin					
					{o1, o2, err} <= 3'b111;
					state <= ERROR;
				end
				if(!i1) begin					
					{o1, o2, err} <= 3'b000;
					state <= IDLE;
				end
			end
		default:begin				
				{o1, o2, err} <= 3'b000;
				state <= IDLE;
			end
		endcase

end


endmodule

// 两段式状态机

module style2_fsm(i_clk, rst_n, i1, i2, o1, o2, err);

input i_clk, rst_n, i1, i2;
output o1, o2, err;

parameter [3:0] IDLE = 4'b0001,
		S1   = 4'b0010,
		S2   = 4'b0100,
		ERROR= 4'b1000;

reg o1, o2, err;
reg [3:0] curr_state, next_state;

always @(posedge i_clk or negedge rst_n) begin
	if(!rst_n)
		curr_state <= IDLE;
	else
		curr_state <= next_state;
end

always @(curr_state or i1 or i2) begin
	case(curr_state)
	IDLE:	begin
			if(!i1) begin
				IDLE_OUT;
				next_state = IDLE;
			end
			if(i1 & i2) begin
				S1_OUT;
				next_state = S1;
			end
			if(i1 & !i2) begin
				ERROR_OUT;
				next_state = ERROR;
			end
		end
	S1:	begin
			if(!i2) begin
				S1_OUT;
				next_state = S1;
			end
			if(!i1 & i2) begin
				ERROR_OUT;
				next_state = ERROR;
			end
			if(i1 & i2) begin
				S2_OUT;
				next_state = S2;
			end
		end
	S2:	begin
			if(i2) begin
				S2_OUT;
				next_state = S2;
			end
			if(i1 & !i2) begin
				IDLE_OUT;
				next_state = IDLE;
			end
			if(!i1 & !i2) begin
				ERROR_OUT;
				next_state = ERROR;
			end
		end
	ERROR:	begin
			if(i1) begin
				ERROR_OUT;
				next_state = ERROR;
			end
			if(!i1) begin
				IDLE_OUT;
				next_state = IDLE;
			end
		end
	default:begin
			IDLE_OUT;
			next_state <= IDLE;
		end
	endcase
end

task IDLE_OUT;
	{o1, o2, err} = 3'b000;
endtask

task S1_OUT;
	{o1, o2, err} = 3'b100;
endtask

task S2_OUT;
	{o1, o2, err} = 3'b010;
endtask

task ERROR_OUT;
	{o1, o2, err} = 3'b111;
endtask

endmodule

// 三段式状态机

module style3_fsm(i_clk, rst_n, i1, i2, o1, o2, err);

input i_clk, rst_n, i1, i2;
output o1, o2, err;

parameter [3:0] IDLE = 4'b0001,
		S1   = 4'b0010,
		S2   = 4'b0100,
		ERROR= 4'b1000;

reg o1, o2, err;
reg [3:0] curr_state, next_state;

always @(posedge i_clk or negedge rst_n) 
begin
	if(!rst_n)
		curr_state <= IDLE;
	else
		curr_state <= next_state;
end

always @(curr_state or i1 or i2) 
begin	
	case(curr_state)
	IDLE:	begin
			if(!i1)		next_state = IDLE;
			if(i1 & i2)	next_state = S1;
			if(i1 & !i2)	next_state = ERROR;
		end
	S1:	begin
			if(!i2)		next_state = S1;
			if(i1 & i2)	next_state = S2;
			if(!i1 & i2)	next_state = ERROR;
		end
	S2:	begin
			if(i2)		next_state = S2;
			if(i1 & !i2)	next_state = IDLE;
			if(!i1 & !i2)	next_state = ERROR;
		end
	ERROR:	begin
			if(i1)		next_state = ERROR;
			if(!i1)		next_state = IDLE;
		end
	default:begin
			next_state = IDLE;	// 不加这个default项 输出会一直是000!!!
		end
	endcase
end

always @(posedge i_clk or negedge rst_n) 
begin
	if(!rst_n)
		{o1, o2, err} <= 3'b000;
	else begin
		case(next_state)
		IDLE:	{o1, o2, err} <= 3'b000;
		S1:	{o1, o2, err} <= 3'b100;
		S2:	{o1, o2, err} <= 3'b010;
		ERROR:	{o1, o2, err} <= 3'b111;
		default:{o1, o2, err} <= 3'b000;//不加这个default 复位前信号都为不定值X
		endcase
	end
end



endmodule


你可能感兴趣的:(【,FPGA,】)