blob: 305dce6cfb58e4a3a4c4c6db27870e3d0debd0ad [file] [log] [blame]
package core
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.util.{switch, is}
import components.Instruction
import ControlPath._
object ControlPath {
object S extends ChiselEnum {
val IF, IF_WAIT, DECODE, EXEC, MEM, MEM_WAIT, WB, HALT = Value
}
}
class ControlPath extends Module {
val io = IO(new Bundle {
val instr = Input(new Instruction)
val issue_if = Output(Bool())
val if_done = Input(Bool())
val issue_mem = Output(Bool())
val mem_we = Output(Bool())
val mem_done = Input(Bool())
val waiting = Output(Bool())
val halted = Output(Bool())
val state = Output(S())
val restart_core = Input(Bool())
val restart = Output(Bool()) // to datapath
})
val restart_reg = RegInit(false.B)
io.restart := io.restart_core || restart_reg
val state = RegInit(S.IF)
io.state := state
val is_store_instr = (io.instr.has_mem && !io.instr.has_wb)
io.issue_if := (state === S.IF)
io.issue_mem := (state === S.MEM)
io.mem_we := is_store_instr
io.waiting := (state === S.IF_WAIT || state === S.MEM_WAIT)
io.halted := (state === S.HALT)
// State-transition logic
switch (state) {
is (S.IF) {
state := S.IF_WAIT
}
is (S.IF_WAIT) {
state := Mux(io.if_done, S.DECODE, S.IF_WAIT)
}
is (S.DECODE) {
state := S.EXEC
}
is (S.EXEC) {
when (io.instr.has_stop) {
state := S.HALT
}.elsewhen (io.instr.has_jump || io.instr.has_branch) {
state := S.IF
}.elsewhen (io.instr.has_mem) {
state := S.MEM
}.otherwise {
state := S.WB
}
}
is (S.MEM) {
state := S.MEM_WAIT
}
is (S.MEM_WAIT) {
state := Mux(io.mem_done,
Mux(is_store_instr, S.IF, S.WB),
S.MEM_WAIT)
}
is (S.WB) {
state := S.IF
}
is (S.HALT) {
state := S.HALT
}
}
when (io.restart_core) {
restart_reg := true.B
}
when (restart_reg && (state =/= S.IF) && (state =/= S.IF_WAIT) && (state =/= S.MEM) && (state =/= S.MEM_WAIT)) {
restart_reg := false.B
state := S.IF
}
}