在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 9919|回复: 17

[求助] 一个不小心导致的隐秘的组合逻辑环

[复制链接]
发表于 2015-10-28 17:42:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
最近在写代码的时候发现一个很隐秘的组合逻辑环,一个不小心就会出现,应该是自己代码习惯的问题。代码见下方。刚好如下的两个模块fsm和fack形成了一个组合逻辑环“ack_i -> nstate -> req_o -> ack_i",用modelsim仿真一下代码会直接报错,用quartusII编译综合可以通过,但是会有警告表明产生了组合逻辑环。
仔细分析,产生这种情况的原因是,两个模块中都存在”input -> output 的组合逻辑“,如果这两个电路刚好匹配,就会形成组合逻辑环。但是如果是两个规模较大的模块,发现这种比较隐蔽的组合逻辑环感觉应该不是那么简单。


问题来了:是不是说每个模块里面最好将输入和输出用至少一级寄存器隔开比较安全?因为你不仔细分析不会知道其他人的代码是怎么写的,如果一旦产生了组合逻辑环,再次修改代码可能会导致比较复杂的改动(当然这里举例比较简单)。所以考虑安全性,最好采用这种方式。


请问,我的分析是不是正确的?上面讲的代码方式”每个模块里面最好将输入和输出用至少一级寄存器隔开比较安全“是不是应该采取?还是说”出现问题后再修改设计切断组合逻辑环“?谢谢!

代码如下:"fsm.v":




  1. `timescale 1ns/1ns

  2. module fsm(
  3.          input         clk
  4.         ,input         rst_n
  5.         ,output req_o
  6.         ,input         ack_i
  7.         ,output led_o
  8. );
  9.        
  10.         localparam         F_IDLE         = 2'd0,
  11.                                                         F_S0                =        2'd1,
  12.                                                         F_S1                =        2'd2;
  13.        
  14.         reg        [1:0] cstate;
  15.         reg        [1:0]        nstate;
  16.        
  17.         always @(posedge clk,negedge rst_n) begin
  18.                 if(!rst_n)
  19.                         cstate <= F_IDLE;
  20.                 else
  21.                         cstate <= nstate;
  22.         end
  23.        
  24.         always @( * ) begin
  25.                 case(cstate)
  26.                         F_IDLE:
  27.                                 nstate = F_S0;
  28.                                
  29.                         F_S0:
  30.                                 if(ack_i)
  31.                                         nstate = F_S1;
  32.                                 else
  33.                                         nstate = F_S0;
  34.                        
  35.                         F_S1:
  36.                                 nstate = F_IDLE;
  37.                        
  38.                         default:
  39.                                 nstate = F_IDLE;
  40.                        
  41.                 endcase
  42.         end
  43.        
  44.         //assign req_o = (cstate == F_S0);  //ok;
  45.         assign req_o = (cstate == F_S0) && (nstate == F_S0);  //error;
  46.        
  47.        
  48.         assign led_o = (cstate == F_S1);
  49.        
  50.        
  51. endmodule



复制代码




"fack.v":




  1. `timescale 1ns/1ns

  2. module fack(
  3.          input         req_i
  4.         ,output ack_o
  5. );

  6.         assign ack_o = req_i;
  7.        
  8. endmodule



复制代码



"top.v":




  1. `timescale 1ns/1ns

  2. module top(
  3.          input         clk
  4.         ,input         rst_n
  5.         ,output led_o
  6. );

  7.         fsm                                fsm(
  8.                  .clk                        (clk        )
  9.                 ,.rst_n                (rst_n)
  10.                 ,.req_o                (req        )
  11.                 ,.ack_i                (ack        )
  12.                 ,.led_o                (led_o)
  13.         );
  14.        
  15.         fack                        fack(
  16.                  .req_i                (req        )
  17.                 ,.ack_o                (ack        )
  18.         );
  19.        

  20. endmodule



复制代码
 楼主| 发表于 2015-10-28 19:00:32 | 显示全部楼层
怎么没人遇到么,,,,,
发表于 2015-10-28 22:55:14 | 显示全部楼层
回复 2# YoungZ1


    根据需要来插入适当的寄存器,关键还是设计的时候要把电路结构考虑清楚。
 楼主| 发表于 2015-10-29 08:18:12 | 显示全部楼层
回复 3# liuguangxi


   嗯,谢谢了,设计时考虑好电路结构才是最重要的。
发表于 2015-11-6 23:14:23 | 显示全部楼层
模块划分和模块间接口定义,需要在写代码前完成的。一般在输入和输出各加打一拍,对时序收敛是有帮助的,因为有可能在另外的逻辑里,输出前已经做了很长的组合逻辑,你的逻辑你又有一些组合逻辑,可能会影响时序。当然,能不能加打拍,也要看设计,有些情况,两个模块间的交互要当前或下一周期完成。  总的来说,多个模块间的交互一定要先沟通设计好后,再写代码实现
发表于 2015-11-11 12:31:32 | 显示全部楼层
好像一般规范要求是尽量做到每个模块组合逻辑入,时序逻辑出,目的是为了减小组合逻辑路径长度,也可以避免组合逻辑环路。

这种组合逻辑环路,一般的check工具都会报warning的,很容易检查出来
发表于 2015-11-11 15:09:15 | 显示全部楼层
我公司的代码要求要求赋值规定如下:
always中只允许使用非堵塞性赋值<=,assign只有一种赋值符号=。
所以不允许在always里的使用组合逻辑。所有我也很少仿真像你发的那种例子。
你的状态机避免使用组合逻辑而使用时序逻辑,不能实现你的要求吗?我感觉这样好理解些
发表于 2015-11-11 15:49:17 | 显示全部楼层
这个逻辑环的产生并不是你的代码风格引发的,而是你对你需要的功能并不清晰。
从你的代码来看fsm中的req_o就是ack_i同一条线,岂能ack_i作为因,req_o作为果呢。即便按照你正确的代码来运行,也不会有任何的波形出现的。
就好像你使用一根水管一头放在水桶里,然后你拿着另一头在外面绕了一下又放回了水桶里,会有水流出现吗?
理清楚你需要的时序关系再想如何写代码。
发表于 2015-11-13 09:51:21 | 显示全部楼层
Combinational loop can be easily found by lint tool such as lec, spyglass, etc.
发表于 2015-11-13 11:02:32 | 显示全部楼层
回复 9# yaya126


    nLint更好用
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-28 03:36 , Processed in 0.030592 second(s), 10 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表