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