关于一阶状态机跳转问题的研究与心得
2012-02-20 12:25
155 查看
转自:/article/5145125.html
简单来说,HDL的精髓就是if、case、FSM(有限状态机),而if、case通常又是伴随在状态机之中的。所以,状态机的重要性是毋庸置疑的。通常,在一个always或者process中,用到的都是一阶的状态机比较多,二阶以上的较复杂,代码可读性不高,所以不用常见,也极少用到。
状态机的核心在于状态的跳转,也是很多初学者头疼的地方,尤其是当一个状态机里的状态数超过10个的时候,考虑不周,很容易混乱。本文中,笔者将用一种新方式来控制状态机的跳转,不同于Xilinx或Altera的参考CodingStyle。虽然不一定是最好的,但是仍有一定的借鉴价值,供读者参考交流。
通常,我们是这样定义状态机的:
这样定义状态机,就需要我们对每个状态机的功能、跳转条件非常清楚,当然,这也是必须的。
而有的时候,初学者,是一边写代码一边思考的,到底要定义多少状态数、每个状态的跳转条件,不一定都是非常清楚的。所以,如果这时候还用上述的方式定义状态机,就可能需要一边写一边修改状态机的定义。状态多到一定程度的时候,自己可能就乱了,糊涂了。那么,有没有一种更好的方法来定义状态机,省去这样的麻烦呢?答案:有!肯定有!必须有!
笔者的思路是这样的:将状态机的状态转理解成CPU中的中断向量地址,然后将状态大概分成几类,每类状态提供一个入口地址。这样,我们仅需要清楚这几类状态的入口状态跳转条件即可,状态数的增加并不会增加状态机的复杂度。
状态机的定义:
假设状态机分成这样几类:初始化(st_init)、取数据(st_read_data)、数学处理(st_math)、写数据(st_write_data),每个类状态都不止一个,所以给第类状态预留了10个状态数的间隔。当然,这只是例子。
这样,在写状态机代码的时候,可以这样写:
状态机在同一类状态下,只需要自加1就可以了,而在同类最后一个状态才要进行状态的跳转判断,这样状态的跳转就变得容易控制了。
虽然可能看上去与一般的状态机写法和跳转法则没太大的区别,但这确实是笔者在实际应用中写代码的时候思考和探索过的问题,也确实在一定程度上减轻了状态数很多的情况下跳转问题的复杂度。
简单来说,HDL的精髓就是if、case、FSM(有限状态机),而if、case通常又是伴随在状态机之中的。所以,状态机的重要性是毋庸置疑的。通常,在一个always或者process中,用到的都是一阶的状态机比较多,二阶以上的较复杂,代码可读性不高,所以不用常见,也极少用到。
状态机的核心在于状态的跳转,也是很多初学者头疼的地方,尤其是当一个状态机里的状态数超过10个的时候,考虑不周,很容易混乱。本文中,笔者将用一种新方式来控制状态机的跳转,不同于Xilinx或Altera的参考CodingStyle。虽然不一定是最好的,但是仍有一定的借鉴价值,供读者参考交流。
通常,我们是这样定义状态机的:
verilog: parameterst1=8'b00000001; parameterst2=8'b00000010; parameterst3=8'b00000100; parameterst4=8'b00001000; parameterst5=8'b00010000; parameterst6=8'b00100000; parameterst7=8'b01000000; parameterst8=8'b10000000; reg[7:0]state=st1;
VHDL:
typestate_valueis(st1,st2,st3,...);
signalstate:state_value:=st1;
这样定义状态机,就需要我们对每个状态机的功能、跳转条件非常清楚,当然,这也是必须的。
而有的时候,初学者,是一边写代码一边思考的,到底要定义多少状态数、每个状态的跳转条件,不一定都是非常清楚的。所以,如果这时候还用上述的方式定义状态机,就可能需要一边写一边修改状态机的定义。状态多到一定程度的时候,自己可能就乱了,糊涂了。那么,有没有一种更好的方法来定义状态机,省去这样的麻烦呢?答案:有!肯定有!必须有!
笔者的思路是这样的:将状态机的状态转理解成CPU中的中断向量地址,然后将状态大概分成几类,每类状态提供一个入口地址。这样,我们仅需要清楚这几类状态的入口状态跳转条件即可,状态数的增加并不会增加状态机的复杂度。
状态机的定义:
verilog:
parameterst_init=8'd0;
parameterst_read_data=8'd10;
parameterst_math=8'd20;
parameterst_write_data=8'd30;
reg[7:0]state=st_init;
VHDL:
constantst_init:integer:=0;
constantst_read_data:integer:=10;
constantst_math:integer:=20;
constantst_write_data:integer:=30;
signalstate:integerrange0to255:=0;
假设状态机分成这样几类:初始化(st_init)、取数据(st_read_data)、数学处理(st_math)、写数据(st_write_data),每个类状态都不止一个,所以给第类状态预留了10个状态数的间隔。当然,这只是例子。
这样,在写状态机代码的时候,可以这样写:
verilog:
case(state)
st_init:
st_init+1:
st_init+2:
st_math:
st_math+1:
st_math+2:
st_read_data:
st_read_data+1:
st_read_data+2:
st_write_data:
st_write_data+1:
st_write_data+2:
default:
endcase
VHDL:
casestateis
whenst_init=>
whenst_init+1=>
whenst_init+2=>
whenst_read_data=>
whenst_read_data+1=>
whenst_read_data+2=>
whenst_math=>
whenst_math+1=>
whenst_math+2=>
whenst_write_data=>
whenst_write_data+1=>
whenst_write_data+2=>
whenothers=>
endcase;
状态机在同一类状态下,只需要自加1就可以了,而在同类最后一个状态才要进行状态的跳转判断,这样状态的跳转就变得容易控制了。
虽然可能看上去与一般的状态机写法和跳转法则没太大的区别,但这确实是笔者在实际应用中写代码的时候思考和探索过的问题,也确实在一定程度上减轻了状态数很多的情况下跳转问题的复杂度。
相关文章推荐
- [Craftor原创]关于一阶状态机跳转问题的研究与心得
- [转载].Craftor - 关于一阶状态机跳转问题的研究与心得
- 关于研究Webservice问题总结与心得体会
- 关于页面中锚跳转问题
- 心得体会:关于开发效率和项目周期的问题
- nginx中关于创建work进程数目问题的心得
- 关于 qma0.bemd.gdn/?s1=glob 连接跳转问题
- 关于plsql导入pde因为字符集设置问题报错,而研究oracle服务器字符集、客户端字符集过程中发现的问题看,以及亲测的解决办法
- 关于web.xml中配置404错误跳转页面 在ie不能显示自定义错误页面的问题
- 关于开放性跳转的一个安全小问题
- 关于两个Activity实现页面跳转问题
- 关于App内跳转到设置界面的问题
- 关于ajax跳转的问题
- 关于J2EE中死锁问题的研究
- Python字符串的encode与decode研究心得乱码问题解决方法
- 个人关于Cemail.vol 文件的研究心得
- Python字符串的encode与decode研究心得——解决乱码问题
- 关于structs和Spring框架整合中的模块装配问题心得
- 建立第一个struts项目,RequestProcessor类,PlugIn,error(关于跳转等问题)
- 关于百度推送点击通知,跳转的问题(Android)