然后介绍了always_comb语句。该语法用于实现组合逻辑操作,代表其中间的逻辑是一段组合逻辑,如果有多条语句,需要在前后分别加上begin和end。此外这页slide还说明了一个非常重要的概念,“阻塞赋值”,也就是“=”。在组合逻辑当中,只允许使用阻塞赋值,阻塞赋值语句在赋值以后,才允许执行下面一条语句。因此表达式的先后顺序是非常重要的。通过电路图可以看出,t由a和b相与以后,和c相或得到了f。这是有先后顺序的,这里有点类似于软件思维。
然后又花了一页slide介绍always_comb语法。通过这段逻辑实现了二选一的mux。有没有发现,跟之前的三目运算符非常类似?实际上assign和always_comb都是用来实现组合逻辑的。assign一般用于实现较为简单的组合逻辑,而always_comb用于实现相对复杂的组合逻辑,如一堆if/else等。上图的mux逻辑足够简单,一句assign y=s?d1:d0;实际上就实现了,当然具体使用哪种,取决于个人习惯。
接下来讲了一下for操作,硬件设计中的for操作实际上是复制粘贴操作,跟你重复写几段是一样的。只不过是为了简化代码。同时for操作中的终止条件必须是确定的,如slide中的4。如果是不定的,是无法综合的,要时刻记住我们设计的是电路,不是顺序执行的软件代码,如果for循环次数不确定。综合工具又怎么知道应该综合多少份这样的电路呢?
至于这段代码实际上就是实现了四比特的加法器,读者可以自己把for展开思考一下。
上面的代码综合出来的电路如图所示,可以看到在n=4的时候,进位就已经很长了。所以行波进位加法器很慢很慢。
接下来介绍了case语句的使用说明。该语法实际上会生成一个多选一MUX,根据data的不同,确定segments的输出。case语句当中一定要写default。如果不写的话,编译器会认为你希望segments保持不变,但是这又是组合逻辑,所以会生成latch,写出latch的后果非常严重。借用之前微处理器老师的一句话,你如果写出这样的代码,离被开除也不远了。
这页slide也强调了default必须要写,否则会有很严重的后果。
然后介绍了一下casez的使用,casez常用于不关注某些比特,如上图所示的优先编码器,我们只关注a的某一位是不是1,当该位是1,低位的就不用看了。这种情况就可以使用casez语法。
然后介绍了一下嵌套的语句,编译器会从“最内部”向外编译。在该例子中,首先会为case语句生成多路复用逻辑,然后为if/else生成多路复用逻辑。然后根据for循环复制内部逻辑多次。
最后介绍了一下function语法,function实际上用的还是挺多的。用来替代常用的组合逻辑,用起来还是很爽的。
function不能带有时序信息,必须有至少一个输入,没有输出,但是有一个返回值。返回值就是function的函数名,该例子中为adder。可以看出,function实现本质上跟上面的always_comb没什么区别,但是优点在于可以复用。
这就是第二节课slide的全部内容了。大家加油,每天进步一点点。对文章有哪些意见或者想问的问题,欢迎在评论区指出。