Skip to content

Commit c4dd011

Browse files
committed
RFC #60: fix data stream signature and clock divisor.
1 parent 5f89cd4 commit c4dd011

File tree

1 file changed

+31
-31
lines changed

1 file changed

+31
-31
lines changed

text/0000-soc-uart-peripheral.md

+31-31
Original file line numberDiff line numberDiff line change
@@ -38,37 +38,37 @@ class MySoC(wiring.Component):
3838

3939
# Instantiate an UART peripheral:
4040

41-
uart_divisor = int(platform.default_clk_frequency / 115200)
41+
uart_divisor_cnt = int(platform.default_clk_frequency / 115200)
4242

43-
m.submodules.uart = uart = uart.Peripheral(divisor_init=uart_divisor, addr_width=8, data_width=8)
43+
m.submodules.uart = uart = uart.Peripheral(divisor_init=(uart_divisor_cnt, 0), addr_width=8, data_width=8)
4444

4545
# Instantiate and connect the UART PHYs:
4646

4747
uart_pins = platform.request("uart", 0)
4848

49-
uart_phy_rx = AsyncSerialRX(uart_divisor, divisor_bits=16, pins=uart_pins)
50-
uart_phy_tx = AsyncSerialTX(uart_divisor, divisor_bits=16, pins=uart_pins)
49+
uart_phy_rx = AsyncSerialRX(uart_divisor_cnt, divisor_bits=16, pins=uart_pins)
50+
uart_phy_tx = AsyncSerialTX(uart_divisor_cnt, divisor_bits=16, pins=uart_pins)
5151

5252
m.submodules.uart_phy_rx = uart_phy_rx
5353
m.submodules.uart_phy_tx = uart_phy_tx
5454

5555
m.d.comb += [
56-
uart_phy_rx.divisor.eq(uart.rx.divisor),
56+
uart_phy_rx.divisor.eq(uart.rx.divisor.cnt),
5757

58-
uart.rx.stream.data.eq(uart_phy_rx.data),
59-
uart.rx.stream.valid.eq(uart_phy_rx.rdy),
60-
uart_phy_rx.ack.eq(uart.stream.ready),
58+
uart.rx.data.payload.eq(uart_phy_rx.data),
59+
uart.rx.data.valid.eq(uart_phy_rx.rdy),
60+
uart_phy_rx.ack.eq(uart.rx.data.ready),
6161

6262
uart.rx.overflow.eq(uart_phy_rx.err.overflow),
6363
uart.rx.error.eq(uart_phy_rx.err.frame),
6464
]
6565

6666
m.d.comb += [
67-
uart_phy_tx.divisor.eq(uart.tx.divisor),
67+
uart_phy_tx.divisor.eq(uart.tx.divisor.cnt),
6868

69-
uart_phy_tx.data.eq(uart.tx.stream.data),
70-
uart_phy_tx.ack.eq(uart.tx.stream.valid),
71-
uart.tx.stream.ready.eq(uart_phy_tx.rdy),
69+
uart_phy_tx.data.eq(uart.tx.data.payload),
70+
uart_phy_tx.ack.eq(uart.tx.data.valid),
71+
uart.tx.data.ready.eq(uart_phy_tx.rdy),
7272
]
7373

7474
# Add the UART peripheral to a CSR bus decoder:
@@ -108,8 +108,8 @@ class MySoC(wiring.Component):
108108

109109
- If `Enable.en` is 0, `Divisor` is read-only.
110110

111-
- `Divisor.cnt` is initialized to `divisor_cnt_init`.
112-
- `Divisor.psc` is initialized to `divisor_psc_init`.
111+
- `Divisor.cnt` is initialized to `divisor_init[0]`.
112+
- `Divisor.psc` is initialized to `divisor_init[1]`.
113113

114114
Assuming a clock frequency of 100MHz, the receiver baudrate is computed like so:
115115

@@ -165,8 +165,8 @@ baudrate = ((1 << psc) * 100e6) // (cnt + 1)
165165

166166
- If `Enable.en` is 0, `Divisor` is read-only.
167167

168-
- `Divisor.cnt` is initialized to `divisor_cnt_init`.
169-
- `Divisor.psc` is initialized to `divisor_psc_init`.
168+
- `Divisor.cnt` is initialized to `divisor_init[0]`.
169+
- `Divisor.psc` is initialized to `divisor_init[1]`.
170170

171171
Assuming a clock frequency of 100MHz, the transmitter baudrate is computed like so:
172172

@@ -205,11 +205,11 @@ Its members are defined as follows:
205205

206206
```python3
207207
{
208-
"divisor": In(unsigned(20)),
209-
"stream": Out(wiring.Signature({
210-
"data": Out(unsigned(data_bits)),
211-
"valid": Out(unsigned(1)),
212-
"ready": In(unsigned(1)),
208+
"divisor": In(data.StructLayout({"cnt": unsigned(13), "psc": unsigned(3)})),
209+
"data": Out(wiring.Signature({
210+
"payload": Out(unsigned(data_bits)),
211+
"valid": Out(unsigned(1)),
212+
"ready": In(unsigned(1)),
213213
})),
214214
"overflow": Out(unsigned(1)),
215215
"error": Out(unsigned(1)),
@@ -225,11 +225,11 @@ Its members are defined as follows:
225225

226226
```python3
227227
{
228-
"divisor": In(unsigned(20)),
229-
"stream": In(wiring.Signature({
230-
"data": Out(unsigned(data_bits)),
231-
"valid": Out(unsigned(1)),
232-
"ready": In(unsigned(1)),
228+
"divisor": In(data.StructLayout({"cnt": unsigned(13), "psc": unsigned(3)})),
229+
"data": In(wiring.Signature({
230+
"payload": Out(unsigned(data_bits)),
231+
"valid": Out(unsigned(1)),
232+
"ready": In(unsigned(1)),
233233
})),
234234
}
235235
```
@@ -238,7 +238,7 @@ Its members are defined as follows:
238238

239239
The `uart.ReceiverPeripheral` class is a `wiring.Component` implementing the receiver of an UART peripheral, with:
240240
- a `.__init__(self, *, divisor_init, addr_width, data_width=8, name=None, data_bits=8)` constructor, where:
241-
* `divisor_init` is a positive integer used as initial value for `Divisor`. It is a 16-bit value, where the lower 13 bits are assigned to `Divisor.cnt`, and the upper 3 bits are assigned to `Divisor.psc` as a log2.
241+
* `divisor_init` is a tuple of two positive integers used as initial values for `Divisor.cnt` and `Divisor.psc` respectively.
242242
* `addr_width`, `data_width` and `name` are passed to a `csr.Builder`.
243243
* `data_bits` is a non-negative integer passed to `Data` and `ReceiverPHYSignature`.
244244
- a `.signature` property, that returns a `wiring.Signature` with the following members:
@@ -254,7 +254,7 @@ The `uart.ReceiverPeripheral` class is a `wiring.Component` implementing the rec
254254

255255
The `uart.TransmitterPeripheral` class is a `wiring.Component` implementing the transmitter of an UART peripheral, with:
256256
- a `.__init__(self, *, divisor_init, addr_width, data_width=8, name=None, data_bits=8)` constructor, where:
257-
* `divisor_init` is a positive integer used as initial value for `Divisor`. It is a 16-bit value, where the lower 13 bits are assigned to `Divisor.cnt`, and the upper 3 bits are assigned to `Divisor.psc` as a log2.
257+
* `divisor_init` is a tuple of two positive integers used as initial values for `Divisor.cnt` and `Divisor.psc` respectively.
258258
* `addr_width`, `data_width` and `name` are passed to a `csr.Builder`.
259259
* `data_bits` is a non-negative integer passed to `Data` and `TransmitterPHYSignature`.
260260
- a `.signature` property, that returns a `wiring.Signature` with the following members:
@@ -270,7 +270,7 @@ The `uart.TransmitterPeripheral` class is a `wiring.Component` implementing the
270270

271271
The `uart.Peripheral` class is a `wiring.Component` implementing an UART peripheral, with:
272272
- a `.__init__(self, *, divisor_init, addr_width, data_width=8, name=None, data_bits=8)` constructor, where:
273-
* `divisor_init` is a positive integer used as initial value for `Divisor`. It is a 16-bit value, where the lower 13 bits are assigned to `Divisor.cnt`, and the upper 3 bits are assigned to `Divisor.psc` as a log2.
273+
* `divisor_init` is a tuple of two positive integers used as initial values for `Divisor.cnt` and `Divisor.psc` respectively.
274274
* `addr_width`, `data_width` and `name` are passed to a `csr.Builder`. `addr_width` must be at least 1. The peripheral address space is split in two, with the lower half occupied by a `ReceiverPeripheral` and the upper by a `TransmitterPeripheral`.
275275
* `data_bits` is a non-negative integer passed to `ReceiverPeripheral`, `TransmitterPeripheral`, `ReceiverPHYSignature` and `TransmitterPHYSignature`.
276276

@@ -290,7 +290,7 @@ The `uart.Peripheral` class is a `wiring.Component` implementing an UART periphe
290290
- This design decouples the UART peripheral from its PHY, which must be provided by the user.
291291
- The receiver and transmitter have separate `Divider` registers, despite using identical values
292292
in most cases.
293-
- Configuring the baudrate through the `Divider` register requires knowledge of the clock frequency used by the peripheral.
293+
- Configuring the baudrate through the `Divisor` register requires knowledge of the clock frequency used by the peripheral.
294294

295295
## Rationale and alternatives
296296
[rationale-and-alternatives]: #rationale-and-alternatives
@@ -299,7 +299,7 @@ The `uart.Peripheral` class is a `wiring.Component` implementing an UART periphe
299299
- Decoupling the peripheral from the PHY allows flexibility in implementations. For example, it is easy to add FIFOs between the PHYs and the peripheral.
300300
- A standalone `ReceiverPeripheral` or `TransmitterPeripheral` can be instantiated.
301301

302-
- The choice of a 16-bit `Divisor` register with a 3-bit prescaler covers the most common frequency/baudrate combinations with an error rate (due to quantization) below 1%.
302+
- The choice of a 13-bit divisor with a 3-bit prescaler covers the most common frequency/baudrate combinations with an error rate (due to quantization) below 1%.
303303

304304
*TODO: a table showing frequency/baudrate combinations*
305305

0 commit comments

Comments
 (0)