Skip to content

Commit

Permalink
adding leros to DtuTop
Browse files Browse the repository at this point in the history
  • Loading branch information
torurstrom committed Nov 28, 2024
1 parent 530d5b6 commit be70f5e
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 8 deletions.
46 changes: 39 additions & 7 deletions src/main/scala/DtuTop.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import chisel3._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}

import leros._
import leros.wrmem._

/*
* DTU Top level
* Some notes on reset strategy:
Expand All @@ -10,7 +13,7 @@ import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
* A verilog blackbox module is added that generates a synchronous active high reset from an asynchrnous active low reset
*/

class DtuTop(addrWidth:Int = 32, dataWidth:Int = 32) extends Module {
class DtuTop(addrWidth:Int = 32, dataWidth:Int = 32, prog:String = "", resetSyncFact:() => ResetSyncBase = () => Module(new ResetSync())) extends Module {
val io = IO(new Bundle {
// Interface: APB
val apb = new ApbTargetPort(addrWidth, dataWidth)
Expand All @@ -33,24 +36,53 @@ class DtuTop(addrWidth:Int = 32, dataWidth:Int = 32) extends Module {
})

// Generate a synchronous active high reset
val ResetSync = Module(new ResetSync())
val ResetSync = resetSyncFact()
ResetSync.io.clock := clock
ResetSync.io.resetIn := reset

val lerosSize = 32
val lerosMemAddrWidth = 8
val lerosClockFreq = 100000000
val lerosUartBaudrate = 115200

// All modules instantiated here are reset by synchronous active high reset
// All registers must be instantiated within this to ensure all have the same reset
withReset(ResetSync.io.resetOut) {
val leros = withReset(ResetSync.io.resetOut) {
val ApbRegs = Module(new ApbRegTarget(addrWidth, dataWidth, 0x01050000, 5))
io.apb <> ApbRegs.io.apb

// pmod 0 set to output
val pmod0oeReg = RegInit(0.U(8.W))
val pmod0gpoReg = RegInit(0.U(1.W))
io.pmod0.oe := pmod0oeReg
io.pmod0.gpo := pmod0gpoReg

if (!prog.isEmpty) {
val leros = Module(new Leros(prog = "notused", size = lerosSize, memAddrWidth = lerosMemAddrWidth))
val instrMem = Module(new InstrMem(lerosMemAddrWidth, prog))
instrMem.io <> leros.imemIO

// val instrMem = Module(new WrInstrMemory(lerosMemAddrWidth, lerosClockFreq, lerosUartBaudrate))
// instrMem.io.instrAddr := leros.imemIO.addr
// leros.imemIO.instr := instrMem.io.instr
// instrMem.io.uartRX := io.pmod0.gpi(0)

val dataMem = Module(new DataMem(lerosMemAddrWidth, false))
dataMem.io <> leros.dmemIO

// IO is now mapped to 0x0f00, but wrAddr counts in 32-bit words
when((leros.dmemIO.wrAddr === 0x03c0.U) && leros.dmemIO.wr) {
dataMem.io.wr := false.B
pmod0oeReg := 1.U
pmod0gpoReg := leros.dmemIO.wrData(7, 0)
}
leros
} else null.asInstanceOf[Leros]
}

// interrup not generated
io.irq1 := false.B

// pmod 0 set to output
io.pmod0.oe := 0.U
io.pmod0.gpo := 0.U

// pmod 1 set to output
io.pmod1.oe := 0.U
io.pmod1.gpo := 0.U
Expand Down
10 changes: 9 additions & 1 deletion src/main/scala/ResetSync.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import chisel3._
import chisel3.util._

class ResetSync extends HasBlackBoxResource {
trait ResetSyncBase {
val io = IO(new Bundle{
val clock = Input(Clock())
val resetIn = Input(Bool())
val resetOut = Output(Bool())
})
}

class ResetSync extends HasBlackBoxResource with ResetSyncBase {
addResource("ResetSync.sv")
}


class ResetSyncTest extends Module with ResetSyncBase {
io.resetOut := io.resetIn
}
34 changes: 34 additions & 0 deletions src/test/scala/DtuTopTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import chisel3._
import chisel3.util.experimental.BoringUtils

import leros._

class DtuTopTest(prog:String) extends Module {
val dtuTop = Module(new DtuTop(prog = prog, resetSyncFact = () => Module(new ResetSyncTest())))
// val programmer = Module(new Programmer(dtuTop.lerosClockFreq, dtuTop.lerosUartBaudrate, prog))
val io = IO(new Debug(dtuTop.lerosSize, dtuTop.lerosMemAddrWidth))

// Boring Utils for debugging
io.accu := DontCare
io.pc := DontCare
io.instr := DontCare
io.exit := DontCare
BoringUtils.bore(dtuTop.leros.accu, Seq(io.accu))
BoringUtils.bore(dtuTop.leros.pcReg, Seq(io.pc))
BoringUtils.bore(dtuTop.leros.instr, Seq(io.instr))
BoringUtils.bore(dtuTop.leros.exit, Seq(io.exit))


dtuTop.io.apb.paddr := 0.U
dtuTop.io.apb.pwrite := false.B
dtuTop.io.apb.psel := false.B
dtuTop.io.apb.penable := false.B
dtuTop.io.apb.pwdata := 0.U

// dtuTop.io.pmod0.gpi := programmer.io.txd ## 0.U
dtuTop.io.pmod0.gpi := 0.U
dtuTop.io.pmod1.gpi := 0.U
dtuTop.io.irqEn1 := false.B
dtuTop.io.ssCtrl1 := 0.U
}

40 changes: 40 additions & 0 deletions src/test/scala/DtuTopTester.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import scala.sys._
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import chisel3.util.experimental.BoringUtils

import leros._

class DtuTopTester extends AnyFlatSpec with ChiselScalatestTester {
System.setProperty("testpath", "leros/asm/test")
val progs = leros.shared.Util.getProgs()
progs.foreach(p => {
val program = p + ".s"

def testFun(dut: DtuTopTest): Unit = {

var run = true
var maxCycles = 1000
while (run) {
val pc = dut.io.pc.peekInt()
val accu = dut.io.accu.peekInt()
val instr = dut.io.instr.peekInt()
// Predef.printf("pc: 0x%04x instr: 0x%04x accu: 0x%08x\n", pc, instr, accu)
dut.clock.step(1)
maxCycles -= 1
run = dut.io.exit.peekInt() == 0 && maxCycles > 0
assert(maxCycles > 0, "Running out of cycles")
}
val res = dut.io.accu.expect(1.U, "Accu shall be one at the end of a test case.\n")
}

"Leros HW " should s"pass $program" in {
test(new DtuTopTest(prog = program))
.withAnnotations(Seq(WriteVcdAnnotation)) { dut =>
testFun(dut)
}
}

})
}
39 changes: 39 additions & 0 deletions src/test/scala/Programmer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package leros

import chisel3._
import chisel3.util._
import java.nio.file._
import leros.shared.Constants._
import leros.uart._

/**
* Sends content of a file over uart
* frequency: clock frequency in hz
* baudrate: baudrate in baud/s
* txFile: path to file to be sent
*/
class Programmer(frequency: Int, baudRate: Int, txFile : String) extends Module {
val io = IO(new Bundle {
val txd = Output(UInt(1.W))
})

val tx = Module(new BufferedTx(frequency, baudRate))

io.txd := tx.io.txd

val txDataFile = Files.readAllBytes(Paths.get(txFile))
val txData = VecInit(txDataFile.map(_.S(8.W)))
val len = txData.length
val cntReg = RegInit(0.U(log2Ceil(len).W))

val instr = txData(cntReg).asUInt ## txData(cntReg-1.U).asUInt
val enable = RegInit(true.B)
enable := cntReg =/= len.U

tx.io.channel.bits := txData(cntReg).asUInt
tx.io.channel.valid := cntReg =/= len.U || enable

when(tx.io.channel.ready && cntReg =/= len.U) {
cntReg := cntReg + 1.U
}
}

0 comments on commit be70f5e

Please sign in to comment.