然后给了一段式状态机的代码,代码逻辑就是开始所说的,如何将所有逻辑写到一个always块。有一说一,这种代码大家不要写.......
这是代码对应的电路图,大家可以看到,会多消耗一个寄存器,用于对应q这个信号。代码和电路都比较简单,就不过多介绍了。
然后给了一个复杂点的例子。可以看到一共有三个状态,然后定义了一个function,实际上就是可以调用的一个组合逻辑而已。我们先看右边这个always_ff逻辑块。
- 初始状态为s0,然后s0会直接跳转到s1,s1会跳转到s2。不需要满足什么逻辑才会进行跳转,所以是3个时钟周期为一次循环。
- 再看c和count这两个逻辑变量。初始状态count和c都为0。s1状态count变成1,c变成a+b(a和b是输入信号,所以这是个mealy型状态机),s2状态count会经过myinc这个函数的计算,这个函数的逻辑将'b01变成了'b10,c变成a-b。
最后将c经过always_comb的逻辑运算,得到了f,这就是整段代码的含义(具体这段代码用来干嘛的,不太清楚。。。)
这是对应的电路图,我给大家理一下。
- 首先我们依旧看状态变化,在最下方,用一个mux选出送到state寄存器的输入信号,这里已经包含了状态机三部分的两部分了。“状态转移逻辑和状态寄存逻辑”。
- 然后状态会送到输出计算逻辑,我们先看count这个寄存器变量。由代码可以知道,它的值可能会是0,会是1,会是由myinc计算得到的值。因此依然会是一个mux进行选择(由state作为选择信号select),然后送到count寄存器作为输出。
- 然后是f变量,其实也是一样的道理。可能是0,可能是a+b,可能是a-b。由状态来选择进行输出到c寄存器。输出以后的变量还要经过always_comb逻辑,进行逻辑运算得到f。
经过了上面的代码,相信大家对状态机,以及状态机对应的代码和电路有了一定的了解。接下来让我们看一个有趣的例子,斐波那契数列
答主本人当时上verilog课的时候,期末上机第一道编程题就是斐波那契数列(当时不学无术的我做了好久才做了出来,越想越觉得自己菜),所以大家好好阅读这篇文章,除了帮助就业科研,还能帮你做考试题(bushi
回到slide本身,斐波那契数列的通向表达式如图所示,相信大家都知道了吧?用通俗的语言来表达,前两个数字为1,后面的数字为前两个数字的和。
这种极具规律,通项公式都给你列出来了的算法,当然可以用状态机来实现。我们定义一个状态机,输入"input_s"表示计算多少项n,"fibo_out"表示“F(n)"。在begin_fibo使能之前,一直保持IDLE状态。运算完成以后,会把done信号拉高。并且我们的testbench会进行一个比较。
然后给了设计思路,使用三个寄存器。分别表示计数,R0和R1的值。当counter计数达到input_s次数的时候完成运算,在此之前一直重复执行运算。
然后给出了代码实现。这种状态机的代码分析思路都是一致的,如下几步:
- 首先看状态怎么跳转,默认IDLE状态,当拉高begin_fibo的时候跳转到COMPUTE状态,当运算了input_s次数的时候,从COMPUTE状态跳转到DONE状态,DONE状态维持一个周期便会跳转到IDLE状态。
- 然后看逻辑输出。在IDLE状态,默认所有变量都是0,当begin_fibo拉高的时候,会给R0赋值1,R1赋值0(这里隐含了一个else逻辑,因为寄存器默认输出保持不变,所以不需要写这几个逻辑变量维持不变的逻辑。但是对于初学者,我的建议是写上,不然可能过段时间你就看不懂你代码了。)然后在COMPUTE状态下,如果没有运算指定的次数,则一直算,算完以后便可以跳转到DONE状态了。这一部分其实跟你写PYTHON区别不大了。因为状态机的思路本身就和软件很类似。
- 最后看一些always_ff块外面有没有一些别的跟state相关的逻辑,这里没有
最后留了一个作业作为project。让你只用两个状态(甚至一个)实现该功能。提示你可以使用assign语句赋值fibo_out和done信号。
两个状态实现其实很简单,大家应该能发现,那个DONE状态本身就是冗余的,我们运算完成以后,可以直接从COMPUTE跳转到IDLE状态即可。至于一个状态实现,那也不能称为状态机了,大家可以用一系列的if/else语句实现,也不难。
最后对于题目所要求的的,用testbench检测运算结果是否正确。首先我解释一下什么是testbench。我们完成设计以后,它只是一个功能模块,我们不知道它功能是否正确,因此我们需要写一个tb文件,里面例化了你的设计,然后有逻辑语句驱动你的设计的输入变量,并且对你的输出变量进行比对,判断对比结果是否正确。更多的概念可以自己搜一下什么是testbench。
此外,关于testbench例化模块,是个很麻烦的事情。大家可以搜一下TerosHDL,我一般使用这个直接生成tb。很方便。当然,这个生成的tb由于不知道你设计的逻辑功能,仅仅是一个简单的模块例化加输入信号赋0/1而已。如何进行比对呢?我的建议是可以加入python进行辅助验证。以这个斐波那契数列为例,大家用Python产生一个txt文件,为绝对正确的斐波那契数列,一般称为golden model或reference model。然后在testbench中大家将输出的结果与之前产生的txt进行比对即可(readmemh函数)。比对成功则PASS,否则FAIL。用脚本辅助IC设计的思想是非常重要的,当然大家也可以不用Python,用MATLAB或者C语言也是一样的。