这篇文章带来ECE111第三节课的Slides以及自己的一些补充。
该课程的网站如下:
首先回顾了一下上节课所介绍的always_comb语法,该语法用于组合逻辑赋值。需要重点关注的就是阻塞赋值,有关阻塞赋值,可以看我在上一讲中的说明:ECE111 第二节课,这里不重复介绍。
然后是这节课的总览。重点讨论”有关时钟的always赋值语句“,该语句会产生”组合逻辑+触发器“。不幸的是,SV没有定义良好的语义来描述触发器和有限状态机,关于这句话,我认为老师可能是要表达SV没有专门的语法去描述状态机,但是这实际上影响不大。关于状态机有专门的写法(idioms,编程模板),综合器可以很好的综合。大家只需要按照模板去写即可,并不复杂。
然后介绍了一下D触发器的代码实现,可以看到时序逻辑一定有时钟信号,并且赋值语句一定要采取"<=",也就是非阻塞赋值。这意味着在下一时钟边沿进行采样。always_ff表明这是一段时序逻辑。@里面表示敏感列表,所谓的敏感列表就是当敏感列表发生变化的时候,会进入该复制逻辑。这里的敏感列表是时钟上升沿。综上可以知道这段代码的含义是,在时钟的上升沿,将d的值送给q(这里其实隐含了个逻辑,就是非时钟上升沿,q的值会保持不变)。显示这就是D触发器的逻辑,因此这段代码会综合成D触发器。D触发器在硬件设计中是非常重要的,目前任何时序逻辑都离不开它。
接下来介绍了一下带复位的D触发器。所谓复位,就是让存储的值回到某一初始状态,典型的是全部置为0。上图中为同步复位,同步复位指的是复位信号只有在时钟的边沿才会触发生效,这段代码的逻辑是。当时钟上升沿到来的时候,如果reset信号为1,则将q的输出置为全0。否则将d的输出送给q。同步复位在现代数字系统中尤其是ASIC用的比较少了,一般是采用”异步复位,同步释放“的方式,我将在后面的文章介绍该方式。但是对Xilinx的多数FPGA,其DSP和BRAM只有同步复位,如果使用者非要用异步复位,则会消耗更多的逻辑资源。这种情况下应该使用同步复位,可以节省资源开销。
接下来介绍了一下异步复位。仔细观察一下代码,和同步复位的区别在于,敏感列表中加入了posedge reset信号。既然如此,大家应该容易理解,当reset拉高的时候,敏感列表发生了变化,因此会进入赋值逻辑,并不需要时钟边沿才可以变化。这种复位与时钟不同步的情况,就称为异步复位。这样生成的D触发器为带异步复位的触发器。
开始介绍的异步复位是高电平有效,既然有高电平有效的,肯定也有低电平有效。我们把posedge改为negedge,并且在reset前面加上!(表示取反)即可,这样便可以在reset的下降沿进行复位。此外,由于工程设计习惯,低电平有效的复位一般在reset最后加上n,表示negative。
有了D触发器这个工具,让我们开始设计时序电路吧。上述的语法很简单,其表达的含义为,将t和c相与,结果送给f。和组合逻辑不同的地方在于,f的值只有在时钟上升沿才会发生变化,并且所采样的值,为上一个周期t和c相与的结果。(那如果t和c一个时钟周期都没有算完怎么办?关于这点大家可以去搜一下建立时间和保持时间的概念,相信看完以后对时序逻辑赋值会有更充分地理解)。除此之外,大家如果按照下面的代码这样写
assign d=t&c; always_ff @(posedge clk) begin f<=d; end