<<<
:sectnums:
==== Pulse-Width Modulation Controller (PWM)

[cols="<3,<3,<4"]
[grid="none"]
|=======================
| Hardware source files:  | neorv32_pwm.vhd |
| Software driver files:  | neorv32_pwm.c   | link:https://stnolting.github.io/neorv32/sw/neorv32__pwm_8c.html[Online software reference (Doxygen)]
|                         | neorv32_pwm.h   | link:https://stnolting.github.io/neorv32/sw/neorv32__pwm_8h.html[Online software reference (Doxygen)]
| Top entity ports:       | `pwm_o`         | PWM output channels (32-bit)
| Configuration generics: | `IO_PWM_NUM`    | number of PWM channels to implement (0..32)
| CPU interrupts:         | none            |
|=======================

**Key Features**

* Up to 32 individual channels with up to 16-bit resolution and programmable polarity
* Fast-PWM mode operation with counter-compare and counter-wrap registers
* Toggle-free 0% and 100% duty cycle output rates
* Global clock prescaler


**Overview**

The PWM module implements a fast-PWM mode pulse-width modulation controller with up to 32 independent channels.
Period length (and thus, the carrier frequency), duty cycle, and polarity can be programmed individually for each
channel. However, the clock for the PWM counter increment is defined by a single global clock prescaler. PWM
operation is based on 16-bit wide period counters that are constrained by programmable wrapping values.

The total number of implemented channels is defined by the `IO_PWM_NUM` generic. The PWM output signal `pwm_o` has
a static size of 32 bit. Channel 0 corresponds to bit 0, channel 1 to bit 1 and so on. If less than 32 channels
are configured, only the LSB-aligned channel bits are connected while the remaining ones are hardwired to zero.


**Theory of Operation**

The PWM module provides several interface registers: an `ENABLE` register, a `POLARITY` registers, a `CLKPRSC`
register and up to 32 `CHANNEL[i]` registers.

The `ENABLE` register is used to enable PWM channels. This can be done individually (only one channel) or by using
bit-mask to enable several channels at once so they operate in perfect lockstep mode. Disabling a channel will clear
the channel's PWM counter ans will also bring the according PWM output to the _idle polarity_. Note that only the
lowest `IO_PWM_NUM` bit are implemented.

The `POLARITY` register defines the _idle polarity_ of the PWM channels. When a channel is disabled, this polarity
also defines the logic level of the according `pwm_o` output. Note that only the lowest `IO_PWM_NUM` bit are
implemented.

The `CLKPRSC` register configures the _global_ clock prescaler that is used for the PWM counter increment of each
channel. Eight pre-defined prescaler values are available:

.PWM prescaler configuration
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
[options="header",grid="rows"]
|=======================
| **`CLKPRSC`**               | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
| Resulting `clock_prescaler` |       2 |       4 |       8 |      64 |     128 |    1024 |    2048 |    4096
|=======================

The duty cycle and period length of each channel are defined by the according `CHANNEL[i]` register (with `i` =
`0 .. IO_PWM_NUM`). This register is split in two half-words: the lowest half-word defines the counter-compare
value (`CMP`) while the upper half-word defines the counter-wrap value (`TOP`).

.`CHANNEL` Half-Word Access
[TIP]
In contrast to many other NEORV32 peripherals, the PWM `CHANNEL[i]` registers can also be accessed using half-word
load/store operation. This allows to update the `TOP` and `CMP` sub-registers with a single instruction.

PWM operation is based on a 16-bit counter that increments with the globally pre-scaled processor clock resulting
in a sawtooth-like waveform. The counter will wrap around to all-zero when reaching the value defined by the `TOP`
sub-register. Whenever the counter value is less than the value defined by the `CMP` sub-register the PWM output
is set to the _inverted_ idle polarity.

.Fast-PWM Operation
----
TOP[i] --------------------/|--------------/|--------------/|--------------/|
                         /  |            /  |            /  |            /  |
                       /    |          /    |          /    |          /    |
CMP[i] --------------/------|--------/------|--------/------|--------/------|
                   / .      |      / .      |      / .      |      / .      |
                 /   .      |    /   .      |    /   .      |    /   .      |
               /     .      |  /     .      |  /     .      |  /     .      |
         ___ /       .      |/       .      |/       .      |/       .      |
            .        .      .        .      .        .      .        .      .
            .        .      .        .      .        .      .        .      .
            +--------+      +--------+      +--------+      +--------+      +
pwm_o[i]    |        |      |        |      |        |      |        |      | (POLARITY[i] = 0)
         ---+        +------+        +------+        +------+        +------+
            .        .      .        .      .        .      .        .      .
            .        .      .        .      .        .      .        .      .
         ---+        +------+        +------+        +------+        +------+
pwm_o[i]    |        |      |        |      |        |      |        |      | (POLARITY[i] = 1)
            +--------+      +--------+      +--------+      +--------+      +
----

Hence, the duty cycle of a channel is defined by the `TOP` and `CMP` register values:

_Duty Cycle[i]_ = 100% * (`CMP[i]` / (`TOP[i] + 1`))

The NEORV32 PWM module supports toggle-free 0% and 100% duty cycle output rates. 0% duty cycle is achieved by
setting `CMP = 0`. 100% duty cycle is achieved by setting `CMP = TOP + 1`.

Based on the global clock prescaler and the `TOP` wrap value, the carrier frequency of a channel is defined by the
following formula (_f~main~_ is the main clock frequency of the processor; `clock_prescaler` is the pre-scaling
factor according to the selected `CLKPRSC` value):

_f~PWM~[i]_ = _f~main~_ / (`clock_prescaler` * (`TOP[i]` + 1))


**Register Map**

.PWM register map (`struct NEORV32_PWM`)
[cols="<4,<2,<3,^2,<8"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
| `0xfff00000` | `ENABLE`             | `31:0` | r/w | Channel enable, one bit per channel
| `0xfff00004` | `POLARITY`           | `31:0` | r/w | Channel idle polarity level, one bit per channel
| `0xfff00008` | `CLKPRSC`            | `2:0`  | r/w | Global clock prescaler select
| `0xfff00080` | `CHANNEL[0].TOPCMP`  | `31:0` | r/w | Channel 0 full word access
| `0xfff00080` | `CHANNEL[0].CMP`     | `15:0` | r/w | Channel 0 top/wrap value register
| `0xfff00082` | `CHANNEL[0].TOP`     | `15:0` | r/w | Channel 0 compare value register
| ...          | ...                  |  ...   | r/w | ...
| `0xfff000fc` | `CHANNEL[31].TOPCMP` | `31:0` | r/w | Channel 31 full word access
| `0xfff000fc` | `CHANNEL[31].CMP`    | `15:0` | r/w | Channel 31 top/wrap value register
| `0xfff000fe` | `CHANNEL[31].TOP`    | `15:0` | r/w | Channel 31 compare value register
|=======================
