【龙芯杯日志】2020/11/19-2020/11/21: 单周期CPU
2020/11/19
重新看了一遍MIPS指令集,跟着PPT把控制路径推导了一遍。
照着PPT里的代码实现了外围的几个模块,regfile、imem、dmem和alu,感觉PPT中的代码有些奇怪,也许是对这些模块的理解还不够深入。
开始写cu,PPT中的控制逻辑基本上可以照搬过来。
目前的代码还是和PPT上的代码保持一致,感觉可以有更好的写法。
2020/11/20
今天密集开发,写了不少内容,也发现了不少问题。
基本上完成了cu,然后开始在顶层把各模块组装起来。
组装过程发现了不少问题,最严重的问题就是发现需要实现一个单独的pc模块,所以又专门实现了个pc模块。
然后进行了整体组装,并结合自己的理解和去年学长的比赛代码风格,对代码进行了很多改动。
下面列一下技术上的问题:
- alu中的控制信号形式(顺序编码)和cu的控制信号(独热编码)不匹配,经过比较,认为顺序编码较为合适
- alu的完成输出信号和错误信息信号似乎没有意义,在实际使用中可以转为使用标志位(因此后面在alu中添加了零标志位用于检验beq)
- 按照PPT中的控制逻辑,beq分支判断时,会将两个寄存器的值输入到br单元中,不过br单元在代码实现中并未体现,用于跳转和分支的相关逻辑均在pc中,而在pc中添加比较逻辑自认为会使得电路不够简洁,最终采取了一个自认为较合适的办法:将beq指令的alu操作设为减法,同时为alu添加零标志位,从而可以通过零标志位判断寄存器值是否相等,即可将alu的零标志位和指令的分支标志位结合确定pc是否应分支跳转
学习了去年的代码以及其他的一些代码之后,发现在写法上也有不少可以提的:
- 宏定义可以极大增加代码的可读性:从去年代码中学到了verilog头文件的用法,可以把一些静态的数值定义在头文件中,比如指令代码、alu控制信号等等,关于这个问题,可以看【这篇文章】。
- PPT中在alu和cu里使用嵌套的三目运算符的写法,在RTL中会被抽象为一系列MUX的级联,增加电路复杂性和门路径长度,换成函数并使用case结构就可以转化为采用MUX的电路,优化了电路结构,具体的分析可以看【这篇文章】。
- 关于cu中控制信号的设计,目前看到的有三种方法:PPT上的“相等判断的或组合”法,我自己实现的掩码法,还有去年代码的全指令信号法,【这篇文章】比较了三种不同的方法,但是方法间的优劣还不太清楚,需要进一步研究。
- regfile有两种写法,一种的输出是wire型,一种是reg型,两种写法的介绍和比较可以看【这篇文章】。
2020/11/21
今天开始对cpu进行仿真调试,花了大半天终于调出来了。
刚开始的时候在综合时发现了不少问题,值得注意的是,有些写错的地方并不会被认为是error,仅仅会被视为warning,因此在综合后看warning也是非常重要的。
一些典型的错误记在了【这篇文章】中,之后遇到的错误也会在这里一并汇总作为参考。
在排错之前,需要先生成包括代码的内存dump,PPT中没有具体提及相关的操作,在【这篇文章】写了一个简单的教程。
之后就是漫长的排错过程。
在调试中发现的错误大部分是三目运算符两个结果写反,或者变量名写错之类的普遍问题,不过也遇到了几个较有意思的问题,在【这篇文章】里可以看到对这些问题的介绍和一些思考。
在修改了许多问题,进行了许多测试之后,cpu终于成功地跑起来了,第一个单周期cpu的征程宣告结束。