两段式状态机书写注意事项

文章讲述了在调试飞腾平台上的电源时序管理模块时遇到的问题,原始状态机代码存在组合逻辑错误,包括非阻塞赋值、混合控制信号以及不完整的if-else结构导致的时序问题。作者指出应当使用阻塞赋值,保持状态机段纯净,避免产生latch。通过修正这些问题,成功调试通了状态机。
摘要由CSDN通过智能技术生成
	如下代码是作者在调试飞腾上电时序管理模块时,书写的状态机,经过多次调试各种各样的问题,无法调通。加上国产高云FPGA综合软件算法功能贼差,导致调试进程异常缓慢。在修改如下代码后,很快调通了,可谓一窍不得,少挣几百。
	以下错误代码,描述以下错误点。
三段式状态机,第一段描述状态的转移。
always @(posedge clk or posedge rst) begin
	if(rst==1'b1)begin
		current_state<=PWR_ON;
	end
	else begin
		current_state<=next_state;
	end
end
第二段使用组合逻辑描述状态的转移过程。笔者在第二段状态机犯了多个错误。铭记警醒,以供后期注意。
1.组合逻辑内多信号的赋值使用非阻塞赋值<=,错误。应该使用阻塞赋值=2.第二段组合逻辑掺杂进来一些其他控制信号,调试过程中问题百出,正确的方法应该是本段只描述状态的转移,其他信号在外部使用always赋值操作。
3.组合逻辑里绝对不能出现不全的if else结构,否则软件会报警告,无法分析主时钟与某一奇怪网表信号的时钟关系,原因是不全的if else架构导致latch产生,所以时序无法分析。PWR_ON状态里出现next_state<=PWR_ON,这种赋值不是latch,因为给next_state了一个确定的值。而组合逻辑if else不全将导致latch生成。

always @(*) begin
	case (current_state)
		PWR_ON:begin
			if (power_on_end==1'b1)begin
				next_state=JUDE;
				reboot_pwr_on_flag=1'b0;
			end
			else begin
				next_state=PWR_ON;
				reboot_pwr_on_flag=1'b1;
			end
			re_pwr_on_dly_en=1'b0;
		end
		JUDE:begin
			re_pwr_on_dly_en=1'b0;
			if (reboot_flag==1'b1)begin
				next_state=SHUT_DOWN;
				reboot_pwr_on_flag=1'b1;
			end
			else if (shut_down_flag==1'b1)begin
				next_state=SHUT_DOWN;
				reboot_pwr_on_flag=1'b0;
			end
			else begin
				next_state=JUDE;
				reboot_pwr_on_flag=1'b0;
			end
		end
		SHUT_DOWN:begin
			re_pwr_on_dly_en=1'b0;

			if(shut_down_end==1'b1)begin
				if(reboot_pwr_on_flag==1'b1)begin
					next_state=RE_PWR_ON1;
				end
				else begin
					next_state=JUDE;
				end
			end
			else begin
				next_state=SHUT_DOWN;
			end
		end
		RE_PWR_ON1:begin
			next_state=RE_PWR_ON2;
			re_pwr_on_dly_en=1'b1;
			reboot_pwr_on_flag=1'b1;
		end
		RE_PWR_ON2:begin
			re_pwr_on_dly_en=1'b0;
			reboot_pwr_on_flag=1'b1;
			if (re_pwr_on_dly_end_500ms==1'b1)begin
				next_state=PWR_ON;
			end
			else begin
				next_state=RE_PWR_ON2;
			end
		end
		default:begin
			next_state=JUDE;
			re_pwr_on_dly_en=1'b0;
			reboot_pwr_on_flag=1'b0;
		end
	endcase
end
修改后的代码结构如下:在第二段状态机内只描述状态的转移过程,没有描述具体信号的情况,输出信号放在了第三段。
always @(posedge clk or posedge rst) begin
	if(rst==1'b1)begin
		current_state<=PWR_ON;
	end
	else begin
		current_state<=next_state;
	end
end

always @(*) begin
	case (current_state)
		PWR_ON:begin
			if (power_on_end==1'b1)begin
				next_state=JUDE;
			end
			else begin
				next_state=PWR_ON;
			end
		end
		JUDE:begin
			if(pwr_on_flag==1'b1)begin
				next_state=PWR_ON;
			end
			else if (reboot_flag==1'b1)begin
				next_state=SHUT_DOWN;
			end
			else if (shut_down_flag==1'b1)begin
				next_state=SHUT_DOWN;
			end
			else begin
				next_state=JUDE;
			end
		end

		SHUT_DOWN:begin
			if(shut_down_end==1'b1)begin
				next_state=JUDE;
			end
			else begin
				next_state=SHUT_DOWN;
			end
		end
		default:begin
			next_state=JUDE;
		end
	endcase
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值