本文共 1617 字,大约阅读时间需要 5 分钟。
-声明:该篇总结的bug是在编写代码,并进行测试过程中遇到问题,并及时记录。并不具有普适性,但可以提供相关的思路,帮助您去寻找出错的关键
文中使用的变量意义声明
变量名 | 含义 |
---|---|
pc | 32位,下一条指令在指令存储器中的地址,起始地址为32’h0040_0000 |
inst | 32位,对应MIPS指令 |
RF_W | 1位,寄存器堆regfile的写信号,高电平有效 |
wdata | 32位,寄存器堆regfile的写数据 |
waddr | 32位,寄存器堆regfile的写地址 |
1. 在顶层测试tb文件中使用$display系统函数无法读出pc以及对应的inst
$fdisplay(file_output,"pc: %h",uut.pc); //file_out指定输出结果的文件$fdisplay(file_output,"instr: %h",uut.instruction);
建议:需要理清楚$fdisplay的层次关系。
解释:以上的代码是最后正确的代码,其中uut是在tb文件中实例化的cpu的名字,pc是cpu的接口之一。用C++中的概念来说,设cpu模块是一个类,那么$fdisplay中都是对象名,也就是实例化后的模块名。如,cpu uut(clk_in,reset,pc,inst) 不断向下挖,一直到最底层的接口为止。2.一直循环读取第一条,第二条指令
在cpu中需要一个指令存储器instmem,接口如下:接口类型 | 名称 | 含义 |
---|---|---|
input[31:0] | address | 下一条指令在指令存储器中的位置 |
output[31:0] | inst | 读出来的指令 |
读出什么指令,取决于两方面
通过观察modelsim看到,address一直在0,1之间徘徊,也没有报地址溢出的错误,所以问题关键,肯定在于address。
对于address,也需要从两方面进行考虑在debug过程中,在分析清楚出错可能的原因之后,一定是先从容易的方面入手。
很幸运,在检查内部处理的部分中,找到了根源。在过程中使用了一个临时变量“接”address,实际应该是用一个32位的临时变量,但编写过程中,不小心使用了一个一位的变量,导致这个临时变量不是0就是13.regfile无法写入数据
思路:以上这个思路是在debug我们的cpu的时候最常用的方法,可以帮助我们检查到出错的量。在此基础上,顺藤摸瓜,直到找到问题的根源。
最终解决:出错根源是,由于regfile写入的wdata有多个来源,需要数据选择器进行选择。在cpu模块中实例化数据选择器时,选择信号M7手误写成了m7。由于我的代码是在sumlime中编写好后,再copy到vivado中,所以vivado并没有及时检查出拼写的错误。4.不能将测试文件中的指令读完
ps:纯经验 在tb文件中需要自行模拟时钟信号always #50 clk=~clk
**解决:**将#50改成#4或者#2,总之改小
解释:#50说明,时钟周期为100个时间单位,频率为1M。也就是说,假设这时候在规定时间内,只能做x次取指操作,那么,改成#2之后,就能做25次取指操作。5.sra测试错误
如何从测试结果找到这个问题根源请参照上述3,这边主要讲一个注意点:**解决办法:**手动通过拼接的方式写了算术右移功能
转载地址:http://uwsqi.baihongyu.com/