perilus

RISC-V processor built with Chisel
git clone https://git.bradleygannon.com/perilus.git
Log | Files | Refs | Submodules | README

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 }