1.task较多的用于搭建test bench和执行其他非综合的任务,比如当你验证一个I2C的slave是否正确时,一般的你需要写一个I2C master的behavior model作为激励模块来帮助测试,而这个master模块向I2C总线产生激励的行为可以写成task,以便于代码的复用其他非综合的任务,比如测试环境中进行数据的比对和错误信息的display等,也都可以用task完成。
2.代码中不同位置调用的function会被综合成不同的组合逻辑(前提是你的function是可综合的),同一个always块中调用的function可能会被DC优化掉合并起来,除非设置dont_touch。
你之前说 函数可以代替子模块例化,我觉得不是的。
例化的使用是确定系统的层次和结构,硬件并不是和软件一样,只有逻辑关系,用一个函数实现一个子模块的功能,看起来在逻辑上清晰,但是在物理逻辑关系上可能会产生问题。
硬件设计除了考虑逻辑,还要考虑很多物理设计的约束和要求,不同的模块内虽然例化了相同的子模块,却可能因为不同的约束条件在综合后的设计中产生不同的结果。
我没有对不同模块在不同约束下对同一函数调用所产生的物理逻辑的差异进行过研究,但是从电路设计来说,使用函数最大的弊端就是结构的不清晰,并且在设计电路时,需要在模块内进行很多的优化,这些优化除了逻辑还有物理上的,这时函数会让设计的信号啊,端口,使用的FF等信息不透明,造成团队设计时不同team间的mismatch。
而你下面举的代码结构,一般来说用于状态机的情况较多,一般来说在这种结构中不要加入太大的逻辑功能,比如你用的这个函数体。应当是用这种结构纯粹做逻辑控制信号的产生。而函数体中的特定功能模块应该通过控制信号和这一状态机进行交互。之所以这样设计比较好。因为,首先函数体中要实现的功能可能不是你所设计的,甚至可能是个ip。在你设计这个控制逻辑时,只是知道接口信号而已,并没有更多的信息。第二呢就是将不同的逻辑和功能进行区分,是很好的设计习惯,便于调试和优化。我个人不认为用函数在case结构中实现较大逻辑是一种简洁,反而会让人在读代码时困惑,尤其是在使用状态机时,调试和对于状态机专门的优化都不太容易进行。控制模块,功能模块,接口模块,这些模块一定要清晰的分开进行定义和设计。这是真正的简洁和明了。
个人认为verilog设计的可读性,并不是代码少,或者逻辑上好说,而是逻辑信号传输关系的清晰,以及模块结构划分的清晰和接口信号逻辑的清晰。这样的设计在维护性,扩展性以及整个top-down设计中都会体现其有点。
所以我个人对于 verilog-2001中的*的使用也觉得不是很好。加上现在模块间的integration都可以用脚本完成,所以模块间的线的多少,并不是评价一个设计好坏的标准,除非你能确定你能减少物理用线,否则逻辑上看起来的简洁,反而会在大型的设计中产生一些困扰。
阅读(1913) | 评论(0) | 转发(0) |