「BUAA-CO」 P4课上


写在前面:笔者不是大佬,P4二战方过,这里记载了二战题目的comprehensive版本。

  • 为什么是comprehensive版本?因为做完挺早,等助教问答的时候顺手把题抄了。
  • 为什么没有一战题目?因为一战没心情回忆痛苦的过去。
  • 为什么二战如此神速?我也不知道,可能是题简单吧。

SSZE

opcode = 6’b000000
func = 6’b001111

当GPR[rs]和GPR[rt]后缀 0 的个数相同时,将GPR[rd]置 1 ,否则置 0 ;

Answer:重点在数0的个数,还有就是改指令的时候记得把通路改完整(这个以大家对自己verilog代码的理解都不成问题)。

CABC

opcode = 6’b111100

cross1 = GPR[rs][23:16] || GPR[rs][7:0] || GPR[rt][31:24] || GPR[rt][15:8]
cross2 = GPR[rt][7:0] || GPR[rt][23:16] || GPR[rs][15:8] || GPR[rs][31:24]
xor_result = cross1 ^ cross2
if (count_zeros(xor_result[31:16]) == count_zeros(xor_result[15:0])) {
PC <-- IMM_beq
}
else{
GPR[rt] <-- xor_result
}

Answer:这和第一题几乎一样,唯一需要注意的是if判断条件成立与否,寄存器堆设计的是是否操作,因此在CTRL模块中的WE(寄存器写使能信号)是(caba && isequal == 0)。isequal是ALU输出的count_zeros(xor_result[31:16]) == count_zeros(xor_result[15:0])判断结果。

LHBOC

opcode = 101101

vaddr <-- GPR[base] + sign_extend(offset)
paddr <-- vaddr[31:2] || 2'b0
memword <-- Memory[paddr]
tmp1 <-- memword[15] + memword[14] + ...... + memword[0]
tmp2 <-- memword[31] + memword[30] + ...... + memword[16]
if (tmp1 > tmp2) {
GPR[rt] <-- sign_extend(memword[15:0])
}
else{
GPR[rt] <-- sign_extend(memword[31:16])
}

Answer:这个题也挺简单的,注意一下不要被RTL语言骗了,我们看到这行memword <-- Memory[paddr],paddr是32位,而DM的范围是0-3072,只需要12位即可,我们在verilog实现的过程中要像这样

memword = DM[addr[13:2]];

addr是ALU的输出结果。

一些Tips

  1. 课下最好实现这个函数——-sign_extend
  2. 一定要记得有符号数怎么比大小,要不然就上去if手搓吧:$signed(A) > $singned(B)
  3. 循环移位别写for循环,会TLE,用这个(A >> n) + (A << (32 - n))
  4. 写函数的时候记得在function后面有begin,end把函数体包起来。
  5. 祝大家P4一战顺利😉😊

Lyrics Sharing

倘若那天
把该说的话好好说
该体谅的不执著
如果那天我
不受情绪挑拨
你会怎么做
那么多如果,可能如果我
可惜没如果,只剩下结果

后记

谨以此篇,纪念我的第一篇github博客。


文章作者: Cordial-Kid
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Cordial-Kid !
  目录