事故现场先贴一下代码的简版:
localparam s_idle = 4'd0;localparam s_head = 4'd1;localparam s_payload = 4'd2;localparam s_tail = 4'd3;localparam s_error = 4'd4;reg [3:0]status, nx_status;always @(posedge clk_100m or negedge rst_spt_n)begin if(!rst_spt_n) status <= s_idle; else status <= nx_status;endalways @* begin case(status) s_idle: ... s_head: ... s_payload: ... s_tail: ... s_error: ... default: nx_status = status; endcaseend状态机本身很简单,default也写了,然后进行仿真时看到了这样的波形:
nx_status仿真初始的值为4'hb,而后导致status的值也为4'hb,始终无法回到idle状态,整个电路的功能也无法正常开展。
事故分析这个问题得以暴露要感谢在验证环境中打开了initreg功能:
cmp_options += +vcs+initreg+randomrun_options += +vcs+initreg+$(seed)通过这样的配置使得reg型的数值在仿真开始时被赋值为随机数。该bug就是由于nx_status被赋值为状态之外的随机数而发现的。
在代码中,nx_status没有任何位置被进行“复位”,当然了因为nx_status本身不是寄存器也就不存在复位的问题,不过状态机的alway@*中的处理是有问题的,这导致nx_status一旦跑“飞”了,status下一拍会更新为nx_status的值,那么整个状态机将不可恢复。
事故解决修改状态机的写法为:
always @* begin case(status) s_idle: ... s_head: ... s_payload: ... s_tail: ... s_error: ... default: nx_status = s_idle; endcaseend或者
always @* begin nx_status = s_idle; case(status) s_idle: ... s_head: ... s_payload: ... s_tail: ... s_error: ... default: nx_status = status; endcaseend重新仿真后波形正确:
电源管理IC即将爆发,解析未来四大市场趋势
Google将推新的Contributor,用户按月付费可免看广告
电动汽车与传统汽车的区别
树脂颗粒机器人破包机 全自动破袋机工作优势
Microchip推出经TüV SüD认证的MPLAB工具
状态机怎么上来就错了?怎么解决?
小米5c摄影,拍甜美的妹子
基于ADI ADG5421F双路单刀单掷(SPST)低阻开关设计方案介绍
科普一下12种管道过滤器
三元锂电池与磷酸铁锂电池相比哪个成本更低
5G能否让运营商实现收入正向增长顺利越过寒冬
如何选购手写板
抽油烟机的清洗方法
机房蓄电池组在线监测系统
传统电池检测电路
工业互联网环境下的大数据技术应用
苹果发明了一个新专利 只为干掉你的Home键!
PCB设计期间的热优化你了解吗
碳化硅肖特基二极管的原理及应用
磷酸铁锂电池的危害