Skip to content

Commit

Permalink
docs(brg): Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
nickelpro committed Nov 13, 2024
1 parent e4facee commit 78f8269
Showing 1 changed file with 32 additions and 73 deletions.
105 changes: 32 additions & 73 deletions docs/BaudRateGen.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
# Baud Rate Generator

A baud rate generator is a form of digital clock divider which generates a
target clock rate based on the input clock and the desired baudrate. PurdNyUart
provides three such generators:
* **BaudRateGen**: Produces a single pair of clocks based on parameterized input
clock, target baud, and oversample rate
* **BaudRateGen4**: Produces one-of-four pairs of clocks based on parameters
* **BaudRateGenVar**: Produces a configurable pair of clocks based on a counter
input
target transmitter and receiver clock rate based on the input clock,
desired baudrate, and desired oversample.

## Contents
* [Parameters](#parameters)
Expand All @@ -18,83 +13,47 @@ provides three such generators:
* [Synchronization](#synchronization)

## Parameters
| Name | Default | Modules | Description |
| :--: | :-----: | :-----: | :---------: |
| `ClockRate` | 50 * 10<sup>6</sup> | Gen/Gen4 | The input system clock rate |
| `MaxClockRate` | 100 * 10<sup>6</sup> | GenVar | Maximum input system clock rate |
| `BaudRate` | 115200 | Gen | Target output baud rate |
| `MinBaudRate` | 9600 | GenVar | Minimum output baud rate |
| `Oversample` | 16 | All | Receiver clock multiplier |
| `Baud1` | 9600 | Gen4 | Target baud rate for `sel == 0` |
| `Baud2` | 38400 | Gen4 | Target baud rate for `sel == 1` |
| `Baud3` | 57600 | Gen4 | Target baud rate for `sel == 2` |
| `Baud4` | 115200 | Gen4 | Target baud rate for `sel == 3` |
| Name | Default | Description |
| :--: | :-----: | :---------: |
| `MaxClockRate` | 100 * 10<sup>6</sup> | Maximum input system clock rate |
| `MinBaudRate` | 9600 | Minimum output baud rate |
| `Oversample` | 16 | Receiver clock multiplier |

## Inputs
| Name | Width | Modules | Description |
| :--: | :---: | :-----: | :---------: |
| `clk` | 1 | All | Input clock |
| `nReset` | 1 | All | Asynchronous active-low reset |
| `phase` | 1 | All | Start phase of output clocks |
| `sel` | 2 | Gen4 | Baud rate selection |
| `count` | var[^1] | GenVar | Clock division counter |
| Name | Width | Description |
| :--: | :---: | :---------: |
| `clk` | 1 | Input clock |
| `nReset` | 1 | Asynchronous active-low reset |
| `syncReset` | 1 | Synchronous active-high reset |
| `phase` | 1 | Start phase of output clocks |
| `rate` | var[^1] | Clock division counter |

[^1]: `$clog2(MaxClockRate / (2 * MinBaudRate))`
[^1]: `$clog2(MaxClockRate / MinBaudRate)`

## Outputs

| Name | Width | Modules | Description |
| :--: | :---: | :-----: | :---------: |
| `rxClk` | 1 | All | Receiver clock |
| `txClk` | 1 | All | Transmitter clock |
| Name | Width | Description |
| :--: | :---: | :---------: |
| `rxClk` | 1 | Receiver clock |
| `txClk` | 1 | Transmitter clock |

## Functionality

### Basics

Consider a baud generator with a clock of 10Mhz, target rate of 115200 Baud,
and an oversample of 16x.
The `rate` input represents the period of the `txClk`. Put another way, it's a
simple counter that sets the `txClk` to `[~phase]` every `[rate]` clock ticks.

The length of each half-period of the receiver clock can be calculated with the
following formula:
The `rxClk` will have `[Oversample]` number of `[~phase]` edges every `txClk`
period. The period of the `rxClk` is referred to as the `rxRate`. These edges
will be evenly spaced within the `txClk` period, with the goal of the
`[Oversample / 2]`<sup>th</sup> edge being directly in the center of the
`txClk` period.

```
RxCycles = (ClockRate // (2 * BaudRate * Oversample)) + 1 = 3
```
This is achieved with two "wait" zones, the `preWait` zone and the `postWait`
zone, which account for the indivisble remainder of the `rate` divided by the
`Oversample`. Each wait zone is about half of the remainder.

**Note**: This is essential a ceiling operation, but even a perfectly divisible
`ClockRate` will result in the extra +1 cycle due to how the divider is
implemented.

Similarly, the length of the half-period of the transmitter clock can be
calculated with:

```
TxCycles = (ClockRate // (2 * BaudRate)) + 1 = 44
```

The resulting `rxClk` is illustrated below:

<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://svg.wavedrom.com/github/NYU-Processor-Design/PurdNyUart/main/docs/waveforms/rxClkDark.json">
<img src="https://svg.wavedrom.com/github/NYU-Processor-Design/PurdNyUart/main/docs/waveforms/rxClkLight.json">
</picture>

`txClk` is the same except with an 88 cycle period.

### Synchronization

`rxClk` is synchronized to `txClk`, it will hold on half-periods to ensure that
its overall period is an even division of `txClk`.

For example, if `rxCycles` is 3 and `txCycles` is 7 the resulting waveform
would be:

<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://svg.wavedrom.com/github/NYU-Processor-Design/PurdNyUart/main/docs/waveforms/syncDark.json">
<img src="https://svg.wavedrom.com/github/NYU-Processor-Design/PurdNyUart/main/docs/waveforms/syncLight.json">
</picture>

Note that the positive half-period of `rxClk` is held for an extra `clk` cycle
to match the half-period of `txClk`. This ensures the overall baud rate of
the receiver and transmitter are the same.
Additionally, the `rxClk` is shifted a half-period (ie, `rxRate / 2`) left
within the overall `txClk` period, to further center the sampling. This shift is
referred to as the `offset` within the rate calculations.

0 comments on commit 78f8269

Please sign in to comment.