uart: power-on with the right divider for the design (#15)
[sifive-blocks.git] / src / main / scala / devices / uart / UART.scala
1 // See LICENSE for license details.
2 package sifive.blocks.devices.uart
3
4 import Chisel._
5 import config._
6 import regmapper._
7 import uncore.tilelink2._
8 import util._
9
10 import sifive.blocks.util.{NonBlockingEnqueue, NonBlockingDequeue}
11
12 case class UARTParams(
13 address: BigInt,
14 dataBits: Int = 8,
15 stopBits: Int = 2,
16 divisorBits: Int = 16,
17 oversample: Int = 4,
18 nSamples: Int = 3,
19 nTxEntries: Int = 8,
20 nRxEntries: Int = 8)
21
22 trait HasUARTParameters {
23 def c: UARTParams
24 def uartDataBits = c.dataBits
25 def uartStopBits = c.stopBits
26 def uartDivisorBits = c.divisorBits
27
28 def uartOversample = c.oversample
29 def uartOversampleFactor = 1 << uartOversample
30 def uartNSamples = c.nSamples
31
32 def uartNTxEntries = c.nTxEntries
33 def uartNRxEntries = c.nRxEntries
34
35 require(uartDivisorBits > uartOversample)
36 require(uartOversampleFactor > uartNSamples)
37 }
38
39 abstract class UARTModule(val c: UARTParams)(implicit val p: Parameters)
40 extends Module with HasUARTParameters
41
42 class UARTPortIO extends Bundle {
43 val txd = Bool(OUTPUT)
44 val rxd = Bool(INPUT)
45 }
46
47 trait HasUARTTopBundleContents extends Bundle {
48 val port = new UARTPortIO
49 }
50
51 class UARTTx(c: UARTParams)(implicit p: Parameters) extends UARTModule(c)(p) {
52 val io = new Bundle {
53 val en = Bool(INPUT)
54 val in = Decoupled(Bits(width = uartDataBits)).flip
55 val out = Bits(OUTPUT, 1)
56 val div = UInt(INPUT, uartDivisorBits)
57 val nstop = UInt(INPUT, log2Up(uartStopBits))
58 }
59
60 val prescaler = Reg(init = UInt(0, uartDivisorBits))
61 val pulse = (prescaler === UInt(0))
62
63 private val n = uartDataBits + 1
64 val counter = Reg(init = UInt(0, log2Floor(n + uartStopBits) + 1))
65 val shifter = Reg(Bits(width = n))
66 val out = Reg(init = Bits(1, 1))
67 io.out := out
68
69 val busy = (counter =/= UInt(0))
70 io.in.ready := io.en && !busy
71 when (io.in.fire()) {
72 printf("%c", io.in.bits)
73 shifter := Cat(io.in.bits, Bits(0, 1))
74 counter := Mux1H((0 until uartStopBits).map(i =>
75 (io.nstop === UInt(i)) -> UInt(n + i + 1)))
76 }
77 when (busy) {
78 prescaler := Mux(pulse, io.div, prescaler - UInt(1))
79 }
80 when (pulse && busy) {
81 counter := counter - UInt(1)
82 shifter := Cat(Bits(1, 1), shifter >> 1)
83 out := shifter(0)
84 }
85 }
86
87 class UARTRx(c: UARTParams)(implicit p: Parameters) extends UARTModule(c)(p) {
88 val io = new Bundle {
89 val en = Bool(INPUT)
90 val in = Bits(INPUT, 1)
91 val out = Valid(Bits(width = uartDataBits))
92 val div = UInt(INPUT, uartDivisorBits)
93 }
94
95 val debounce = Reg(init = UInt(0, 2))
96 val debounce_max = (debounce === UInt(3))
97 val debounce_min = (debounce === UInt(0))
98
99 val prescaler = Reg(init = UInt(0, uartDivisorBits - uartOversample))
100 val start = Wire(init = Bool(false))
101 val busy = Wire(init = Bool(false))
102 val pulse = (prescaler === UInt(0)) && busy
103
104 when (busy) {
105 prescaler := prescaler - UInt(1)
106 }
107 when (start || pulse) {
108 prescaler := io.div >> uartOversample
109 }
110
111 val sample = Reg(Bits(width = uartNSamples))
112 val voter = Majority(sample.toBools.toSet)
113 when (pulse) {
114 sample := Cat(sample, io.in)
115 }
116
117 private val delay0 = (uartOversampleFactor + uartNSamples) >> 1
118 private val delay1 = uartOversampleFactor
119
120 val timer = Reg(UInt(width = uartOversample + 1))
121 val counter = Reg(UInt(width = log2Floor(uartDataBits) + 1))
122 val shifter = Reg(Bits(width = uartDataBits))
123 val expire = (timer === UInt(0)) && pulse
124
125 val sched = Wire(init = Bool(false))
126 when (pulse) {
127 timer := timer - UInt(1)
128 }
129 when (sched) {
130 timer := UInt(delay1-1)
131 }
132
133 val valid = Reg(init = Bool(false))
134 valid := Bool(false)
135 io.out.valid := valid
136 io.out.bits := shifter
137
138 val (s_idle :: s_start :: s_data :: Nil) = Enum(UInt(), 3)
139 val state = Reg(init = s_idle)
140
141 switch (state) {
142 is (s_idle) {
143 when (!(!io.in) && !debounce_min) {
144 debounce := debounce - UInt(1)
145 }
146 when (!io.in) {
147 debounce := debounce + UInt(1)
148 when (debounce_max) {
149 state := s_start
150 start := Bool(true)
151 timer := UInt(delay0-1)
152 }
153 }
154 }
155
156 is (s_start) {
157 busy := Bool(true)
158 when (expire) {
159 sched := Bool(true)
160 when (voter) {
161 state := s_idle
162 } .otherwise {
163 state := s_data
164 counter := UInt(uartDataBits)
165 }
166 }
167 }
168
169 is (s_data) {
170 busy := Bool(true)
171 when (expire) {
172 counter := counter - UInt(1)
173 when (counter === UInt(0)) {
174 state := s_idle
175 valid := Bool(true)
176 } .otherwise {
177 shifter := Cat(voter, shifter >> 1)
178 sched := Bool(true)
179 }
180 }
181 }
182 }
183
184 when (!io.en) {
185 debounce := UInt(0)
186 }
187 }
188
189 class UARTInterrupts extends Bundle {
190 val rxwm = Bool()
191 val txwm = Bool()
192 }
193
194 trait HasUARTTopModuleContents extends Module with HasUARTParameters with HasRegMap {
195 val io: HasUARTTopBundleContents
196 implicit val p: Parameters
197 def params: UARTParams
198 def c = params
199
200 val txm = Module(new UARTTx(params))
201 val txq = Module(new Queue(txm.io.in.bits, uartNTxEntries))
202
203 val rxm = Module(new UARTRx(params))
204 val rxq = Module(new Queue(rxm.io.out.bits, uartNRxEntries))
205
206 val divinit = p(diplomacy.DTSTimebase) * p(rocketchip.RTCPeriod) / 115200
207 val div = Reg(init = UInt(divinit, uartDivisorBits))
208
209 private val stopCountBits = log2Up(uartStopBits)
210 private val txCountBits = log2Floor(uartNTxEntries) + 1
211 private val rxCountBits = log2Floor(uartNRxEntries) + 1
212
213 val txen = Reg(init = Bool(false))
214 val rxen = Reg(init = Bool(false))
215 val txwm = Reg(init = UInt(0, txCountBits))
216 val rxwm = Reg(init = UInt(0, rxCountBits))
217 val nstop = Reg(init = UInt(0, stopCountBits))
218
219 txm.io.en := txen
220 txm.io.in <> txq.io.deq
221 txm.io.div := div
222 txm.io.nstop := nstop
223 io.port.txd := txm.io.out
224
225 rxm.io.en := rxen
226 rxm.io.in := io.port.rxd
227 rxq.io.enq <> rxm.io.out
228 rxm.io.div := div
229
230 val ie = Reg(init = new UARTInterrupts().fromBits(Bits(0)))
231 val ip = Wire(new UARTInterrupts)
232
233 ip.txwm := (txq.io.count < txwm)
234 ip.rxwm := (rxq.io.count > rxwm)
235 interrupts(0) := (ip.txwm && ie.txwm) || (ip.rxwm && ie.rxwm)
236
237 regmap(
238 UARTCtrlRegs.txfifo -> NonBlockingEnqueue(txq.io.enq),
239 UARTCtrlRegs.rxfifo -> NonBlockingDequeue(rxq.io.deq),
240
241 UARTCtrlRegs.txctrl -> Seq(
242 RegField(1, txen),
243 RegField(stopCountBits, nstop)),
244 UARTCtrlRegs.rxctrl -> Seq(RegField(1, rxen)),
245 UARTCtrlRegs.txmark -> Seq(RegField(txCountBits, txwm)),
246 UARTCtrlRegs.rxmark -> Seq(RegField(rxCountBits, rxwm)),
247
248 UARTCtrlRegs.ie -> Seq(
249 RegField(1, ie.txwm),
250 RegField(1, ie.rxwm)),
251
252 UARTCtrlRegs.ip -> Seq(
253 RegField.r(1, ip.txwm),
254 RegField.r(1, ip.rxwm)),
255
256 UARTCtrlRegs.div -> Seq(
257 RegField(uartDivisorBits, div))
258 )
259 }
260
261 // Magic TL2 Incantation to create a TL2 UART
262 class TLUART(w: Int, c: UARTParams)(implicit p: Parameters)
263 extends TLRegisterRouter(c.address, "serial", Seq("sifive,uart0"), interrupts = 1, beatBytes = w)(
264 new TLRegBundle(c, _) with HasUARTTopBundleContents)(
265 new TLRegModule(c, _, _) with HasUARTTopModuleContents)