package sifive.blocks.devices.uart
import Chisel._
-import config._
-import regmapper._
-import uncore.tilelink2._
-import util._
+import chisel3.experimental.MultiIOModule
+import freechips.rocketchip.config.Parameters
+import freechips.rocketchip.regmapper._
+import freechips.rocketchip.tilelink._
+import freechips.rocketchip.util._
import sifive.blocks.util.{NonBlockingEnqueue, NonBlockingDequeue}
address: BigInt,
dataBits: Int = 8,
stopBits: Int = 2,
+ divisorInit: Int = 0,
divisorBits: Int = 16,
oversample: Int = 4,
nSamples: Int = 3,
def c: UARTParams
def uartDataBits = c.dataBits
def uartStopBits = c.stopBits
+ def uartDivisorInit = c.divisorInit
def uartDivisorBits = c.divisorBits
def uartOversample = c.oversample
def uartNTxEntries = c.nTxEntries
def uartNRxEntries = c.nRxEntries
+ require(uartDivisorInit != 0) // should have been initialized during instantiation
require(uartDivisorBits > uartOversample)
require(uartOversampleFactor > uartNSamples)
}
val out = Reg(init = Bits(1, 1))
io.out := out
+ val plusarg_tx = PlusArg("uart_tx", 1, "Enable/disable the TX to speed up simulation").orR
+
val busy = (counter =/= UInt(0))
io.in.ready := io.en && !busy
when (io.in.fire()) {
- printf("%c", io.in.bits)
+ printf("UART TX (%x): %c\n", io.in.bits, io.in.bits)
+ }
+ when (io.in.fire() && plusarg_tx) {
shifter := Cat(io.in.bits, Bits(0, 1))
counter := Mux1H((0 until uartStopBits).map(i =>
(io.nstop === UInt(i)) -> UInt(n + i + 1)))
val debounce_max = (debounce === UInt(3))
val debounce_min = (debounce === UInt(0))
- val prescaler = Reg(init = UInt(0, uartDivisorBits - uartOversample))
+ val prescaler = Reg(UInt(width = uartDivisorBits - uartOversample + 1))
val start = Wire(init = Bool(false))
- val busy = Wire(init = Bool(false))
- val pulse = (prescaler === UInt(0)) && busy
+ val pulse = (prescaler === UInt(0))
- when (busy) {
- prescaler := prescaler - UInt(1)
- }
- when (start || pulse) {
- prescaler := io.div >> uartOversample
- }
+ private val dataCountBits = log2Floor(uartDataBits) + 1
- val sample = Reg(Bits(width = uartNSamples))
- val voter = Majority(sample.toBools.toSet)
- when (pulse) {
- sample := Cat(sample, io.in)
- }
+ val data_count = Reg(UInt(width = dataCountBits))
+ val data_last = (data_count === UInt(0))
+ val sample_count = Reg(UInt(width = uartOversample))
+ val sample_mid = (sample_count === UInt((uartOversampleFactor - uartNSamples + 1) >> 1))
+ val sample_last = (sample_count === UInt(0))
+ val countdown = Cat(data_count, sample_count) - UInt(1)
- private val delay0 = (uartOversampleFactor + uartNSamples) >> 1
- private val delay1 = uartOversampleFactor
+ // Compensate for the divisor not being a multiple of the oversampling period.
+ // Let remainder k = (io.div % uartOversampleFactor).
+ // For the last k samples, extend the sampling delay by 1 cycle.
+ val remainder = io.div(uartOversample-1, 0)
+ val extend = (sample_count < remainder) // Pad head: (sample_count > ~remainder)
+ val restore = start || pulse
+ val prescaler_in = Mux(restore, io.div >> uartOversample, prescaler)
+ val prescaler_next = prescaler_in - Mux(restore && extend, UInt(0), UInt(1))
- val timer = Reg(UInt(width = uartOversample + 1))
- val counter = Reg(UInt(width = log2Floor(uartDataBits) + 1))
+ val sample = Reg(Bits(width = uartNSamples))
+ val voter = Majority(sample.toBools.toSet)
val shifter = Reg(Bits(width = uartDataBits))
- val expire = (timer === UInt(0)) && pulse
-
- val sched = Wire(init = Bool(false))
- when (pulse) {
- timer := timer - UInt(1)
- }
- when (sched) {
- timer := UInt(delay1-1)
- }
val valid = Reg(init = Bool(false))
valid := Bool(false)
io.out.valid := valid
io.out.bits := shifter
- val (s_idle :: s_start :: s_data :: Nil) = Enum(UInt(), 3)
+ val (s_idle :: s_data :: Nil) = Enum(UInt(), 2)
val state = Reg(init = s_idle)
switch (state) {
when (!io.in) {
debounce := debounce + UInt(1)
when (debounce_max) {
- state := s_start
- start := Bool(true)
- timer := UInt(delay0-1)
- }
- }
- }
-
- is (s_start) {
- busy := Bool(true)
- when (expire) {
- sched := Bool(true)
- when (voter) {
- state := s_idle
- } .otherwise {
state := s_data
- counter := UInt(uartDataBits)
+ start := Bool(true)
+ prescaler := prescaler_next
+ data_count := UInt(uartDataBits+1)
+ sample_count := UInt(uartOversampleFactor - 1)
}
}
}
is (s_data) {
- busy := Bool(true)
- when (expire) {
- counter := counter - UInt(1)
- when (counter === UInt(0)) {
- state := s_idle
- valid := Bool(true)
- } .otherwise {
- shifter := Cat(voter, shifter >> 1)
- sched := Bool(true)
+ prescaler := prescaler_next
+ when (pulse) {
+ sample := Cat(sample, io.in)
+ data_count := countdown >> uartOversample
+ sample_count := countdown(uartOversample-1, 0)
+
+ when (sample_mid) {
+ when (data_last) {
+ state := s_idle
+ valid := Bool(true)
+ } .otherwise {
+ shifter := Cat(voter, shifter >> 1)
+ }
}
}
}
val txwm = Bool()
}
-trait HasUARTTopModuleContents extends Module with HasUARTParameters with HasRegMap {
+trait HasUARTTopModuleContents extends MultiIOModule with HasUARTParameters with HasRegMap {
val io: HasUARTTopBundleContents
implicit val p: Parameters
def params: UARTParams
val rxm = Module(new UARTRx(params))
val rxq = Module(new Queue(rxm.io.out.bits, uartNRxEntries))
- val divinit = 542 // (62.5MHz / 115200)
- val div = Reg(init = UInt(divinit, uartDivisorBits))
+ val div = Reg(init = UInt(uartDivisorInit, uartDivisorBits))
private val stopCountBits = log2Up(uartStopBits)
private val txCountBits = log2Floor(uartNTxEntries) + 1