# SIMPLECPU **Repository Path**: balababa/simplecpu ## Basic Information - **Project Name**: SIMPLECPU - **Description**: single cycle CPU - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-11-04 - **Last Updated**: 2022-11-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # compiler with iverilog: ```bash $ iverilog -o output.o input.v $ vvp -n output.o -lxt2 $ gtkwave output.lxt ``` # 预计实现的功能有: * 逻辑运算指令: * add指令 * sub指令 * and指令 * or指令 * 跳转指令 * beq * 存取指令 * load * store # 编码情况: |指令|描述|opcode(Dex)|funct7|funct3| |--|--|--|--|--| |add x5, x6, x7|x5 = x6 + x7|1|0000000|000| |sub x5, x6, x7|x5 = x6 - x7|2|0100000|000| |and x5, x6, x7|x5 = x6 & x7|3|0000000|111| |or x5, x6, x7|x5 = x6 \| x7|4|0000000|110| |beq x5, x6, 100|if(x5==x6) goto pc+100|5|--|--| |ld x5, 100(x6)|x5 = M[100 + x6]|6|--|--| |sd x5, 100(x6)|M[100 + x6] = x5|7|--|--| 高位 <-----> 低位 add : 0000000 [rs2 5] [rs1 5] 000 [rd 5] 0000001 sub : 0100000 [rs2 5] [rs1 5] 000 [rd 5] 0000010 and : 0000000 [rs2 5] [rs1 5] 111 [rd 5] 0000011 or : 0100000 [rs2 5] [rs1 5] 000 [rd 5] 0000100 ## R型指令 最常用的R型指令指令操作有7bits opcode, 7 bits funct7, 3 bits funct3构成. The following instructions are R-type: add, sub, and, or instruction fields: |funct7 (7bits)|rs2 (5)|rs1 (5)|funct3 (3)|rd (5)|opcode (7)| |--|--|--|--|--|--| |op field|source reg2|source reg1|op field|destation reg|op field| |high bits|<-|<-|<-|<-|low bits| ## I-Type I-type instructions owns two reg addr(a destation reg rd and a source reg rs1), and one imm number, whose width is 12 bits. The operation of I-type instruction is determained by *opcode* and *funct3*. Just like a R-type Instruction, but one of its *rs* and *funct7* is changed to 12-bits imm number. Instruction fields: |immediate (12)|rs1 (5)|funct3 (3)|rd (5)|opcode (7)| |--|--|--|--|--| |imm number|source reg1|op field|destation reg|op field| ## S-Type The operation of S-Type instruction is determained by *opcode* and *funct3*(same as I-type). Generally S-type instructions are memory access instructions. |Imm(7bits)|rs2 (5)|rs1 (5)|funct3 (3)|rd (5)|opcode (7)| |--|--|--|--|--|--| |imm num|source reg2|source reg1|op field|destation reg|op field| ## B-Type The operation of B-Type instruction is determained by *opcode* and *funct3*(same as I-type). Generally S-type instructions are condition branch instruction. |Imm[11] (1)|Imm[9:4] (6)|rs2 (5)|rs1 (5)|funct3 (3)|Imm[3:0] (4)|Imm[10] (1)|opcode (7)| |--|--|--|--|--|--|--|--| |imm|imm|source reg2|source reg1|op field|imm|imm|op field| # 遇到的问题 ## 新旧值问题 情景:在某一时钟上升沿时刻,PC值改变,InstruMem同步读取PC值,此时InstruMem读取到的是PC的旧值。理想情况下,应该按照这样的顺序:PC值改变->InstruMem读取PC值。 原因分析:verilog语言的各个模块都是同步进行的,不应该拿设计软件的思想来设计硬件。在《verilog HDL 数字系统设计及仿真》P162页中提到,非阻塞赋值是先将同一时间步中的所有赋值语句的右值计算出来,保存到一个临时寄存器,当此时间步结束时,再进行统一赋值。在实际代码中使用了大量的非阻塞赋值,按照此角度考虑就不奇怪了。 这也就是说,每个时钟上升沿时,每个元器件**只能取到输入的旧值**,在此时刻更新出的新值是拿不到的。 解决办法:让元器件输出的敏感列表不再是clk,而是输入元器件的值。在设计中,元器件总是按照clk上升沿的指示运行,显然不太合理!