controlUnit.scala (9680B)
1 package com.rinthyAi.perilus.controlUnit 2 3 import chisel3._ 4 import chisel3.util._ 5 6 import com.rinthyAi.perilus.alu._ 7 import com.rinthyAi.perilus.extendUnit._ 8 import com.rinthyAi.perilus.memory._ 9 10 class ControlUnit(withDebug: Boolean = false) extends Module { 11 // Figure 7.28 (page 423) 12 val io = IO(new Bundle { 13 val op = Input(Opcode()) 14 val funct3 = Input(UInt(3.W)) 15 val funct7_5 = Input(Bool()) 16 val zero, lessThan = Input(Bool()) 17 val adrSrc, irWrite, memWrite, pcWrite, regWrite, signExtData = Output(Bool()) 18 val aluSrcA = Output(AluSrcA()) 19 val aluSrcB = Output(AluSrcB()) 20 val resultSrc = Output(ResultSrc()) 21 val immSrc = Output(ImmSrc()) 22 val aluControl = Output(AluControl()) 23 val dataMask = Output(DataMask()) 24 val debug = if (withDebug) Some(Output(new Bundle { 25 val state = ControlUnitState() 26 })) 27 else None 28 }) 29 30 val aluDecoder = Module(new AluDecoder()) 31 val instrDecoder = Module(new InstructionDecoder()) 32 33 val state = RegInit(ControlUnitState.fetch) 34 35 io.debug.foreach(d => { 36 d.state := state 37 }) 38 39 val aluOp = WireDefault(AluOp.memory) 40 val branch, pcUpdate = WireDefault(false.B) 41 42 io.adrSrc := false.B 43 io.aluSrcA := AluSrcA.pc 44 io.aluSrcB := AluSrcB.rd2 45 io.irWrite := false.B 46 io.memWrite := false.B 47 io.regWrite := false.B 48 io.resultSrc := ResultSrc.aluOutBuf 49 50 when( 51 (state === ControlUnitState.memRead || state === ControlUnitState.memWb || state === ControlUnitState.memWrite) && (io.op === Opcode.load || io.op === Opcode.store) 52 ) { 53 when(io.funct3 === 0.U || io.funct3 === 4.U) { 54 io.dataMask := DataMask.byte 55 }.elsewhen(io.funct3 === 1.U || io.funct3 === 5.U) { 56 io.dataMask := DataMask.half 57 }.otherwise { 58 io.dataMask := DataMask.word 59 } 60 }.otherwise { 61 io.dataMask := DataMask.word 62 } 63 64 when(io.op === Opcode.load && (io.funct3 === 0.U || io.funct3 === 1.U)) { 65 io.signExtData := true.B 66 }.otherwise { 67 io.signExtData := false.B 68 } 69 70 // Main FSM (Figure 7.45, page 436) 71 switch(state) { 72 is(ControlUnitState.fetch) { 73 io.adrSrc := false.B 74 io.irWrite := true.B 75 io.aluSrcA := AluSrcA.pc 76 io.aluSrcB := AluSrcB.four 77 aluOp := AluOp.memory 78 io.resultSrc := ResultSrc.aluResult 79 pcUpdate := true.B 80 state := ControlUnitState.decode 81 } 82 is(ControlUnitState.decode) { 83 io.aluSrcA := AluSrcA.oldPc 84 io.aluSrcB := AluSrcB.immExt 85 aluOp := AluOp.memory 86 when(io.op === Opcode.load || io.op === Opcode.store) { 87 state := ControlUnitState.memAdr 88 }.elsewhen(io.op === Opcode.rType) { 89 state := ControlUnitState.executeR 90 }.elsewhen(io.op === Opcode.immediate) { 91 state := ControlUnitState.executeI 92 }.elsewhen(io.op === Opcode.jal) { 93 state := ControlUnitState.jal 94 }.elsewhen(io.op === Opcode.jalr) { 95 state := ControlUnitState.jalrLink 96 }.elsewhen(io.op === Opcode.branch) { 97 state := ControlUnitState.branch 98 }.elsewhen(io.op === Opcode.lui) { 99 state := ControlUnitState.lui 100 }.elsewhen(io.op === Opcode.auipc) { 101 state := ControlUnitState.auipc 102 }.elsewhen(io.op === Opcode.env || io.op === Opcode.fence) { 103 state := ControlUnitState.fetch 104 } 105 } 106 is(ControlUnitState.memAdr) { 107 io.aluSrcA := AluSrcA.rd1 108 io.aluSrcB := AluSrcB.immExt 109 aluOp := AluOp.memory 110 switch(io.op) { 111 is(Opcode.load) { 112 state := ControlUnitState.memRead 113 } 114 is(Opcode.store) { 115 state := ControlUnitState.memWrite 116 } 117 } 118 } 119 is(ControlUnitState.memRead) { 120 io.resultSrc := ResultSrc.aluOutBuf 121 io.adrSrc := true.B 122 state := ControlUnitState.memWb 123 } 124 is(ControlUnitState.memWb) { 125 io.resultSrc := ResultSrc.readDataBuf 126 io.regWrite := true.B 127 state := ControlUnitState.fetch 128 } 129 is(ControlUnitState.memWrite) { 130 io.resultSrc := ResultSrc.aluOutBuf 131 io.adrSrc := true.B 132 io.memWrite := true.B 133 state := ControlUnitState.fetch 134 } 135 is(ControlUnitState.executeR) { 136 io.aluSrcA := AluSrcA.rd1 137 io.aluSrcB := AluSrcB.rd2 138 aluOp := AluOp.arithmetic 139 state := ControlUnitState.aluWb 140 } 141 is(ControlUnitState.aluWb) { 142 io.resultSrc := ResultSrc.aluOutBuf 143 io.regWrite := true.B 144 state := ControlUnitState.fetch 145 } 146 is(ControlUnitState.executeI) { 147 io.aluSrcA := AluSrcA.rd1 148 io.aluSrcB := AluSrcB.immExt 149 aluOp := AluOp.arithmetic 150 state := ControlUnitState.aluWb 151 } 152 is(ControlUnitState.jal) { 153 io.aluSrcA := AluSrcA.oldPc 154 io.aluSrcB := AluSrcB.four 155 io.resultSrc := ResultSrc.aluOutBuf 156 aluOp := AluOp.memory 157 pcUpdate := true.B 158 state := ControlUnitState.aluWb 159 } 160 is(ControlUnitState.jalrLink) { 161 io.aluSrcA := AluSrcA.oldPc 162 io.aluSrcB := AluSrcB.four 163 io.resultSrc := ResultSrc.aluResult 164 io.regWrite := true.B 165 aluOp := AluOp.arithmetic 166 state := ControlUnitState.jalrJump 167 } 168 is(ControlUnitState.jalrJump) { 169 io.aluSrcA := AluSrcA.rd1 170 io.aluSrcB := AluSrcB.immExt 171 io.resultSrc := ResultSrc.aluResult 172 aluOp := AluOp.arithmetic 173 pcUpdate := true.B 174 state := ControlUnitState.fetch 175 } 176 is(ControlUnitState.branch) { 177 io.aluSrcA := AluSrcA.rd1 178 io.aluSrcB := AluSrcB.rd2 179 io.resultSrc := ResultSrc.aluOutBuf 180 aluOp := AluOp.branch 181 branch := true.B 182 state := ControlUnitState.fetch 183 } 184 is(ControlUnitState.lui) { 185 io.resultSrc := ResultSrc.immExt 186 io.regWrite := true.B 187 state := ControlUnitState.fetch 188 } 189 is(ControlUnitState.auipc) { 190 io.resultSrc := ResultSrc.aluResult 191 io.aluSrcA := AluSrcA.oldPc 192 io.aluSrcB := AluSrcB.immExt 193 aluOp := AluOp.auipc 194 io.regWrite := true.B 195 state := ControlUnitState.fetch 196 } 197 } 198 199 io.pcWrite := ((branch && ((io.funct3 === 0.U && io.zero) 200 || (io.funct3 === 1.U && !io.zero) 201 || ((io.funct3 === 4.U || io.funct3 === 6.U) && io.lessThan) 202 || ((io.funct3 === 5.U || io.funct3 === 7.U) && !io.lessThan))) 203 || pcUpdate) 204 205 aluDecoder.io.aluOp := aluOp 206 aluDecoder.io.funct3 := io.funct3 207 aluDecoder.io.funct7_5 := io.funct7_5 208 aluDecoder.io.op := io.op 209 io.aluControl := aluDecoder.io.aluControl 210 211 instrDecoder.io.op := io.op 212 instrDecoder.io.funct3 := io.funct3 213 io.immSrc := instrDecoder.io.immSrc 214 } 215 216 // ALU Decoder (Table 7.3, page 409) 217 class AluDecoder extends Module { 218 val io = IO(new Bundle { 219 val aluOp = Input(AluOp()) 220 val funct3 = Input(UInt(3.W)) 221 val funct7_5 = Input(Bool()) 222 val op = Input(Opcode()) 223 val aluControl = Output(AluControl()) 224 }) 225 226 io.aluControl := AluControl.add 227 228 switch(io.aluOp) { 229 is(AluOp.auipc) { 230 io.aluControl := AluControl.add 231 } 232 is(AluOp.memory) { 233 io.aluControl := AluControl.add 234 } 235 is(AluOp.branch) { 236 when(io.funct3 === 0.U || io.funct3 === 1.U) { 237 io.aluControl := AluControl.sub 238 }.elsewhen(io.funct3 === 4.U || io.funct3 === 5.U) { 239 io.aluControl := AluControl.slt 240 }.elsewhen(io.funct3 === 6.U || io.funct3 === 7.U) { 241 io.aluControl := AluControl.sltu 242 }.otherwise { 243 io.aluControl := AluControl.sub 244 } 245 } 246 is(AluOp.arithmetic) { 247 when( 248 io.funct3 === "b000".U && (io.op === Opcode.jalr || !io.op.asUInt(5) || (io.op.asUInt( 249 5 250 ) && !io.funct7_5)) 251 ) { 252 io.aluControl := AluControl.add 253 }.elsewhen(io.funct3 === "b000".U && io.op.asUInt(5) && io.funct7_5) { 254 io.aluControl := AluControl.sub 255 }.elsewhen(io.funct3 === "b001".U) { 256 io.aluControl := AluControl.sll 257 }.elsewhen(io.funct3 === "b010".U) { 258 io.aluControl := AluControl.slt 259 }.elsewhen(io.funct3 === "b011".U) { 260 io.aluControl := AluControl.sltu 261 }.elsewhen(io.funct3 === "b100".U) { 262 io.aluControl := AluControl.xor 263 }.elsewhen(io.funct3 === "b101".U && !io.funct7_5) { 264 io.aluControl := AluControl.srl 265 }.elsewhen(io.funct3 === "b101".U && io.funct7_5) { 266 io.aluControl := AluControl.sra 267 }.elsewhen(io.funct3 === "b110".U) { 268 io.aluControl := AluControl.or 269 }.elsewhen(io.funct3 === "b111".U) { 270 io.aluControl := AluControl.and 271 } 272 } 273 } 274 } 275 276 // Instruction Decoder (Table 7.6, page 413) 277 class InstructionDecoder extends Module { 278 val io = IO(new Bundle { 279 val op = Input(Opcode()) 280 val funct3 = Input(UInt(3.W)) 281 val immSrc = Output(ImmSrc()) 282 }) 283 284 io.immSrc := ImmSrc.iType 285 286 switch(io.op) { 287 is(Opcode.load) { 288 io.immSrc := ImmSrc.iType 289 } 290 is(Opcode.store) { 291 io.immSrc := ImmSrc.sType 292 } 293 is(Opcode.branch) { 294 io.immSrc := ImmSrc.bType 295 } 296 is(Opcode.immediate) { 297 io.immSrc := ImmSrc.iType 298 } 299 is(Opcode.jal) { 300 io.immSrc := ImmSrc.jType 301 } 302 is(Opcode.lui) { 303 io.immSrc := ImmSrc.uType 304 } 305 is(Opcode.auipc) { 306 io.immSrc := ImmSrc.uType 307 } 308 } 309 } 310 311 object ControlUnitState extends ChiselEnum { 312 val fetch, decode, memAdr, memRead, memWb, memWrite, executeR, aluWb, executeI, jal, jalrLink, 313 jalrJump, branch, lui, auipc = 314 Value 315 } 316 317 object Opcode extends ChiselEnum { 318 val load = Value("b0000011".U) 319 val fence = Value("b0001111".U) 320 val immediate = Value("b0010011".U) 321 val auipc = Value("b0010111".U) 322 val store = Value("b0100011".U) 323 val rType = Value("b0110011".U) 324 val lui = Value("b0110111".U) 325 val branch = Value("b1100011".U) 326 val jalr = Value("b1100111".U) 327 val jal = Value("b1101111".U) 328 val env = Value("b1110011".U) 329 }