OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [docs/] [datasheet/] [soc_pwm.adoc] - Blame information for rev 70

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 60 zero_gravi
<<<
2
:sectnums:
3
==== Pulse-Width Modulation Controller (PWM)
4
 
5
[cols="<3,<3,<4"]
6
[frame="topbot",grid="none"]
7
|=======================
8
| Hardware source file(s): | neorv32_pwm.vhd |
9
| Software driver file(s): | neorv32_pwm.c |
10
|                          | neorv32_pwm.h |
11 70 zero_gravi
| Top entity port:         | `pwm_o` | up to 60 PWM output channels (60-bit, fixed)
12 60 zero_gravi
| Configuration generics:  | _IO_PWM_NUM_CH_ | number of PWM channels to implement (0..60)
13
| CPU interrupts:          | none |
14
|=======================
15
 
16
The PWM controller implements a pulse-width modulation controller with up to 60 independent channels and 8-
17
bit resolution per channel. The actual number of implemented channels is defined by the _IO_PWM_NUM_CH_ generic.
18
Setting this generic to zero will completely remove the PWM controller from the design.
19
 
20 70 zero_gravi
[NOTE]
21
The `pwm_o` has a static size of 60-bit. Is less than 60 PWM channels are configured, only the LSB-aligned channels
22
(bits) are used while the remaining bits are hardwired to zero.
23
 
24 60 zero_gravi
The PWM controller is based on an 8-bit base counter with a programmable threshold comparators for each channel
25
that defines the actual duty cycle. The controller can be used to drive fancy RGB-LEDs with 24-
26
bit true color, to dim LCD back-lights or even for "analog" control. An external integrator (RC low-pass filter)
27
can be used to smooth the generated "analog" signals.
28
 
29
**Theory of Operation**
30
 
31 64 zero_gravi
The PWM controller is activated by setting the _PWM_CTRL_EN_ bit in the module's control register `CTRL`. When this
32 60 zero_gravi
bit is cleared, the unit is reset and all PWM output channels are set to zero.
33
The 8-bit duty cycle for each channel, which represents the channel's "intensity", is defined via an 8-bit value. The module
34 64 zero_gravi
provides up to 15 duty cycle registers `DUTY[0]` to `DUTY[14]` (depending on the number of implemented channels).
35 60 zero_gravi
Each register contains the duty cycle configuration for 4 consecutive channels. For example, the duty cycle of channel 0
36 64 zero_gravi
is defined via bits 7:0 in `DUTY[0]`. The duty cycle of channel 2 is defined via bits 15:0 in `DUTY[0]`.
37
Channel 4's duty cycle is defined via bits 7:0 in `DUTY[1]` and so on.
38 60 zero_gravi
 
39
[NOTE]
40
Regardless of the configuration of _IO_PWM_NUM_CH_ all module registers can be accessed without raising an exception.
41
Software can discover the number of available channels by writing 0xff to all duty cycle configuration bytes and
42
reading those values back. The duty-cycle of channels that were not implemented always reads as zero.
43
 
44
Based on the configured duty cycle the according intensity of the channel can be computed by the following formula:
45
 
46 64 zero_gravi
_**Intensity~x~**_ = `DUTY[y](i*8+7 downto i*8)` / (2^8^)
47 60 zero_gravi
 
48
The base frequency of the generated PWM signals is defined by the PWM core clock. This clock is derived
49 64 zero_gravi
from the main processor clock and divided by a prescaler via the 3-bit PWM_CTRL_PRSCx in the unit's control
50 66 zero_gravi
register. The following pre-scalers are available:
51 60 zero_gravi
 
52
.PWM prescaler configuration
53
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
54
[options="header",grid="rows"]
55
|=======================
56 64 zero_gravi
| **`PWM_CTRL_PRSCx`**        | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
57 60 zero_gravi
| Resulting `clock_prescaler` |       2 |       4 |       8 |      64 |     128 |    1024 |    2048 |    4096
58
|=======================
59
 
60
The resulting PWM base frequency is defined by:
61
 
62
_**f~PWM~**_ = _f~main~[Hz]_ / (2^8^ * `clock_prescaler`)
63
 
64
<<<
65 64 zero_gravi
.PWM register map (`struct neorv32_pwm_t`)
66 60 zero_gravi
[cols="<4,<4,<6,^2,<8"]
67
[options="header",grid="all"]
68
|=======================
69
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
70 64 zero_gravi
.4+<| `0xfffffe80` .4+<| `NEORV32_PWM.CTRL` <|`0` _PWM_CTRL_EN_    ^| r/w | PWM enable
71
                                            <|`1` _PWM_CTRL_PRSC0_ ^| r/w .3+<| 3-bit clock prescaler select
72
                                            <|`2` _PWM_CTRL_PRSC1_ ^| r/w
73
                                            <|`3` _PWM_CTRL_PRSC2_ ^| r/w
74
.4+<| `0xfffffe84` .4+<| `NEORV32_PWM.DUTY[0]`  <|`7:0`   ^| r/w <| 8-bit duty cycle for channel 0
75
                                                <|`15:8`  ^| r/w <| 8-bit duty cycle for channel 1
76
                                                <|`23:16` ^| r/w <| 8-bit duty cycle for channel 2
77
                                                <|`31:24` ^| r/w <| 8-bit duty cycle for channel 3
78
| ...     | ...      | ...                       | r/w | ...
79
.4+<| `0xfffffebc` .4+<| `NEORV32_PWM.DUTY[14]` <|`7:0`   ^| r/w <| 8-bit duty cycle for channel 56
80
                                                <|`15:8`  ^| r/w <| 8-bit duty cycle for channel 57
81
                                                <|`23:16` ^| r/w <| 8-bit duty cycle for channel 58
82
                                                <|`31:24` ^| r/w <| 8-bit duty cycle for channel 59
83 60 zero_gravi
|=======================

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.