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