From 0cc7d6de8fbce8b9dc9e78766993b22aa874dddb Mon Sep 17 00:00:00 2001 From: Sina Karvandi Date: Wed, 3 Apr 2024 14:40:43 +0900 Subject: [PATCH] remove UART library --- src/main/scala/hwdbg/lib/uart/Uart.scala | 222 ------------------ .../scala/hwdbg/lib/uart/UartTester.scala | 77 ------ 2 files changed, 299 deletions(-) delete mode 100644 src/main/scala/hwdbg/lib/uart/Uart.scala delete mode 100644 src/test/scala/hwdbg/lib/uart/UartTester.scala diff --git a/src/main/scala/hwdbg/lib/uart/Uart.scala b/src/main/scala/hwdbg/lib/uart/Uart.scala deleted file mode 100644 index b0b8029..0000000 --- a/src/main/scala/hwdbg/lib/uart/Uart.scala +++ /dev/null @@ -1,222 +0,0 @@ -/* - * - * A UART is a serial port, also called an RS232 interface. - * - * Author: Martin Schoeberl (martin@jopdesign.com) - * - */ -package hwdbg.lib.uart - -import chisel3._ -import circt.stage.ChiselStage -import chisel3.util._ - -class UartIO extends DecoupledIO(UInt(8.W)) - -/** - * Transmit part of the UART. - * A minimal version without any additional buffering. - * Use a ready/valid handshaking. - */ -class Tx(frequency: Int, baudRate: Int) extends Module { - val io = IO(new Bundle { - val txd = Output(UInt(1.W)) - val channel = Flipped(new UartIO()) - }) - - val BIT_CNT = ((frequency + baudRate / 2) / baudRate - 1).asUInt - - val shiftReg = RegInit(0x7ff.U) - val cntReg = RegInit(0.U(20.W)) - val bitsReg = RegInit(0.U(4.W)) - - io.channel.ready := (cntReg === 0.U) && (bitsReg === 0.U) - io.txd := shiftReg(0) - - when(cntReg === 0.U) { - - cntReg := BIT_CNT - when(bitsReg =/= 0.U) { - val shift = shiftReg >> 1 - shiftReg := Cat(1.U, shift(9, 0)) - bitsReg := bitsReg - 1.U - }.otherwise { - when(io.channel.valid) { - shiftReg := Cat(Cat(3.U, io.channel.bits), 0.U) // two stop bits, data, one start bit - bitsReg := 11.U - }.otherwise { - shiftReg := 0x7ff.U - } - } - - }.otherwise { - cntReg := cntReg - 1.U - } -} - -/** - * Receive part of the UART. - * A minimal version without any additional buffering. - * Use a ready/valid handshaking. - * - * The following code is inspired by Tommy's receive code at: - * https://github.com/tommythorn/yarvi - */ -class Rx(frequency: Int, baudRate: Int) extends Module { - val io = IO(new Bundle { - val rxd = Input(UInt(1.W)) - val channel = new UartIO() - }) - - val BIT_CNT = ((frequency + baudRate / 2) / baudRate - 1).U - val START_CNT = ((3 * frequency / 2 + baudRate / 2) / baudRate - 1).U - - // Sync in the asynchronous RX data, reset to 1 to not start reading after a reset - val rxReg = RegNext(RegNext(io.rxd, 1.U), 1.U) - - val shiftReg = RegInit(0.U(8.W)) - val cntReg = RegInit(0.U(20.W)) - val bitsReg = RegInit(0.U(4.W)) - val valReg = RegInit(false.B) - - when(cntReg =/= 0.U) { - cntReg := cntReg - 1.U - }.elsewhen(bitsReg =/= 0.U) { - cntReg := BIT_CNT - shiftReg := Cat(rxReg, shiftReg >> 1) - bitsReg := bitsReg - 1.U - // the last shifted in - when(bitsReg === 1.U) { - valReg := true.B - } - }.elsewhen(rxReg === 0.U) { // wait 1.5 bits after falling edge of start - cntReg := START_CNT - bitsReg := 8.U - } - - when(valReg && io.channel.ready) { - valReg := false.B - } - - io.channel.bits := shiftReg - io.channel.valid := valReg -} - -/** - * A single byte buffer with a ready/valid interface - */ -class Buffer extends Module { - val io = IO(new Bundle { - val in = Flipped(new UartIO()) - val out = new UartIO() - }) - - val empty :: full :: Nil = Enum(2) - val stateReg = RegInit(empty) - val dataReg = RegInit(0.U(8.W)) - - io.in.ready := stateReg === empty - io.out.valid := stateReg === full - - when(stateReg === empty) { - when(io.in.valid) { - dataReg := io.in.bits - stateReg := full - } - }.otherwise { // full - when(io.out.ready) { - stateReg := empty - } - } - io.out.bits := dataReg -} - -/** - * A transmitter with a single buffer. - */ -class BufferedTx(frequency: Int, baudRate: Int) extends Module { - val io = IO(new Bundle { - val txd = Output(UInt(1.W)) - val channel = Flipped(new UartIO()) - }) - val tx = Module(new Tx(frequency, baudRate)) - val buf = Module(new Buffer()) - - buf.io.in <> io.channel - tx.io.channel <> buf.io.out - io.txd <> tx.io.txd -} - -/** - * Send a string. - */ -class Sender(frequency: Int, baudRate: Int) 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 msg = "Hello World!" - val text = VecInit(msg.map(_.U)) - val len = msg.length.U - - val cntReg = RegInit(0.U(8.W)) - - tx.io.channel.bits := text(cntReg) - tx.io.channel.valid := cntReg =/= len - - when(tx.io.channel.ready && cntReg =/= len) { - cntReg := cntReg + 1.U - } -} - -class Echo(frequency: Int, baudRate: Int) extends Module { - val io = IO(new Bundle { - val txd = Output(UInt(1.W)) - val rxd = Input(UInt(1.W)) - }) - // io.txd := RegNext(io.rxd) - val tx = Module(new BufferedTx(frequency, baudRate)) - val rx = Module(new Rx(frequency, baudRate)) - io.txd := tx.io.txd - rx.io.rxd := io.rxd - tx.io.channel <> rx.io.channel -} - -class UartMain(frequency: Int, baudRate: Int) extends Module { - val io = IO(new Bundle { - val rxd = Input(UInt(1.W)) - val txd = Output(UInt(1.W)) - }) - - val doSender = true - - if (doSender) { - val s = Module(new Sender(frequency, baudRate)) - io.txd := s.io.txd - } else { - val e = Module(new Echo(frequency, baudRate)) - e.io.rxd := io.rxd - io.txd := e.io.txd - } - -} - -object Main extends App { - // These lines generate the Verilog output - println( - ChiselStage.emitSystemVerilog( - new UartMain(50000000, 115200), - firtoolOpts = Array( - "-disable-all-randomization", - "-strip-debug-info", - "--split-verilog", // The intention for this argument (and next argument) is to separate generated files. - "-o", - "generated/", - ) - ) - ) -} diff --git a/src/test/scala/hwdbg/lib/uart/UartTester.scala b/src/test/scala/hwdbg/lib/uart/UartTester.scala deleted file mode 100644 index 8cfde35..0000000 --- a/src/test/scala/hwdbg/lib/uart/UartTester.scala +++ /dev/null @@ -1,77 +0,0 @@ -import chisel3._ -import chisel3.experimental.BundleLiterals._ -import chisel3.simulator.EphemeralSimulator._ -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.must.Matchers - -import hwdbg.lib.uart._ - - -class UartTxTests extends AnyFreeSpec with Matchers { - "UartTx should work" in { - simulate(new Tx(10000, 3000)) { dut => - dut.clock.step(2) - // ready/valid handshake the first character - dut.io.channel.valid.poke(true.B) - dut.io.channel.bits.poke('a'.toInt.U) - while (!dut.io.channel.ready.peek().litToBoolean) { - dut.clock.step(1) - } - dut.clock.step(1) - dut.io.channel.valid.poke(false.B) - dut.io.channel.bits.poke(0.U) - - // wait for start bit - while (dut.io.txd.peek().litValue != 0) { - dut.clock.step(1) - } - // to the first bit - dut.clock.step(3) - - for (i <- 0 until 8) { - dut.io.txd.expect((('a'.toInt >> i) & 0x01).U) - dut.clock.step(3) - } - // stop bit - dut.io.txd.expect(1.U) - } - } -} - -class UartSenderTests extends AnyFreeSpec with Matchers { - "UartSender should work" in { - simulate(new Sender(10000, 3000)) { dut => - dut.clock.step(300) - } - } -} - -class UartRxTests extends AnyFreeSpec with Matchers { - "UartRx should work" in { - simulate(new Rx(10000, 3000)) { dut => - dut.io.rxd.poke(1.U) - dut.clock.step(10) - // start bit - dut.io.rxd.poke(0.U) - dut.clock.step(3) - // 8 data bits - for (i <- 0 until 8) { - dut.io.rxd.poke(((0xa5 >> i) & 0x01).U) - dut.clock.step(3) - } - // stop bit - dut.io.rxd.poke(1.U) - while (!dut.io.channel.valid.peek().litToBoolean) { - // wait on valid - dut.clock.step(1) - } - dut.io.channel.bits.expect(0xa5.U) - - // read it out - dut.io.channel.ready.poke(true.B) - dut.clock.step(1) - dut.io.channel.ready.poke(false.B) - dut.clock.step(5) - } - } -}