Skip to content

Latest commit

 

History

History
133 lines (88 loc) · 3.87 KB

P4课下解析.md

File metadata and controls

133 lines (88 loc) · 3.87 KB

P4课下解析

看着各位学长的代码,觉得他们,,都好牛逼。。
沿着他们的足迹,我也搭了一个自己的单周期CPU。
并且重新设计了main.circ,方便对比。

再者就是多看、多分析学长的代码、博客,里面提到了很多坑。

简化你的工作

命名方式

  1. 全大写。如:
    IFU、CTL

  2. (大)驼峰。如:
    AluOp、MemAddr
    当然也可以选择ALUOp,我个人在P4中选择了AluOp(保佑我能过P4呜呜呜)
    不过我在P5中选择了ALUOp的命名方式(当事人非常后悔)。

  3. 全小写。如:
    instr、addr

我的想法是:
模块定义都是大写,
单个单词尽量缩写,
多个单词(词组)的拼接,用大驼峰。

驼峰命名有一个不好,也可能是我菜,不知道怎么处理,
就是有缩写时,会难受。比如“ALUOp”还是“AluOp”

使用宏

想要设计Multiplexer,有三种解决方法:

  1. if-else,需要设计寄存器,然后always@(*)

  2. case-endcase,同1

  3. assign语句。

设定某些常数时,可以考虑使用宏,放置在多路选择中,
如各种ALU的Op等,这样代码的可读性也更高。

MUX的设计

有至少两种方法建模多路选择:

  1. 建模Multiplexer

  2. assign直接多路选择

我个人现在比较倾向后面一种。因为到了P5,多路选择很烦,
ALU可以看作一个很大的MUX,而小型的MUX用2~4行代码就可完成建模。
又考虑到P4MUX不多,挺纠结的。

功能分配

这一部分建议阅读学长代码。
个人比较纠结的是lui,参考了YushengZhao学长的结构,把它放到了ALU里。

模块设计

我一开始根本就不知道怎样用ISE设计一个有结构的project,
因为平常都是写个状态机再写个testbench就过去了。

其实只要写好一个Verilog Module后,
View选择implementation,
Processes内找到View HDL Instantiation Template,双击,
拷贝实例化的文件内容,放到另一个module里,连好线就可以了。
ISE会自动帮我们以一个“层次”的视角看到我们的架构。

以下是我的架构:

mips----|-Controller
        |-Datapath--|--NPC
                    |--PC
                    |--IM
                    |--GRF
                    |--ALU
                    |--DM
                    |--GRF
                    |--EXT
                    |--MUX

有的人设计了IFU,把NPC、PC还有IM放一块,
还有人直接不要Datapath了,,
各种各样,什么都有,我还是跟着教程走了。

具体的模块如何设计?我用Logisim重新搭了一遍,对着翻译就好了。

出的错

  1. 多定义了线
    这个就是有的线(wire),已经作为端口了,但是在后面又重复定义了。

  2. Mux错了
    当初定义的不纯粹,把控制ALU的操作数的输出端口命名成AluSrc了,在实例化又叫做out,导致仿真的时候,一堆z

  3. 多次CTRL+V,导致AluOp[0]出现3次
    这个也会导致一堆z或x
    这个地方,虽然Logisim中对ALU的op每一位都生成了表达式,
    但是我建议不要按照Logisim的思路,
    在Verilog中,直接assign+三元表达式才快速、可读性高

  4. Mux端口位宽
    这个一不小心就错了

  5. 输出格式
    要注意空格啥的,否则会“fewer outputs”,
    测评机会对输出进行匹配,匹配不上,就miss了。

至于更多要注意的地方,可以参考这位学长的博客:
BUAA-Wander的P4解析

Debug

一般都是xxx和zzz
这个没有办法,得老老实实跟着数据通路走一遍。

先看模块定义,再看实例化。

上机前的害怕

sll指令

ALU的operandB要有一个sel

循环右移指令

x = (x >> 32-k) | (x << k);

生成中间变量,然后做或运算