57 lines
1.9 KiB
Scala
57 lines
1.9 KiB
Scala
package projet
|
|
import chisel3._
|
|
|
|
/*\
|
|
* Principalement le timer pour pouvoir faire tourner space invaders !
|
|
\*/
|
|
class CLint extends Module {
|
|
val io = IO(new Bundle {
|
|
val bus = new BusInterface
|
|
val tip = Output(Bool())
|
|
})
|
|
|
|
// Adresses des deux registres 64 bits du composant
|
|
val MTIMERCMP_ADDR = 0x4000
|
|
val MTIMER_ADDR = 0xbff8
|
|
|
|
// Sur le rv32i le timer est constitué de 2 registres pour faire 64 bits
|
|
val mtime_lo = RegInit(0.U(32.W))
|
|
val mtime_hi = RegInit(0.U(32.W))
|
|
|
|
// Free running, comme on dit chez nous !
|
|
mtime_lo := mtime_lo + 1.U
|
|
mtime_hi := Mux(mtime_lo + 1.U === 0.U, mtime_hi + 1.U, mtime_hi)
|
|
|
|
// La comparaison nécessite également 2 registres, pour une
|
|
// comparaison sur 64 bits si nécessaire
|
|
val mtimecmp_lo = RegInit(0.U(32.W))
|
|
val mtimecmp_hi = RegInit(0.U(32.W))
|
|
// Sortie mtimer interrupt pending dont on se moque pour l'instant
|
|
io.tip := (mtime_hi > mtimecmp_hi) || ((mtime_hi === mtimecmp_hi) && (mtime_lo >= mtimecmp_lo))
|
|
// Valeur par défaut sur le bus de lecture
|
|
// avec toujours un cycle de latence
|
|
val clintRegValue = RegInit(0.U(32.W))
|
|
|
|
io.bus.rdata := clintRegValue
|
|
|
|
when(io.bus.en === true.B) {
|
|
when(io.bus.be.asUInt.orR) { // Écriture
|
|
when(io.bus.addr === MTIMERCMP_ADDR.U) {
|
|
mtimecmp_lo := io.bus.wdata
|
|
}.elsewhen(io.bus.addr === (MTIMERCMP_ADDR + 4).U) {
|
|
mtimecmp_hi := io.bus.wdata
|
|
}
|
|
}.otherwise { // Lecture
|
|
when(io.bus.addr === MTIMER_ADDR.U) {
|
|
clintRegValue := mtime_lo
|
|
}.elsewhen(io.bus.addr === (MTIMER_ADDR + 4).U) {
|
|
clintRegValue := mtime_hi
|
|
}.elsewhen(io.bus.addr === MTIMERCMP_ADDR.U) {
|
|
clintRegValue := mtimecmp_lo
|
|
}.elsewhen(io.bus.addr === (MTIMERCMP_ADDR + 4).U) {
|
|
clintRegValue := mtimecmp_hi
|
|
}
|
|
}
|
|
}
|
|
}
|