随着功能复杂度的快速提升,对芯片的要求也是随着提高,所以现在一款芯片的开发,往往需要数十人,长达几个月的共同开发才能完成。
因为Verilog HDL的语法相对开放,所以每个人开发的Verilog HDL之间的差异也是非常的大。但是一个设计团队之间,进行RTL模块的交叉review、相互调用是非常频繁的事情,所以为了增强RTL代码的可移植性,以及review的效率,我们通常在一个项目开始的时候,会统一整理一个RTL编码规则,里面的内容包括,命名的规则、单词的缩略原则,一些标准电路的常用写法等等。往往这个编码规则会写的很具体,但是个人认为,这是非常有必要的。在前面的五篇文章中,我们已经聊了一些,今天的文章,我就继续来聊一聊一般常见的规则。
RTL推荐编码规则
在编写RTL时候,如果有比较复杂的逻辑运算,我们一定要注意避免冗长的逻辑和子表达式。
这种情况是十分常见的,我们还是通过一个例子说明一下。比如说:
input a,b,c,d,e,f;
output out;
assign out = (a & (~b) | c )& d & (e | ~(f));
我们可以看到,这里面的运算特别复杂,牵扯到了6个输入,进行不同的逻辑,共同得到了一个输出。一般说来,这种表达式,有两个很大的问题所在:
- 我们很难在较短的时间内,得出这一串逻辑运算的最终结果,无法快速的得到一个确定的正确结果。
- 在debug过程中,很难去debug出到底是哪根信号出了问题,即使是把所有信号都拉出来,通过眼睛也是很难看出问题所在(当然debug的工具里面提供了信号的逻辑运算功能,但是毕竟要操作很长时间)
所以我们看出,使用一长串复杂的逻辑组合,带来的坏处是很明显的。
那正确的作法是怎样的?个人推荐两种作法,分别如下所示:
- 卡洛图化简。在学习数字电路的时候,大家都学过,对比较复杂的逻辑表达式,要先进行化简,然后再做成电路。
- 分成多个简单的逻辑表达式。在逻辑表达式中,我们可以多加几个中间变量,通过中间变量,一步一步得出最终的结果。例如上面的例子中,我们可以分解成以下的写法:
wire out_1,out_2,out_3,,out_4,out;
assign out_1 = a & (~b);
assign out_2 = out_1 | c;
assign out_3 = out_2 & d;
assign out_4 = e | ~(f);
assign out= out_3 & out_4;
这么写有两个好处,首先逻辑运算中的优先级就能很清楚的出来,再次,在debug过程中,我们可以先拉出out_1/out_2/out_3/out_4,可以加快debug的速度。
小结在编写复杂逻辑的时候,我们需要特别小心,逻辑优先级,是否便于debug等等,都是我们需要考虑的了。
,