mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-23 13:47:33 -04:00
Merge branch 'main' into linty_test
This commit is contained in:
commit
450a1662b0
50 changed files with 413 additions and 344 deletions
4
.github/workflows/Documentation.yml
vendored
4
.github/workflows/Documentation.yml
vendored
|
@ -4,11 +4,11 @@ on:
|
|||
push:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/**'
|
||||
- '.github/workflows/Documentation.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/**'
|
||||
- '.github/workflows/Documentation.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
|
4
.github/workflows/Processor.yml
vendored
4
.github/workflows/Processor.yml
vendored
|
@ -6,13 +6,13 @@ on:
|
|||
- 'rtl/**'
|
||||
- 'sw/**'
|
||||
- 'sim/**'
|
||||
- '.github/workflows/**'
|
||||
- '.github/workflows/Processor.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'rtl/**'
|
||||
- 'sw/**'
|
||||
- 'sim/**'
|
||||
- '.github/workflows/**'
|
||||
- '.github/workflows/Processor.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
|
|
@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
|
|||
|
||||
| Date | Version | Comment | Ticket |
|
||||
|:----:|:-------:|:--------|:------:|
|
||||
| 06.10.2024 | 1.10.5.4 | :warning: rework PWM module | [#1049](https://github.com/stnolting/neorv32/pull/1049) |
|
||||
| 05.10.2024 | 1.10.5.3 | upgrade neoTRNG to version 3.2 | [#1048](https://github.com/stnolting/neorv32/pull/1048) |
|
||||
| 03.10.2024 | 1.10.5.2 | :warning: remove `A` ISA extensions; replaced by new `Zalrsc` ISA extension | [#1047](https://github.com/stnolting/neorv32/pull/1047) |
|
||||
| 02.10.2024 | 1.10.5.1 | :warning: rework CFU interface; reduce minimal latency of CFU instructions from 4 cycles to 3 cycles | [#1046](https://github.com/stnolting/neorv32/pull/1046) |
|
||||
|
@ -57,7 +58,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
|
|||
| 05.09.2024 | 1.10.3.1 | minor CPU RTL cleanups and optimizations | [#1004](https://github.com/stnolting/neorv32/pull/1004) |
|
||||
| 03.09.2024 | [**:rocket:1.10.3**](https://github.com/stnolting/neorv32/releases/tag/v1.10.3) | **New release** | |
|
||||
| 30.08.2024 | 1.10.2.9 | :bug: fix PC reset bug (introduced in v1.10.2.8); minor RTL optimizations (size and critical path) | [#998](https://github.com/stnolting/neorv32/pull/998) |
|
||||
| 25.08.2024 | 1.10.2.8 | :warning: remove user-mode HPM counters; add individual `mocuntern` bits (`CY` and `IR`) rework Vivado IP module; minor RTL cleanups and optimization | [#996](https://github.com/stnolting/neorv32/pull/996) |
|
||||
| 25.08.2024 | 1.10.2.8 | :warning: remove user-mode HPM counters; add individual `mocunteren` bits (`CY` and `IR`) rework Vivado IP module; minor RTL cleanups and optimization | [#996](https://github.com/stnolting/neorv32/pull/996) |
|
||||
| 16.08.2024 | 1.10.2.7 | minor CPU area and critical path optimizations; minor code cleanups | [#990](https://github.com/stnolting/neorv32/pull/990) |
|
||||
| 09.08.2024 | 1.10.2.6 | :warning: re-organize RTL files; all core files are now located in `rtl/core`; remove `mem` sub-folder | [#985](https://github.com/stnolting/neorv32/pull/985) |
|
||||
| 09.08.2024 | 1.10.2.5 | minor HDL edits | [#984](https://github.com/stnolting/neorv32/pull/984) |
|
||||
|
|
|
@ -98,8 +98,8 @@ setup according to your needs. Note that all of the following SoC modules are en
|
|||
**CPU Core**
|
||||
|
||||
* [](https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md)
|
||||
* 32-bit little-endian RISC-V single-core, pipelined/multi-cycle modified Harvard architecture
|
||||
* configurable ISA extensions:
|
||||
* RISC-V 32-bit little-endian single-core pipelined/multi-cycle modified Harvard architecture
|
||||
* configurable [instruction sets and extensions](https://stnolting.github.io/neorv32/#_instruction_sets_and_extensions):
|
||||
\
|
||||
`RV32`
|
||||
[[`I`](https://stnolting.github.io/neorv32/#_i_isa_extension)/[`E`](https://stnolting.github.io/neorv32/#_e_isa_extension)]
|
||||
|
|
|
@ -425,38 +425,38 @@ This chapter gives a brief overview of all available ISA extensions.
|
|||
|=======================
|
||||
| Name | Description | <<_processor_top_entity_generics, Enabled by Generic>>
|
||||
| <<_b_isa_extension,`B`>> | Bit manipulation instructions | _Implicitly_ enabled
|
||||
| <<_c_isa_extension,`C`>> | Compressed (16-bit) instructions | `RISCV_ISA_C`
|
||||
| <<_e_isa_extension,`E`>> | Embedded CPU extension (reduced register file size) | `RISCV_ISA_E`
|
||||
| <<_c_isa_extension,`C`>> | Compressed (16-bit) instructions | <<_processor_top_entity_generics, `RISCV_ISA_C`>>
|
||||
| <<_e_isa_extension,`E`>> | Embedded CPU extension (reduced register file size) | <<_processor_top_entity_generics, `RISCV_ISA_E`>>
|
||||
| <<_i_isa_extension,`I`>> | Integer base ISA | Enabled if `RISCV_ISA_E` is **not** enabled
|
||||
| <<_m_isa_extension,`M`>> | Integer multiplication and division instructions | `RISCV_ISA_M`
|
||||
| <<_u_isa_extension,`U`>> | Less-privileged _user_ mode extension | `RISCV_ISA_U`
|
||||
| <<_m_isa_extension,`M`>> | Integer multiplication and division instructions | <<_processor_top_entity_generics, `RISCV_ISA_M`>>
|
||||
| <<_u_isa_extension,`U`>> | Less-privileged _user_ mode extension | <<_processor_top_entity_generics, `RISCV_ISA_U`>>
|
||||
| <<_x_isa_extension,`X`>> | Platform-specific / NEORV32-specific extension | Always enabled
|
||||
| <<_zalrsc_isa_extension,`Zalrsc`>> | Atomic reservation-set instructions | `RISCV_ISA_Zalrsc`
|
||||
| <<_zba_isa_extension,`Zba`>> | Shifted-add bit manipulation instructions | `RISCV_ISA_Zba`
|
||||
| <<_zbb_isa_extension,`Zbb`>> | Basic bit manipulation instructions | `RISCV_ISA_Zbb`
|
||||
| <<_zbkb_isa_extension,`Zbkb`>> | Scalar cryptographic bit manipulation instructions | `RISCV_ISA_Zbkb`
|
||||
| <<_zbkc_isa_extension,`Zbkc`>> | Scalar cryptographic carry-less multiplication instructions | `RISCV_ISA_Zbkc`
|
||||
| <<_zbkx_isa_extension,`Zbkx`>> | Scalar cryptographic crossbar permutation instructions | `RISCV_ISA_Zbkx`
|
||||
| <<_zbs_isa_extension,`Zbs`>> | Single-bit bit manipulation instructions | `RISCV_ISA_Zbs`
|
||||
| <<_zfinx_isa_extension,`Zfinx`>> | Floating-point instructions using integer registers | `RISCV_ISA_Zfinx`
|
||||
| <<_zalrsc_isa_extension,`Zalrsc`>> | Atomic reservation-set instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zalrsc`>>
|
||||
| <<_zba_isa_extension,`Zba`>> | Shifted-add bit manipulation instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zba`>>
|
||||
| <<_zbb_isa_extension,`Zbb`>> | Basic bit manipulation instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zbb`>>
|
||||
| <<_zbkb_isa_extension,`Zbkb`>> | Scalar cryptographic bit manipulation instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zbkb`>>
|
||||
| <<_zbkc_isa_extension,`Zbkc`>> | Scalar cryptographic carry-less multiplication instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zbkc`>>
|
||||
| <<_zbkx_isa_extension,`Zbkx`>> | Scalar cryptographic crossbar permutation instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zbkx`>>
|
||||
| <<_zbs_isa_extension,`Zbs`>> | Single-bit bit manipulation instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zbs`>>
|
||||
| <<_zfinx_isa_extension,`Zfinx`>> | Floating-point instructions using integer registers | <<_processor_top_entity_generics, `RISCV_ISA_Zfinx`>>
|
||||
| <<_zifencei_isa_extension,`Zifencei`>> | Instruction stream synchronization instruction | Always enabled
|
||||
| <<_zicntr_isa_extension,`Zicntr`>> | Base counters extension | `RISCV_ISA_Zicntr`
|
||||
| <<_zicond_isa_extension,`Zicond`>> | Integer conditional operations | `RISCV_ISA_Zicond`
|
||||
| <<_zicntr_isa_extension,`Zicntr`>> | Base counters extension | <<_processor_top_entity_generics, `RISCV_ISA_Zicntr`>>
|
||||
| <<_zicond_isa_extension,`Zicond`>> | Integer conditional operations | <<_processor_top_entity_generics, `RISCV_ISA_Zicond`>>
|
||||
| <<_zicsr_isa_extension,`Zicsr`>> | Control and status register access instructions | Always enabled
|
||||
| <<_zihpm_isa_extension,`Zihpm`>> | Hardware performance monitors extension | `RISCV_ISA_Zihpm`
|
||||
| <<_zihpm_isa_extension,`Zihpm`>> | Hardware performance monitors extension | <<_processor_top_entity_generics, `RISCV_ISA_Zihpm`>>
|
||||
| <<_zkn_isa_extension,`Zkn`>> | Scalar cryptographic NIST algorithm suite | _Implicitly_ enabled
|
||||
| <<_zknd_isa_extension,`Zknd`>> | Scalar cryptographic NIST AES decryption instructions | `RISCV_ISA_Zknd`
|
||||
| <<_zkne_isa_extension,`Zkne`>> | Scalar cryptographic NIST AES encryption instructions | `RISCV_ISA_Zkne`
|
||||
| <<_zknh_isa_extension,`Zknh`>> | Scalar cryptographic NIST hash function instructions | `RISCV_ISA_Zknh`
|
||||
| <<_zknd_isa_extension,`Zknd`>> | Scalar cryptographic NIST AES decryption instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zknd`>>
|
||||
| <<_zkne_isa_extension,`Zkne`>> | Scalar cryptographic NIST AES encryption instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zkne`>>
|
||||
| <<_zknh_isa_extension,`Zknh`>> | Scalar cryptographic NIST hash function instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zknh`>>
|
||||
| <<_zkt_isa_extension,`Zkt`>> | Data independent execution time (of cryptographic operations) | _Implicitly_ enabled
|
||||
| <<_zks_isa_extension,`Zks`>> | Scalar cryptographic ShangMi algorithm suite | _Implicitly_ enabled
|
||||
| <<_zksed_isa_extension,`Zksed`>> | Scalar cryptographic ShangMi block cypher instructions | `RISCV_ISA_Zksed`
|
||||
| <<_zksh_isa_extension,`Zksh`>> | Scalar cryptographic ShangMi hash instructions | `RISCV_ISA_Zksh`
|
||||
| <<_zmmul_isa_extension,`Zmmul`>> | Integer multiplication-only instructions | `RISCV_ISA_Zmmul`
|
||||
| <<_zxcfu_isa_extension,`Zcfu`>> | Custom / user-defined instructions | `RISCV_ISA_Zxcfu`
|
||||
| <<_smpmp_isa_extension,`Smpmp`>> | Physical memory protection (PMP) extension | `RISCV_ISA_Smpmp`
|
||||
| <<_sdext_isa_extension,`Sdext`>> | External debug support extension | `ON_CHIP_DEBUGGER_EN`
|
||||
| <<_sdtrig_isa_extension,`Sdtrig`>> | Trigger module extension | `ON_CHIP_DEBUGGER_EN`
|
||||
| <<_zksed_isa_extension,`Zksed`>> | Scalar cryptographic ShangMi block cypher instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zksed`>>
|
||||
| <<_zksh_isa_extension,`Zksh`>> | Scalar cryptographic ShangMi hash instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zksh`>>
|
||||
| <<_zmmul_isa_extension,`Zmmul`>> | Integer multiplication-only instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zmmul`>>
|
||||
| <<_zxcfu_isa_extension,`Zcfu`>> | Custom / user-defined instructions | <<_processor_top_entity_generics, `RISCV_ISA_Zxcfu`>>
|
||||
| <<_smpmp_isa_extension,`Smpmp`>> | Physical memory protection (PMP) extension | <<_processor_top_entity_generics, `RISCV_ISA_Smpmp`>>
|
||||
| <<_sdext_isa_extension,`Sdext`>> | External debug support extension | <<_processor_top_entity_generics, `ON_CHIP_DEBUGGER_EN`>>
|
||||
| <<_sdtrig_isa_extension,`Sdtrig`>> | Trigger module extension | <<_processor_top_entity_generics, `ON_CHIP_DEBUGGER_EN`>>
|
||||
|=======================
|
||||
|
||||
.RISC-V ISA Specification
|
||||
|
@ -603,7 +603,7 @@ RISC-V specs. Also, custom trap codes for <<_mcause>> are implemented.
|
|||
|
||||
The `Zalrsc` ISA extension is a sub-extension of the RISC-V _atomic memory access_ (`A`) ISA extension and includes
|
||||
instructions for reservation-set operations (load-reservate `lr` and store-conditional `sc`) only.
|
||||
It is enabled by the top's `RISCV_ISA_Zalrsc` generic.
|
||||
It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zalrsc`>> generic.
|
||||
|
||||
.AMO / `A` Emulation
|
||||
[NOTE]
|
||||
|
@ -712,7 +712,7 @@ User-level access to the counter CSRs can be constrained by the <<_mcounteren>>
|
|||
==== `Zicond` ISA Extension
|
||||
|
||||
The `Zicond` ISA extension adds integer conditional move primitives that allow to implement branch-less
|
||||
control flows. It is enabled by the top's `RISCV_ISA_Zicond` generic.
|
||||
control flows. It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zicond`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_cond.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -768,8 +768,9 @@ The event-driven increment of the HPMs can be deactivated individually via the <
|
|||
==== `Zba` ISA Extension
|
||||
|
||||
The `Zba` sub-extension is part of the _RISC-V bit manipulation_ ISA specification (<<_b_isa_extension>>)
|
||||
and adds shifted-add / address-generation instructions. It is enabled by the top's `RISCV_ISA_Zba` generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_bitmanip.vhd`).
|
||||
and adds shifted-add / address-generation instructions. It is enabled by the top's
|
||||
<<_processor_top_entity_generics, `RISCV_ISA_Zba`>> generic. This ISA extension is implemented as multi-cycle
|
||||
ALU co-processor (`rtl/core/neorv32_cpu_cp_bitmanip.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
[cols="<2,<4,<3"]
|
||||
|
@ -783,8 +784,8 @@ This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neo
|
|||
==== `Zbb` ISA Extension
|
||||
|
||||
The `Zbb` sub-extension is part of the _RISC-V bit manipulation_ ISA specification (<<_b_isa_extension>>)
|
||||
and adds the basic bit manipulation instructions. It is enabled by the top's `RISCV_ISA_Zbb` generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_bitmanip.vhd`).
|
||||
and adds the basic bit manipulation instructions. It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zbb`>>
|
||||
generic. This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_bitmanip.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
[cols="<5,<4,<5"]
|
||||
|
@ -810,7 +811,7 @@ configuration option that will replace the (time-variant) bit-serial shifter by
|
|||
==== `Zbs` ISA Extension
|
||||
|
||||
The `Zbs` sub-extension is part of the _RISC-V bit manipulation_ ISA specification (<<_b_isa_extension>>)
|
||||
and adds single-bit operations. It is enabled by the top's `RISCV_ISA_Zbs` generic.
|
||||
and adds single-bit operations. It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zbs`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_bitmanip.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -824,7 +825,7 @@ This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neo
|
|||
==== `Zbkb` ISA Extension
|
||||
|
||||
The `Zbkb` sub-extension is part of the _RISC-V scalar cryptography_ ISA specification and extends the _RISC-V bit manipulation_
|
||||
ISA extension with additional instructions. It is enabled by the top's `RISCV_ISA_Zbkb` generic.
|
||||
ISA extension with additional instructions. It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zbkb`>> generic.
|
||||
Note that enabling this extension will also enable the `Zbb` basic bit-manipulation ISA extension (which is extended by `Zknb`).
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_bitmanip.vhd`).
|
||||
|
||||
|
@ -842,7 +843,7 @@ This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neo
|
|||
==== `Zbkc` ISA Extension
|
||||
|
||||
The `Zbkc` sub-extension is part of the _RISC-V scalar cryptography_ ISA extension and adds carry-less multiplication instruction.
|
||||
ISA extension with additional instructions. It is enabled by the top's `RISCV_ISA_Zbkc` generic.
|
||||
ISA extension with additional instructions. It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zbkc`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_bitmanip.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -857,7 +858,7 @@ This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neo
|
|||
==== `Zbkx` ISA Extension
|
||||
|
||||
The `Zbkx` sub-extension is part of the _RISC-V scalar cryptography_ ISA specification and adds crossbar permutation instructions.
|
||||
It is enabled by the top's `RISCV_ISA_Zbkx` generic.
|
||||
It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zbkx`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_crypto.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -890,7 +891,7 @@ A processor configuration which implements `Zkn` must implement all of the above
|
|||
==== `Zknd` ISA Extension
|
||||
|
||||
The `Zknd` sub-extension is part of the _RISC-V scalar cryptography_ ISA specification and adds NIST AES decryption instructions.
|
||||
It is enabled by the top's `RISCV_ISA_Zknd` generic.
|
||||
It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zknd`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_crypto.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -905,7 +906,7 @@ This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neo
|
|||
==== `Zkne` ISA Extension
|
||||
|
||||
The `Zkne` sub-extension is part of the _RISC-V scalar cryptography_ ISA specification and adds NIST AES encryption instructions.
|
||||
It is enabled by the top's `RISCV_ISA_Zkne` generic.
|
||||
It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zkne`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_crypto.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -920,7 +921,7 @@ This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neo
|
|||
==== `Zknh` ISA Extension
|
||||
|
||||
The `Zknh` sub-extension is part of the _RISC-V scalar cryptography_ ISA specification and adds NIST hash function instructions.
|
||||
It is enabled by the top's `RISCV_ISA_Zknh` generic.
|
||||
It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zknh`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_crypto.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -953,7 +954,7 @@ A processor configuration which implements `Zks` must implement all of the above
|
|||
==== `Zksed` ISA Extension
|
||||
|
||||
The `Zksed` sub-extension is part of the _RISC-V scalar cryptography_ ISA specification and adds ShangMi block cypher
|
||||
and key schedule instructions. It is enabled by the top's `RISCV_ISA_Zksed` generic.
|
||||
and key schedule instructions. It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zksed`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_crypto.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
@ -969,7 +970,7 @@ This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neo
|
|||
==== `Zksh` ISA Extension
|
||||
|
||||
The `Zksh` sub-extension is part of the _RISC-V scalar cryptography_ ISA specification and adds ShangMi hash function instructions.
|
||||
It is enabled by the top's `RISCV_ISA_Zksh` generic.
|
||||
It is enabled by the top's <<_processor_top_entity_generics, `RISCV_ISA_Zksh`>> generic.
|
||||
This ISA extension is implemented as multi-cycle ALU co-processor (`rtl/core/neorv32_cpu_cp_crypto.vhd`).
|
||||
|
||||
.Instructions and Timing
|
||||
|
|
|
@ -211,7 +211,7 @@ of the register file by 50%.
|
|||
.CFU Execution Time
|
||||
[NOTE]
|
||||
The CFU has to complete computation within a **bound time window** (default = 512 clock cycles). Otherwise,
|
||||
the CFU operation is terminated by the hardware and an illegal instruction exception is raised. See section
|
||||
the CFU operation is terminated by the CPU execution logic and an illegal instruction exception is raised. See section
|
||||
<<_cpu_arithmetic_logic_unit>> for more information.
|
||||
|
||||
.CFU Exception
|
||||
|
|
|
@ -762,8 +762,8 @@ caused by a fence instruction, a control flow transfer or a instruction fetch bu
|
|||
| 5 | `HPMCNT_EVENT_WAIT_ALU` | r/w | any delay/wait cycle caused by a _multi-cycle_ <<_cpu_arithmetic_logic_unit>> operation
|
||||
| 6 | `HPMCNT_EVENT_BRANCH` | r/w | any executed branch instruction (unconditional, conditional-taken or conditional-not-taken)
|
||||
| 7 | `HPMCNT_EVENT_BRANCHED` | r/w | any control transfer operation (unconditional jump, taken conditional branch or trap entry/exit)
|
||||
| 8 | `HPMCNT_EVENT_LOAD` | r/w | any executed load operation (including atomic memory operations, <<_a_isa_extension>>)
|
||||
| 9 | `HPMCNT_EVENT_STORE` | r/w | any executed store operation (including atomic memory operations, <<_a_isa_extension>>)
|
||||
| 8 | `HPMCNT_EVENT_LOAD` | r/w | any executed load operation (including atomic memory operations, <<_zalrsc_isa_extension>>)
|
||||
| 9 | `HPMCNT_EVENT_STORE` | r/w | any executed store operation (including atomic memory operations, <<_zalrsc_isa_extension>>)
|
||||
| 10 | `HPMCNT_EVENT_WAIT_LSU` | r/w | any memory/bus/cache/etc. delay/wait cycle while executing any load or store operation (caused by a data bus wait cycle))
|
||||
| 11 | `HPMCNT_EVENT_TRAP` | r/w | starting processing of any trap (<<_traps_exceptions_and_interrupts>>)
|
||||
|=======================
|
||||
|
|
|
@ -20,7 +20,8 @@ image::neorv32_processor.png[align=center]
|
|||
**Key Features**
|
||||
|
||||
* _optional_ processor-internal data and instruction memories (<<_data_memory_dmem,**DMEM**>>/<<_instruction_memory_imem,**IMEM**>>)
|
||||
* _optional_ caches (<<_processor_internal_instruction_cache_icache,**iCACHE**>>, <<_processor_internal_data_cache_dcache,**dCACHE**>>, <<_execute_in_place_module_xip,**xipCACHE**>>, <<_processor_external_bus_interface_xbus,**xCACHE**>>)
|
||||
* _optional_ caches (<<_processor_internal_instruction_cache_icache,**I-CACHE**>>, <<_processor_internal_data_cache_dcache,**D-CACHE**>>,
|
||||
<<_execute_in_place_module_xip,**XIP-CACHE**>>, <<_processor_external_bus_interface_xbus,**XBUS-CACHE**>>)
|
||||
* _optional_ internal bootloader (<<_bootloader_rom_bootrom,**BOOTROM**>>) with UART console & SPI flash boot option
|
||||
* _optional_ machine system timer (<<_machine_system_timer_mtime,**MTIME**>>), RISC-V-compatible
|
||||
* _optional_ two independent universal asynchronous receivers and transmitters (<<_primary_universal_asynchronous_receiver_and_transmitter_uart0,**UART0**>>,
|
||||
|
@ -31,11 +32,11 @@ image::neorv32_processor.png[align=center]
|
|||
* _optional_ general purpose parallel IO port (<<_general_purpose_input_and_output_port_gpio,**GPIO**>>), 64xOut, 64xIn
|
||||
* _optional_ 32-bit external bus interface, Wishbone b4 / AXI4-Lite compatible (<<_processor_external_bus_interface_xbus,**XBUS**>>)
|
||||
* _optional_ watchdog timer (<<_watchdog_timer_wdt,**WDT**>>)
|
||||
* _optional_ PWM controller with up to 12 channels & 8-bit duty cycle resolution (<<_pulse_width_modulation_controller_pwm,**PWM**>>)
|
||||
* _optional_ PWM controller with up to 16 individual channels (<<_pulse_width_modulation_controller_pwm,**PWM**>>)
|
||||
* _optional_ ring-oscillator-based true random number generator (<<_true_random_number_generator_trng,**TRNG**>>)
|
||||
* _optional_ custom functions subsystem for custom co-processor extensions (<<_custom_functions_subsystem_cfs,**CFS**>>)
|
||||
* _optional_ NeoPixel(TM)/WS2812-compatible smart LED interface (<<_smart_led_interface_neoled,**NEOLED**>>)
|
||||
* _optional_ external interrupt controller with up to 32 channels (<<_external_interrupt_controller_xirq,**XIRQ**>>)
|
||||
* _optional_ external interrupt controller with up to 32 channels and programmable interrupt triggers (<<_external_interrupt_controller_xirq,**XIRQ**>>)
|
||||
* _optional_ general purpose 32-bit timer (<<_general_purpose_timer_gptmr,**GPTMR**>>)
|
||||
* _optional_ execute in-place module (<<_execute_in_place_module_xip,**XIP**>>)
|
||||
* _optional_ 1-wire serial interface controller (<<_one_wire_serial_interface_controller_onewire,**ONEWIRE**>>), compatible to the 1-wire standard
|
||||
|
@ -43,7 +44,7 @@ image::neorv32_processor.png[align=center]
|
|||
* _optional_ stream link interface (<<_stream_link_interface_slink,**SLINK**>>), AXI4-Stream compatible
|
||||
* _optional_ cyclic redundancy check unit (<<_cyclic_redundancy_check_crc,**CRC**>>)
|
||||
* _optional_ on-chip debugger with JTAG TAP (<<_on_chip_debugger_ocd,**OCD**>>)
|
||||
* (optional) system configuration information memory to check HW configuration via software (<<_system_configuration_information_memory_sysinfo,**SYSINFO**>>)
|
||||
* _optional_ system configuration information memory to determine hardware configuration via software (<<_system_configuration_information_memory_sysinfo,**SYSINFO**>>)
|
||||
|
||||
|
||||
<<<
|
||||
|
@ -72,7 +73,7 @@ bits/channels are hardwired to zero.
|
|||
Some interfaces (like the TWI and the 1-Wire bus) require explicit tri-state drivers in the final top module.
|
||||
|
||||
.Input/Output Registers
|
||||
[NOTE]
|
||||
[NOTE]
|
||||
By default all output signals are driven by register and all input signals are synchronized into the processor's
|
||||
clock domain also using registers. However, for ASIC implementations it is recommended to add another register state
|
||||
to all inputs and output so the synthesis tool can insert an explicit IO (boundary) scan chain.
|
||||
|
@ -149,7 +150,7 @@ to all inputs and output so the synthesis tool can insert an explicit IO (bounda
|
|||
| `onewire_i` | 1 | in | `'H'` | 1-wire bus sense input
|
||||
| `onewire_o` | 1 | out | - | 1-wire bus output (pull low only)
|
||||
5+^| **<<_pulse_width_modulation_controller_pwm>>**
|
||||
| `pwm_o` | 12 | out | - | pulse-width modulated channels
|
||||
| `pwm_o` | 16 | out | - | pulse-width modulated channels
|
||||
5+^| **<<_custom_functions_subsystem_cfs>>**
|
||||
| `cfs_in_i` | 32 | in | `'L'` | custom CFS input signal conduit
|
||||
| `cfs_out_o` | 32 | out | - | custom CFS output signal conduit
|
||||
|
@ -289,7 +290,7 @@ The generic type "`suv(x:y)`" is an abbreviation for "`std_ulogic_vector(x downt
|
|||
| `IO_SDI_FIFO` | natural | 1 | Depth of the <<_serial_data_interface_controller_sdi>> FIFO. Has to be a power of two, min 1, max 32768.
|
||||
| `IO_TWI_EN` | boolean | false | Implement the <<_two_wire_serial_interface_controller_twi>>.
|
||||
| `IO_TWI_FIFO` | natural | 1 | Depth of the <<_two_wire_serial_interface_controller_twi>> FIFO. Has to be a power of two, min 1, max 32768.
|
||||
| `IO_PWM_NUM_CH` | natural | 0 | Number of channels of the <<_pulse_width_modulation_controller_pwm>> to implement (0..12).
|
||||
| `IO_PWM_NUM_CH` | natural | 0 | Number of channels of the <<_pulse_width_modulation_controller_pwm>> to implement (0..16).
|
||||
| `IO_WDT_EN` | boolean | false | Implement the <<_watchdog_timer_wdt>>.
|
||||
| `IO_TRNG_EN` | boolean | false | Implement the <<_true_random_number_generator_trng>>.
|
||||
| `IO_TRNG_FIFO` | natural | 1 | Depth of the TRNG data FIFO. Has to be a power of two, min 1, max 32768.
|
||||
|
@ -585,7 +586,7 @@ explicit specific processor generic. See section <<_processor_external_bus_inter
|
|||
==== Reservation Set Controller
|
||||
|
||||
The reservation set controller is responsible for handling the load-reservate and store-conditional bus transaction that
|
||||
are triggered by the `lr.w` (LR) and `sc.w` (SC) instructions from the CPU's <<_a_isa_extension>>.
|
||||
are triggered by the `lr.w` (LR) and `sc.w` (SC) instructions from the CPU's <<_zalrsc_isa_extension>>.
|
||||
|
||||
A "reservation" defines an address or address range that provides a guarding mechanism to support atomic accesses. A new
|
||||
reservation is registered by the LR instruction. The address provided by this instruction defines the memory location
|
||||
|
|
|
@ -28,7 +28,7 @@ The data cache provides direct accesses (= uncached) to memory in order to acces
|
|||
processor-internal IO/peripheral modules). All accesses that target the address range from `0xF0000000` to `0xFFFFFFFF`
|
||||
will not be cached at all (see section <<_address_space>>). Direct/uncached accesses have **lower** priority than
|
||||
cache block operations to allow continuous burst transfer and also to maintain logical instruction forward
|
||||
progress / data coherency. Furthermore, atomic load-reservate and store-conditional instructions (<<_a_isa_extension>>)
|
||||
progress / data coherency. Furthermore, atomic load-reservate and store-conditional instructions (<<_zalrsc_isa_extension>>)
|
||||
will always **bypass** the cache.
|
||||
|
||||
.Caching Internal Memories
|
||||
|
|
|
@ -28,7 +28,7 @@ The data cache provides direct accesses (= uncached) to memory in order to acces
|
|||
processor-internal IO/peripheral modules). All accesses that target the address range from `0xF0000000` to `0xFFFFFFFF`
|
||||
will not be cached at all (see section <<_address_space>>). Direct/uncached accesses have **lower** priority than
|
||||
cache block operations to allow continuous burst transfer and also to maintain logical instruction forward
|
||||
progress / data coherency. Furthermore, atomic load-reservate and store-conditional instructions (<<_a_isa_extension>>)
|
||||
progress / data coherency. Furthermore, atomic load-reservate and store-conditional instructions (<<_zalrsc_isa_extension>>)
|
||||
will always **bypass** the cache.
|
||||
|
||||
.Caching Internal Memories
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
| Hardware source files: | neorv32_pwm.vhd |
|
||||
| Software driver files: | neorv32_pwm.c |
|
||||
| | neorv32_pwm.h |
|
||||
| Top entity ports: | `pwm_o` | PWM output channels (12-bit)
|
||||
| Configuration generics: | `IO_PWM_NUM_CH` | number of PWM channels to implement (0..12)
|
||||
| Top entity ports: | `pwm_o` | PWM output channels (16-bit)
|
||||
| Configuration generics: | `IO_PWM_NUM_CH` | number of PWM channels to implement (0..16)
|
||||
| CPU interrupts: | none |
|
||||
| Access restrictions: 2+| privileged access only, non-32-bit write accesses are ignored
|
||||
|=======================
|
||||
|
@ -17,47 +17,45 @@
|
|||
|
||||
**Overview**
|
||||
|
||||
The PWM module implements a pulse-width modulation controller with up to 12 independent channels providing
|
||||
8-bit resolution per channel. The actual number of implemented channels is defined by the `IO_PWM_NUM_CH` generic.
|
||||
Setting this generic to zero will completely remove the PWM controller from the design.
|
||||
|
||||
[NOTE]
|
||||
The `pwm_o` has a static size of 12-bit. If less than 12 PWM channels are configured, only the LSB-aligned channel
|
||||
bits are used while the remaining bits are hardwired to zero.
|
||||
The PWM module implements a pulse-width modulation controller with up to 16 independent channels. Duty cycle and
|
||||
carrier frequency can be programmed individually for each channel.The total number of implemented channels is
|
||||
defined by the `IO_PWM_NUM_CH` generic. The PWM output signal `pwm_o` has a static size of 16-bit. Channel 0
|
||||
corresponds to bit 0, channel 1 to bit 1 and so on. If less than 16 channels are configured, only the LSB-aligned
|
||||
channel bits are connected while the remaining ones are hardwired to zero.
|
||||
|
||||
|
||||
**Theory of Operation**
|
||||
|
||||
The PWM controller is activated by setting the `PWM_CTRL_EN` bit in the module's control register `CTRL`. When this
|
||||
bit is cleared, the unit is reset and all PWM output channels are set to zero. The module
|
||||
provides three duty cycle registers `DC[0]` to `DC[2]`. Each register contains the duty cycle configuration for four
|
||||
consecutive channels. For example, the duty cycle of channel 0 is defined via bits 7:0 in `DC[0]`. The duty cycle of
|
||||
channel 2 is defined via bits 15:0 in `DC[0]` and so on.
|
||||
Depending on the configured number channels, the PWM module provides 16 configuration registers `CHANNEL_CFG[0]` to
|
||||
`CHANNEL_CFG[15]` - one for each channel. Regardless of the configuration of `IO_PWM_NUM_CH` all channel registers can
|
||||
be accessed without raising an exception. However, registers above `IO_PWM_NUM_CH-1` are read-only and hardwired to
|
||||
all-zero.
|
||||
|
||||
[NOTE]
|
||||
Regardless of the configuration of `IO_PWM_NUM_CH` all module registers can be accessed without raising an exception.
|
||||
Software can discover the number of available channels by writing 0xff to all duty cycle configuration bytes and
|
||||
reading those values back. The duty-cycle of channels that were not implemented always reads as zero.
|
||||
Each configuration provides a 1-bit enable flag to enable/disable the according channel, an 8-bit register for setting
|
||||
the duty cycle and a 3-bit clock prescaler select as well as a 10-bit clock diver for _coarse_ and _fine_ tuning of the
|
||||
carrier frequency, respectively.
|
||||
|
||||
Based on the configured duty cycle the according intensity of the channel can be computed by the following formula:
|
||||
A channel is enabled by setting the `PWM_CFG_EN` bit. If this bit is cleared the according PWM output is set to zero.
|
||||
The duty cycle is programmed via the 8 `PWM_CFG_DUTY` bits. Based on the value programmed to this bits the duty cycle
|
||||
the resulting duty cycle of the according channel can be computed by the following formula:
|
||||
|
||||
_**Intensity~x~**_ = `DC[y](i*8+7 downto i*8)` / (2^8^)
|
||||
_Duty Cycle_[%] = `PWM_CFG_DUTY` / 2^8^
|
||||
|
||||
The base frequency of the generated PWM signals is defined by the PWM core clock. This clock is derived
|
||||
from the main processor clock and divided by a prescaler via the 3-bit `PWM_CTRL_PRSCx` in the unit's control
|
||||
register.
|
||||
The PWM period (carrier frequency) is derived from the processor's main clock (_f~main~_). The `PWM_CFG_PRSC` register
|
||||
bits allow to select one out of eight pre-defined clock prescalers for a coarse clock scaling. The 10 `PWM_CFG_CDIV` register
|
||||
bits can be used to apply another fine clock scaling.
|
||||
|
||||
.PWM prescaler configuration
|
||||
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
|
||||
[options="header",grid="rows"]
|
||||
|=======================
|
||||
| **`PWM_CTRL_PRSCx`** | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
|
||||
| **`PWM_CFG_PRSC`** | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
|
||||
| Resulting `clock_prescaler` | 2 | 4 | 8 | 64 | 128 | 1024 | 2048 | 4096
|
||||
|=======================
|
||||
|
||||
The resulting PWM carrier frequency is defined by:
|
||||
|
||||
_**f~PWM~**_ = _f~main~[Hz]_ / (2^8^ * `clock_prescaler`)
|
||||
_f~PWM~_[Hz] = _f~main~_[Hz] / (2^8^ * `clock_prescaler` * (1 + `PWM_CFG_CDIV`))
|
||||
|
||||
|
||||
**Register Map**
|
||||
|
@ -67,19 +65,15 @@ _**f~PWM~**_ = _f~main~[Hz]_ / (2^8^ * `clock_prescaler`)
|
|||
[options="header",grid="all"]
|
||||
|=======================
|
||||
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
||||
.3+<| `0xfffff000` .3+<| `CTRL` <|`0` `PWM_CTRL_EN` ^| r/w <| PWM enable
|
||||
<|`3:1` `PWM_CTRL_PRSC2 : PWM_CTRL_PRSC0` ^| r/w <| 3-bit clock prescaler select
|
||||
<|`31:4` - ^| r/- <| _reserved_, read as zero
|
||||
.4+<| `0xfffff004` .4+<| `DC[0]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 0
|
||||
<|`15:8` ^| r/w <| 8-bit duty cycle for channel 1
|
||||
<|`23:16` ^| r/w <| 8-bit duty cycle for channel 2
|
||||
<|`31:24` ^| r/w <| 8-bit duty cycle for channel 3
|
||||
.4+<| `0xfffff008` .4+<| `DC[1]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 4
|
||||
<|`15:8` ^| r/w <| 8-bit duty cycle for channel 5
|
||||
<|`23:16` ^| r/w <| 8-bit duty cycle for channel 6
|
||||
<|`31:24` ^| r/w <| 8-bit duty cycle for channel 7
|
||||
.4+<| `0xfffff00c` .4+<| `DC[2]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 8
|
||||
<|`15:8` ^| r/w <| 8-bit duty cycle for channel 9
|
||||
<|`23:16` ^| r/w <| 8-bit duty cycle for channel 10
|
||||
<|`31:24` ^| r/w <| 8-bit duty cycle for channel 11
|
||||
.5+<| `0xfffff000` .5+<| `CHANNEL_CFG[0]` <|`31` - `PWM_CFG_EN` ^| r/w <| Channel 0: channel enabled when set
|
||||
<|`30:28` - `PWM_CFG_PRSC_MSB:PWM_CFG_PRSC_LSB` ^| r/w <| Channel 0: 3-bit clock prescaler select
|
||||
<|`27:18` ^| r/- <| Channel 0: _reserved_, hardwired to zero
|
||||
<|`17:8` - `PWM_CFG_CDIV_MSB:PWM_CFG_CDIV_LSB` ^| r/w <| Channel 0: 10-bit clock divider
|
||||
<|`7:0` - `PWM_CFG_DUTY_MSB:PWM_CFG_DUTY_LSB` ^| r/w <| Channel 0: 8-bit duty cycle
|
||||
| `0xfffff004` ... `0xfffff038` | `CHANNEL_CFG[1]` ... `CHANNEL_CFG[14]` | ... | r/w <| Channels 1 to 14
|
||||
.5+<| `0xfffff03C` .5+<| `CHANNEL_CFG[15]` <|`31` - `PWM_CFG_EN` ^| r/w <| Channel 15: channel enabled when set
|
||||
<|`30:28` - `PWM_CFG_PRSC_MSB:PWM_CFG_PRSC_LSB` ^| r/w <| Channel 15: 3-bit clock prescaler select
|
||||
<|`27:18` ^| r/- <| Channel 15: _reserved_, hardwired to zero
|
||||
<|`17:8` - `PWM_CFG_CDIV_MSB:PWM_CFG_CDIV_LSB` ^| r/w <| Channel 15: 10-bit clock divider
|
||||
<|`7:0` - `PWM_CFG_DUTY_MSB:PWM_CFG_DUTY_LSB` ^| r/w <| Channel 15: 8-bit duty cycle
|
||||
|=======================
|
||||
|
|
|
@ -141,5 +141,5 @@ The data cache provides direct accesses (= uncached) to memory in order to acces
|
|||
All accesses that target the address range from `0xF0000000` to `0xFFFFFFFF`
|
||||
will not be cached at all (see section <<_address_space>>). Direct/uncached accesses have **lower** priority than
|
||||
cache block operations to allow continuous burst transfer and also to maintain logical instruction forward
|
||||
progress / data coherency. Furthermore, atomic load-reservate and store-conditional instructions (<<_a_isa_extension>>)
|
||||
progress / data coherency. Furthermore, atomic load-reservate and store-conditional instructions (<<_zalrsc_isa_extension>>)
|
||||
will always **bypass** the cache.
|
||||
|
|
|
@ -87,7 +87,7 @@ The NEORV32 project provides a set of pre-defined C libraries that allow an easy
|
|||
| `neorv32_cfs.c` | `neorv32_cfs.h` | <<_custom_functions_subsystem_cfs>> HAL
|
||||
| `neorv32_crc.c` | `neorv32_crc.h` | <<_cyclic_redundancy_check_crc>> HAL
|
||||
| `neorv32_cpu.c` | `neorv32_cpu.h` | <<_neorv32_central_processing_unit_cpu>> HAL
|
||||
| `neorv32_cpu_amo.c` | `neorv32_cpu_amo.h` | Emulation functions for the read-modify-write <<_a_isa_extension>> instructions
|
||||
| `neorv32_cpu_amo.c` | `neorv32_cpu_amo.h` | Emulation functions for the read-modify-write <<_zalrsc_isa_extension>> / `A` instructions
|
||||
| | `neorv32_cpu_csr.h` | <<_control_and_status_registers_csrs>> definitions
|
||||
| `neorv32_cpu_cfu.c` | `neorv32_cpu_cfu.h` | <<_custom_functions_unit_cfu>> HAL
|
||||
| `neorv32_dma.c` | `neorv32_dma.h` | <<_direct_memory_access_controller_dma>> HAL
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
|
@ -29,7 +29,7 @@ package neorv32_package is
|
|||
|
||||
-- Architecture Constants -----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100503"; -- hardware version
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100504"; -- hardware version
|
||||
constant archid_c : natural := 19; -- official RISC-V architecture ID
|
||||
constant XLEN : natural := 32; -- native data path width
|
||||
|
||||
|
@ -755,7 +755,7 @@ package neorv32_package is
|
|||
IO_SDI_FIFO : natural range 1 to 2**15 := 1;
|
||||
IO_TWI_EN : boolean := false;
|
||||
IO_TWI_FIFO : natural range 1 to 2**15 := 1;
|
||||
IO_PWM_NUM_CH : natural range 0 to 12 := 0;
|
||||
IO_PWM_NUM_CH : natural range 0 to 16 := 0;
|
||||
IO_WDT_EN : boolean := false;
|
||||
IO_TRNG_EN : boolean := false;
|
||||
IO_TRNG_FIFO : natural range 1 to 2**15 := 1;
|
||||
|
@ -841,7 +841,7 @@ package neorv32_package is
|
|||
onewire_i : in std_ulogic := 'H';
|
||||
onewire_o : out std_ulogic;
|
||||
-- PWM (available if IO_PWM_NUM_CH > 0) --
|
||||
pwm_o : out std_ulogic_vector(11 downto 0); -- pwm channels
|
||||
pwm_o : out std_ulogic_vector(15 downto 0); -- pwm channels
|
||||
-- Custom Functions Subsystem IO --
|
||||
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'L');
|
||||
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0);
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
-- ================================================================================ --
|
||||
-- NEORV32 SoC - Pulse Width Modulation Controller (PWM) --
|
||||
-- -------------------------------------------------------------------------------- --
|
||||
-- Providing up to 16 individual PWM channels; each channel features an individual --
|
||||
-- enable flag, an 8-bit duty-cycle configuration, a 3-bit prescaler (for coarse --
|
||||
-- clock configuration) and a 16-bit clock divider (for fine clock configuration). --
|
||||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
|
@ -17,7 +21,7 @@ use neorv32.neorv32_package.all;
|
|||
|
||||
entity neorv32_pwm is
|
||||
generic (
|
||||
NUM_CHANNELS : natural range 0 to 12 -- number of PWM channels (0..12)
|
||||
NUM_CHANNELS : natural range 0 to 16 -- number of PWM channels (0..16)
|
||||
);
|
||||
port (
|
||||
clk_i : in std_ulogic; -- global clock line
|
||||
|
@ -26,32 +30,32 @@ entity neorv32_pwm is
|
|||
bus_rsp_o : out bus_rsp_t; -- bus response
|
||||
clkgen_en_o : out std_ulogic; -- enable clock generator
|
||||
clkgen_i : in std_ulogic_vector(7 downto 0); -- clock divider input
|
||||
pwm_o : out std_ulogic_vector(11 downto 0) -- PWM output
|
||||
pwm_o : out std_ulogic_vector(15 downto 0) -- PWM output
|
||||
);
|
||||
end neorv32_pwm;
|
||||
|
||||
architecture neorv32_pwm_rtl of neorv32_pwm is
|
||||
|
||||
-- Control register bits --
|
||||
constant ctrl_enable_c : natural := 0; -- r/w: PWM enable
|
||||
constant ctrl_prsc0_bit_c : natural := 1; -- r/w: prescaler select bit 0
|
||||
constant ctrl_prsc1_bit_c : natural := 2; -- r/w: prescaler select bit 1
|
||||
constant ctrl_prsc2_bit_c : natural := 3; -- r/w: prescaler select bit 2
|
||||
-- pwm channel controller --
|
||||
component neorv32_pwm_channel
|
||||
port (
|
||||
clk_i : in std_ulogic; -- global clock line
|
||||
rstn_i : in std_ulogic; -- global reset line, low-active, async
|
||||
we_i : in std_ulogic; -- write enable
|
||||
re_i : in std_ulogic; -- read enable
|
||||
wdata_i : in std_ulogic_vector(31 downto 0); -- write data
|
||||
rdata_o : out std_ulogic_vector(31 downto 0); -- read data
|
||||
clkgen_i : in std_ulogic_vector(7 downto 0); -- clock divider input
|
||||
clkgen_en_o : out std_ulogic; -- enable clock generator
|
||||
pwm_o : out std_ulogic -- PWM output
|
||||
);
|
||||
end component;
|
||||
|
||||
-- accessible regs --
|
||||
type pwm_ch_t is array (0 to 11) of std_ulogic_vector(7 downto 0);
|
||||
signal pwm_ch : pwm_ch_t; -- duty cycle (r/w)
|
||||
signal enable : std_ulogic; -- enable unit (r/w)
|
||||
signal prsc : std_ulogic_vector(2 downto 0); -- clock prescaler (r/w)
|
||||
|
||||
type pwm_ch_rd_t is array (0 to 11) of std_ulogic_vector(7 downto 0);
|
||||
signal pwm_ch_rd : pwm_ch_rd_t; -- duty cycle read-back
|
||||
|
||||
-- prescaler clock generator --
|
||||
signal prsc_tick : std_ulogic;
|
||||
|
||||
-- pwm core counter --
|
||||
signal pwm_cnt : std_ulogic_vector(7 downto 0);
|
||||
-- wiring --
|
||||
type rdata_t is array (0 to NUM_CHANNELS-1) of std_ulogic_vector(31 downto 0);
|
||||
signal rdata : rdata_t;
|
||||
signal rdata_sum : std_ulogic_vector(31 downto 0);
|
||||
signal sel, we, re, ce, pwm : std_ulogic_vector(NUM_CHANNELS-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
|
@ -61,99 +65,173 @@ begin
|
|||
begin
|
||||
if (rstn_i = '0') then
|
||||
bus_rsp_o <= rsp_terminate_c;
|
||||
enable <= '0';
|
||||
prsc <= (others => '0');
|
||||
pwm_ch <= (others => (others => '0'));
|
||||
elsif rising_edge(clk_i) then
|
||||
-- bus handshake --
|
||||
bus_rsp_o.ack <= bus_req_i.stb;
|
||||
bus_rsp_o.err <= '0';
|
||||
bus_rsp_o.data <= (others => '0');
|
||||
if (bus_req_i.stb = '1') then
|
||||
|
||||
-- write access --
|
||||
if (bus_req_i.rw = '1') then
|
||||
-- control register --
|
||||
if (bus_req_i.addr(3 downto 2) = "00") then
|
||||
enable <= bus_req_i.data(ctrl_enable_c);
|
||||
prsc <= bus_req_i.data(ctrl_prsc2_bit_c downto ctrl_prsc0_bit_c);
|
||||
end if;
|
||||
-- duty cycle register 0 --
|
||||
if (bus_req_i.addr(3 downto 2) = "01") then
|
||||
pwm_ch(00) <= bus_req_i.data(07 downto 00);
|
||||
pwm_ch(01) <= bus_req_i.data(15 downto 08);
|
||||
pwm_ch(02) <= bus_req_i.data(23 downto 16);
|
||||
pwm_ch(03) <= bus_req_i.data(31 downto 24);
|
||||
end if;
|
||||
-- duty cycle register 1 --
|
||||
if (bus_req_i.addr(3 downto 2) = "10") then
|
||||
pwm_ch(04) <= bus_req_i.data(07 downto 00);
|
||||
pwm_ch(05) <= bus_req_i.data(15 downto 08);
|
||||
pwm_ch(06) <= bus_req_i.data(23 downto 16);
|
||||
pwm_ch(07) <= bus_req_i.data(31 downto 24);
|
||||
end if;
|
||||
-- duty cycle register 2 --
|
||||
if (bus_req_i.addr(3 downto 2) = "11") then
|
||||
pwm_ch(08) <= bus_req_i.data(07 downto 00);
|
||||
pwm_ch(09) <= bus_req_i.data(15 downto 08);
|
||||
pwm_ch(10) <= bus_req_i.data(23 downto 16);
|
||||
pwm_ch(11) <= bus_req_i.data(31 downto 24);
|
||||
end if;
|
||||
|
||||
-- read access --
|
||||
else
|
||||
case bus_req_i.addr(3 downto 2) is
|
||||
when "00" => bus_rsp_o.data(ctrl_enable_c) <= enable; bus_rsp_o.data(ctrl_prsc2_bit_c downto ctrl_prsc0_bit_c) <= prsc;
|
||||
when "01" => bus_rsp_o.data <= pwm_ch_rd(03) & pwm_ch_rd(02) & pwm_ch_rd(01) & pwm_ch_rd(00);
|
||||
when "10" => bus_rsp_o.data <= pwm_ch_rd(07) & pwm_ch_rd(06) & pwm_ch_rd(05) & pwm_ch_rd(04);
|
||||
when "11" => bus_rsp_o.data <= pwm_ch_rd(11) & pwm_ch_rd(10) & pwm_ch_rd(09) & pwm_ch_rd(08);
|
||||
when others => bus_rsp_o.data <= (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
|
||||
bus_rsp_o.data <= rdata_sum;
|
||||
bus_rsp_o.ack <= '1';
|
||||
else
|
||||
bus_rsp_o.data <= (others => '0');
|
||||
bus_rsp_o.ack <= '0';
|
||||
end if;
|
||||
bus_rsp_o.err <= '0'; -- no errors
|
||||
end if;
|
||||
end process bus_access;
|
||||
|
||||
-- duty cycle read-back --
|
||||
pwm_dc_rd_gen: process(pwm_ch)
|
||||
-- data read-back (large OR) --
|
||||
read_back: process(rdata)
|
||||
variable tmp_v : std_ulogic_vector(31 downto 0);
|
||||
begin
|
||||
pwm_ch_rd <= (others => (others => '0'));
|
||||
for i in 0 to NUM_CHANNELS-1 loop -- only implement the actually configured number of channel register
|
||||
pwm_ch_rd(i) <= pwm_ch(i);
|
||||
tmp_v := (others => '0');
|
||||
for i in 0 to NUM_CHANNELS-1 loop
|
||||
tmp_v := tmp_v or rdata(i);
|
||||
end loop;
|
||||
end process pwm_dc_rd_gen;
|
||||
rdata_sum <= tmp_v;
|
||||
end process read_back;
|
||||
|
||||
-- Channel Controllers --------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
pwm_channel_gen:
|
||||
for i in 0 to NUM_CHANNELS-1 generate
|
||||
neorv32_pwm_channel_inst: neorv32_pwm_channel
|
||||
port map (
|
||||
clk_i => clk_i,
|
||||
rstn_i => rstn_i,
|
||||
we_i => we(i),
|
||||
re_i => re(i),
|
||||
wdata_i => bus_req_i.data,
|
||||
rdata_o => rdata(i),
|
||||
clkgen_i => clkgen_i,
|
||||
clkgen_en_o => ce(i),
|
||||
pwm_o => pwm(i)
|
||||
);
|
||||
|
||||
-- access enable --
|
||||
sel(i) <= '1' when (bus_req_i.addr(5 downto 2) = std_ulogic_vector(to_unsigned(i, 4))) else '0';
|
||||
we(i) <= sel(i) and bus_req_i.stb and ( bus_req_i.rw);
|
||||
re(i) <= sel(i) and bus_req_i.stb and (not bus_req_i.rw);
|
||||
end generate;
|
||||
|
||||
pwm_channel_connect: process(pwm)
|
||||
begin
|
||||
pwm_o <= (others => '0');
|
||||
pwm_o(pwm'range) <= pwm(pwm'range);
|
||||
end process pwm_channel_connect;
|
||||
|
||||
-- any clock requests? --
|
||||
clkgen_en_o <= or_reduce_f(ce);
|
||||
|
||||
end neorv32_pwm_rtl;
|
||||
|
||||
-- ================================================================================ --
|
||||
-- NEORV32 SoC - PWM - Channel Controller --
|
||||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library neorv32;
|
||||
use neorv32.neorv32_package.all;
|
||||
|
||||
entity neorv32_pwm_channel is
|
||||
port (
|
||||
clk_i : in std_ulogic; -- global clock line
|
||||
rstn_i : in std_ulogic; -- global reset line, low-active, async
|
||||
we_i : in std_ulogic; -- write enable
|
||||
re_i : in std_ulogic; -- read enable
|
||||
wdata_i : in std_ulogic_vector(31 downto 0); -- write data
|
||||
rdata_o : out std_ulogic_vector(31 downto 0); -- read data
|
||||
clkgen_i : in std_ulogic_vector(7 downto 0); -- clock divider input
|
||||
clkgen_en_o : out std_ulogic; -- enable clock generator
|
||||
pwm_o : out std_ulogic -- PWM output
|
||||
);
|
||||
end neorv32_pwm_channel;
|
||||
|
||||
architecture neorv32_pwm_channel_rtl of neorv32_pwm_channel is
|
||||
|
||||
-- configuration register --
|
||||
signal cfg_en : std_ulogic; -- channel enable
|
||||
signal cfg_prsc : std_ulogic_vector(2 downto 0); -- (course) clock prescaler select
|
||||
signal cfg_cdiv : std_ulogic_vector(9 downto 0); -- (fine) clock divider
|
||||
signal cfg_duty : std_ulogic_vector(7 downto 0); -- duty cycle
|
||||
|
||||
-- pwm core --
|
||||
signal cnt_cdiv : std_ulogic_vector(9 downto 0);
|
||||
signal cnt_tick : std_ulogic;
|
||||
signal cnt_duty : std_ulogic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- Configuration --------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
config_write: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
cfg_en <= '0';
|
||||
cfg_prsc <= (others => '0');
|
||||
cfg_cdiv <= (others => '0');
|
||||
cfg_duty <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
if (we_i = '1') then
|
||||
cfg_en <= wdata_i(31);
|
||||
cfg_prsc <= wdata_i(30 downto 28);
|
||||
cfg_cdiv <= wdata_i(17 downto 8);
|
||||
cfg_duty <= wdata_i(7 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process config_write;
|
||||
|
||||
-- read access --
|
||||
rdata_o <= cfg_en & cfg_prsc & "0000000000" & cfg_cdiv & cfg_duty when (re_i = '1') else (others => '0');
|
||||
|
||||
-- enable global clock generator --
|
||||
clkgen_en_o <= cfg_en;
|
||||
|
||||
-- PWM Core -------------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
pwm_core: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
pwm_cnt <= (others => '0');
|
||||
pwm_o <= (others => '0');
|
||||
cnt_cdiv <= (others => '0');
|
||||
cnt_duty <= (others => '0');
|
||||
pwm_o <= '0';
|
||||
elsif rising_edge(clk_i) then
|
||||
-- pwm base counter --
|
||||
if (enable = '0') then
|
||||
pwm_cnt <= (others => '0');
|
||||
elsif (prsc_tick = '1') then
|
||||
pwm_cnt <= std_ulogic_vector(unsigned(pwm_cnt) + 1);
|
||||
end if;
|
||||
-- channels --
|
||||
pwm_o <= (others => '0');
|
||||
for i in 0 to NUM_CHANNELS-1 loop
|
||||
if (unsigned(pwm_cnt) >= unsigned(pwm_ch(i))) or (enable = '0') then
|
||||
pwm_o(i) <= '0';
|
||||
|
||||
-- clock divider --
|
||||
if (cfg_en = '0') then
|
||||
cnt_cdiv <= (others => '0');
|
||||
elsif (clkgen_i(to_integer(unsigned(cfg_prsc))) = '1') then -- pre-scaled clock (coarse)
|
||||
if (cnt_tick = '1') then -- fine-tuned clock
|
||||
cnt_cdiv <= (others => '0');
|
||||
else
|
||||
pwm_o(i) <= '1';
|
||||
cnt_cdiv <= std_ulogic_vector(unsigned(cnt_cdiv) + 1);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
-- duty cycle counter --
|
||||
if (cfg_en = '0') then
|
||||
cnt_duty <= (others => '0');
|
||||
elsif (cnt_tick = '1') then
|
||||
cnt_duty <= std_ulogic_vector(unsigned(cnt_duty) + 1);
|
||||
end if;
|
||||
|
||||
-- pwm output --
|
||||
if (cfg_en = '0') or (unsigned(cnt_duty) >= unsigned(cfg_duty)) then
|
||||
pwm_o <= '0';
|
||||
else
|
||||
pwm_o <= '1';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process pwm_core;
|
||||
|
||||
-- PWM clock select --
|
||||
clkgen_en_o <= enable; -- enable clock generator
|
||||
prsc_tick <= clkgen_i(to_integer(unsigned(prsc)));
|
||||
-- fine-tuned clock tick --
|
||||
cnt_tick <= '1' when (cnt_cdiv = cfg_cdiv) else '0';
|
||||
|
||||
|
||||
end neorv32_pwm_rtl;
|
||||
end neorv32_pwm_channel_rtl;
|
||||
|
|
|
@ -122,7 +122,7 @@ entity neorv32_top is
|
|||
IO_SDI_FIFO : natural range 1 to 2**15 := 1; -- RTX fifo depth, has to be zero or a power of two, min 1
|
||||
IO_TWI_EN : boolean := false; -- implement two-wire interface (TWI)?
|
||||
IO_TWI_FIFO : natural range 1 to 2**15 := 1; -- RTX fifo depth, has to be zero or a power of two, min 1
|
||||
IO_PWM_NUM_CH : natural range 0 to 12 := 0; -- number of PWM channels to implement (0..12); 0 = disabled
|
||||
IO_PWM_NUM_CH : natural range 0 to 16 := 0; -- number of PWM channels to implement (0..16)
|
||||
IO_WDT_EN : boolean := false; -- implement watch dog timer (WDT)?
|
||||
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)?
|
||||
IO_TRNG_FIFO : natural range 1 to 2**15 := 1; -- data fifo depth, has to be a power of two, min 1
|
||||
|
@ -220,7 +220,7 @@ entity neorv32_top is
|
|||
onewire_o : out std_ulogic; -- 1-wire bus output (pull low only)
|
||||
|
||||
-- PWM (available if IO_PWM_NUM_CH > 0) --
|
||||
pwm_o : out std_ulogic_vector(11 downto 0); -- pwm channels
|
||||
pwm_o : out std_ulogic_vector(15 downto 0); -- pwm channels
|
||||
|
||||
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
|
||||
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'L'); -- custom CFS inputs conduit
|
||||
|
|
|
@ -25,7 +25,7 @@ entity neorv32_ProcessorTop_Minimal is
|
|||
MEM_INT_DMEM_EN : boolean := true; -- implement processor-internal data memory
|
||||
MEM_INT_DMEM_SIZE : natural := 64*1024; -- size of processor-internal data memory in bytes
|
||||
-- Processor peripherals --
|
||||
IO_PWM_NUM_CH : natural := 3 -- number of PWM channels to implement (0..12); 0 = disabled
|
||||
IO_PWM_NUM_CH : natural := 3 -- number of PWM channels to implement (0..16)
|
||||
);
|
||||
port (
|
||||
-- Global control --
|
||||
|
@ -39,7 +39,7 @@ end entity;
|
|||
architecture neorv32_ProcessorTop_Minimal_rtl of neorv32_ProcessorTop_Minimal is
|
||||
|
||||
-- internal IO connection --
|
||||
signal con_pwm_o : std_ulogic_vector(11 downto 0);
|
||||
signal con_pwm_o : std_ulogic_vector(15 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ entity neorv32_ProcessorTop_MinimalBoot is
|
|||
MEM_INT_DMEM_SIZE : natural := 64*1024; -- size of processor-internal data memory in bytes
|
||||
-- Processor peripherals --
|
||||
IO_GPIO_NUM : natural := 0; -- number of GPIO input/output pairs (0..64)
|
||||
IO_PWM_NUM_CH : natural := 3 -- number of PWM channels to implement (0..12); 0 = disabled
|
||||
IO_PWM_NUM_CH : natural := 3 -- number of PWM channels to implement (0..16)
|
||||
);
|
||||
port (
|
||||
-- Global control --
|
||||
|
@ -46,7 +46,7 @@ architecture neorv32_ProcessorTop_MinimalBoot_rtl of neorv32_ProcessorTop_Minima
|
|||
|
||||
-- internal IO connection --
|
||||
signal con_gpio_o : std_ulogic_vector(63 downto 0);
|
||||
signal con_pwm_o : std_ulogic_vector(11 downto 0);
|
||||
signal con_pwm_o : std_ulogic_vector(15 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ entity neorv32_ProcessorTop_UP5KDemo is
|
|||
MEM_INT_DMEM_SIZE : natural := 64*1024; -- size of processor-internal data memory in bytes
|
||||
-- Processor peripherals --
|
||||
IO_GPIO_NUM : natural := 64; -- number of GPIO input/output pairs (0..64)
|
||||
IO_PWM_NUM_CH : natural := 3 -- number of PWM channels to implement (0..12); 0 = disabled
|
||||
IO_PWM_NUM_CH : natural := 3 -- number of PWM channels to implement (0..16)
|
||||
);
|
||||
port (
|
||||
-- Global control --
|
||||
|
@ -61,7 +61,7 @@ architecture neorv32_ProcessorTop_UP5KDemo_rtl of neorv32_ProcessorTop_UP5KDemo
|
|||
-- internal IO connection --
|
||||
signal con_gpio_o : std_ulogic_vector(63 downto 0);
|
||||
signal con_gpio_i : std_ulogic_vector(63 downto 0);
|
||||
signal con_pwm_o : std_ulogic_vector(11 downto 0);
|
||||
signal con_pwm_o : std_ulogic_vector(15 downto 0);
|
||||
signal con_spi_sck : std_ulogic;
|
||||
signal con_spi_sdi : std_ulogic;
|
||||
signal con_spi_sdo : std_ulogic;
|
||||
|
|
|
@ -114,7 +114,7 @@ entity neorv32_vivado_ip is
|
|||
IO_TWI_EN : boolean := false;
|
||||
IO_TWI_FIFO : natural range 1 to 2**15 := 1;
|
||||
IO_PWM_EN : boolean := false;
|
||||
IO_PWM_NUM_CH : natural range 1 to 12 := 1; -- variable-sized ports must be at least 0 downto 0; #974
|
||||
IO_PWM_NUM_CH : natural range 1 to 16 := 1; -- variable-sized ports must be at least 0 downto 0; #974
|
||||
IO_WDT_EN : boolean := false;
|
||||
IO_TRNG_EN : boolean := false;
|
||||
IO_TRNG_FIFO : natural range 1 to 2**15 := 1;
|
||||
|
@ -274,7 +274,7 @@ architecture neorv32_vivado_ip_rtl of neorv32_vivado_ip is
|
|||
-- constrained size ports --
|
||||
signal gpio_o_aux : std_ulogic_vector(63 downto 0);
|
||||
signal gpio_i_aux : std_ulogic_vector(63 downto 0);
|
||||
signal pwm_o_aux : std_ulogic_vector(11 downto 0);
|
||||
signal pwm_o_aux : std_ulogic_vector(15 downto 0);
|
||||
signal xirq_i_aux : std_ulogic_vector(31 downto 0);
|
||||
|
||||
-- internal wishbone bus --
|
||||
|
|
|
@ -273,7 +273,7 @@ begin
|
|||
IO_SDI_FIFO => 4, -- SDI RTX fifo depth, has to be zero or a power of two
|
||||
IO_TWI_EN => true, -- implement two-wire interface (TWI)?
|
||||
IO_TWI_FIFO => 4, -- RTX fifo depth, has to be zero or a power of two, min 1
|
||||
IO_PWM_NUM_CH => 12, -- number of PWM channels to implement (0..12); 0 = disabled
|
||||
IO_PWM_NUM_CH => 8, -- number of PWM channels to implement (0..16)
|
||||
IO_WDT_EN => true, -- implement watch dog timer (WDT)?
|
||||
IO_TRNG_EN => true, -- implement true random number generator (TRNG)?
|
||||
IO_TRNG_FIFO => 4, -- TRNG fifo depth, has to be a power of two, min 1
|
||||
|
|
|
@ -249,7 +249,7 @@ begin
|
|||
IO_SDI_FIFO => 4, -- SDI RTX fifo depth, has to be zero or a power of two
|
||||
IO_TWI_EN => true, -- implement two-wire interface (TWI)?
|
||||
IO_TWI_FIFO => 4, -- RTX fifo depth, has to be zero or a power of two, min 1
|
||||
IO_PWM_NUM_CH => 12, -- number of PWM channels to implement (0..12); 0 = disabled
|
||||
IO_PWM_NUM_CH => 8, -- number of PWM channels to implement (0..16)
|
||||
IO_WDT_EN => true, -- implement watch dog timer (WDT)?
|
||||
IO_TRNG_EN => true, -- implement true random number generator (TRNG)?
|
||||
IO_TRNG_FIFO => 4, -- TRNG fifo depth, has to be a power of two, min 1
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
/**@{*/
|
||||
/** UART BAUD rate */
|
||||
#define BAUD_RATE 19200
|
||||
/** Maximum PWM output intensity (8-bit) */
|
||||
#define PWM_MAX 200
|
||||
/** Maximum PWM output intensity (8-bit duty cycle) */
|
||||
#define MAX_DUTY 200
|
||||
/**@}*/
|
||||
|
||||
|
||||
|
@ -61,49 +61,61 @@ int main() {
|
|||
|
||||
int num_pwm_channels = neorv32_pmw_get_num_channels();
|
||||
|
||||
// check number of PWM channels
|
||||
// get number of implemented PWM channels
|
||||
if (neorv32_uart0_available()) {
|
||||
neorv32_uart0_printf("Implemented PWM channels: %i\n\n", num_pwm_channels);
|
||||
}
|
||||
|
||||
|
||||
// deactivate all PWM channels
|
||||
// deactivate/clear all available channels
|
||||
int i;
|
||||
for (i=0; i<num_pwm_channels; i++) {
|
||||
neorv32_pwm_set(i, 0);
|
||||
neorv32_pwm_ch_disable(i);
|
||||
neorv32_pwm_ch_set_clock(i, 0, 0);
|
||||
neorv32_pwm_ch_set_duty(i, 0);
|
||||
}
|
||||
|
||||
// configure and enable PWM
|
||||
neorv32_pwm_setup(CLK_PRSC_64);
|
||||
// configure all available channels
|
||||
for (i=0; i<num_pwm_channels; i++) {
|
||||
neorv32_pwm_ch_set_clock(i, CLK_PRSC_64, 0);
|
||||
neorv32_pwm_ch_enable(i);
|
||||
}
|
||||
|
||||
uint8_t pwm = 0;
|
||||
uint8_t up = 1;
|
||||
uint8_t ch = 0;
|
||||
// simple animation: "pulse" channels one by one
|
||||
neorv32_uart0_printf("Starting animation...\n");
|
||||
|
||||
// animate!
|
||||
while(1) {
|
||||
int dc = 0; // current duty cycle
|
||||
int up = 1; // up/down (increase/decrease)
|
||||
int ch = 0; // current channel
|
||||
|
||||
while (1) {
|
||||
|
||||
// update duty cycle
|
||||
if (up) {
|
||||
if (pwm == PWM_MAX) {
|
||||
if (dc >= (int)(MAX_DUTY)) { // maximum intensity reached?
|
||||
up = 0;
|
||||
}
|
||||
else {
|
||||
pwm++;
|
||||
dc++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pwm == 0) {
|
||||
ch = (ch + 1) & 3; // goto next channel
|
||||
if (dc == 0) {
|
||||
// goto next channel
|
||||
if ((ch + 1) >= num_pwm_channels) {
|
||||
ch = 0;
|
||||
}
|
||||
else {
|
||||
ch++;
|
||||
}
|
||||
up = 1;
|
||||
}
|
||||
else {
|
||||
pwm--;
|
||||
dc--;
|
||||
}
|
||||
}
|
||||
|
||||
neorv32_pwm_set(ch, pwm); // output new duty cycle
|
||||
neorv32_cpu_delay_ms(3); // wait ~3ms
|
||||
neorv32_pwm_ch_set_duty(ch, dc); // set new duty cycle for channel
|
||||
neorv32_cpu_delay_ms(3); // wait ~3ms using busy-wait
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -27,19 +27,22 @@
|
|||
/**@{*/
|
||||
/** PWM module prototype */
|
||||
typedef volatile struct __attribute__((packed,aligned(4))) {
|
||||
uint32_t CTRL; /**< offset 0: control register (#NEORV32_PWM_CTRL_enum) */
|
||||
uint32_t DC[3]; /**< offset 4..12: duty cycle register 0..2 */
|
||||
uint32_t CHANNEL_CFG[16]; /**< offset 0..64: channel configuration 0..15 (#CHANNEL_CFG_enum) */
|
||||
} neorv32_pwm_t;
|
||||
|
||||
/** PWM module hardware access (#neorv32_pwm_t) */
|
||||
#define NEORV32_PWM ((neorv32_pwm_t*) (NEORV32_PWM_BASE))
|
||||
|
||||
/** PWM control register bits */
|
||||
enum NEORV32_PWM_CTRL_enum {
|
||||
PWM_CTRL_EN = 0, /**< PWM control register(0) (r/w): PWM controller enable */
|
||||
PWM_CTRL_PRSC0 = 1, /**< PWM control register(1) (r/w): Clock prescaler select bit 0 */
|
||||
PWM_CTRL_PRSC1 = 2, /**< PWM control register(2) (r/w): Clock prescaler select bit 1 */
|
||||
PWM_CTRL_PRSC2 = 3 /**< PWM control register(3) (r/w): Clock prescaler select bit 2 */
|
||||
/** PWM channel configuration bits */
|
||||
enum CHANNEL_CFG_enum {
|
||||
PWM_CFG_DUTY_LSB = 0, /**< PWM configuration register(0) (r/w): Duty cycle (8-bit), LSB */
|
||||
PWM_CFG_DUTY_MSB = 7, /**< PWM configuration register(7) (r/w): Duty cycle (8-bit), MSB */
|
||||
PWM_CFG_CDIV_LSB = 8, /**< PWM configuration register(8) (r/w): Clock divider (10-bit), LSB */
|
||||
PWM_CFG_CDIV_MSB = 17, /**< PWM configuration register(17) (r/w): Clock divider (10-bit), MSB */
|
||||
|
||||
PWM_CFG_PRSC_LSB = 28, /**< PWM configuration register(28) (r/w): Clock prescaler select (3-bit), LSB */
|
||||
PWM_CFG_PRSC_MSB = 30, /**< PWM configuration register(30) (r/w): Clock prescaler select (3-bit), MSB */
|
||||
PWM_CFG_EN = 31 /**< PWM configuration register(31) (r/w): channel enable */
|
||||
};
|
||||
/**@}*/
|
||||
|
||||
|
@ -48,13 +51,12 @@ enum NEORV32_PWM_CTRL_enum {
|
|||
* @name Prototypes
|
||||
**************************************************************************/
|
||||
/**@{*/
|
||||
int neorv32_pwm_available(void);
|
||||
void neorv32_pwm_setup(int prsc);
|
||||
void neorv32_pwm_disable(void);
|
||||
void neorv32_pwm_enable(void);
|
||||
int neorv32_pmw_get_num_channels(void);
|
||||
void neorv32_pwm_set(int channel, uint8_t dc);
|
||||
uint8_t neorv32_pwm_get(int channel);
|
||||
int neorv32_pwm_available(void);
|
||||
int neorv32_pmw_get_num_channels(void);
|
||||
void neorv32_pwm_ch_enable(int channel);
|
||||
void neorv32_pwm_ch_disable(int channel);
|
||||
void neorv32_pwm_ch_set_clock(int channel, int prsc, int cdiv);
|
||||
void neorv32_pwm_ch_set_duty(int channel, int duty);
|
||||
/**@}*/
|
||||
|
||||
#endif // neorv32_pwm_h
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
#include <newlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/timeb.h>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
@ -35,59 +35,19 @@ int neorv32_pwm_available(void) {
|
|||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Enable and configure pulse width modulation controller.
|
||||
* The PWM control register bits are listed in #NEORV32_PWM_CTRL_enum.
|
||||
* Get number of implemented PWM channels.
|
||||
* @warning This function will override all channel configuration registers.
|
||||
*
|
||||
* @param[in] prsc Clock prescaler select (0..7). See #NEORV32_CLOCK_PRSC_enum.
|
||||
**************************************************************************/
|
||||
void neorv32_pwm_setup(int prsc) {
|
||||
|
||||
NEORV32_PWM->CTRL = 0; // reset
|
||||
|
||||
uint32_t ct_enable = 1;
|
||||
ct_enable = ct_enable << PWM_CTRL_EN;
|
||||
|
||||
uint32_t ct_prsc = (uint32_t)(prsc & 0x07);
|
||||
ct_prsc = ct_prsc << PWM_CTRL_PRSC0;
|
||||
|
||||
NEORV32_PWM->CTRL = ct_enable | ct_prsc;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Disable pulse width modulation controller.
|
||||
**************************************************************************/
|
||||
void neorv32_pwm_disable(void) {
|
||||
|
||||
NEORV32_PWM->CTRL &= ~((uint32_t)(1 << PWM_CTRL_EN));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Enable pulse width modulation controller.
|
||||
**************************************************************************/
|
||||
void neorv32_pwm_enable(void) {
|
||||
|
||||
NEORV32_PWM->CTRL |= ((uint32_t)(1 << PWM_CTRL_EN));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Get number of implemented channels.
|
||||
* @warning This function will override all duty cycle configuration registers.
|
||||
*
|
||||
* @return Number of implemented channels.
|
||||
* @return Number of implemented PWM channels.
|
||||
**************************************************************************/
|
||||
int neorv32_pmw_get_num_channels(void) {
|
||||
|
||||
neorv32_pwm_disable();
|
||||
|
||||
int i = 0;
|
||||
uint32_t cnt = 0;
|
||||
|
||||
for (i=0; i<12; i++) {
|
||||
neorv32_pwm_set(i, 1);
|
||||
cnt += neorv32_pwm_get(i);
|
||||
for (i=0; i<16; i++) {
|
||||
NEORV32_PWM->CHANNEL_CFG[i] = 1;
|
||||
cnt += NEORV32_PWM->CHANNEL_CFG[i];
|
||||
}
|
||||
|
||||
return (int)cnt;
|
||||
|
@ -95,42 +55,62 @@ int neorv32_pmw_get_num_channels(void) {
|
|||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Set duty cycle for channel.
|
||||
* Enable PWM channel.
|
||||
*
|
||||
* @param[in] channel Channel select (0..11).
|
||||
* @param[in] dc Duty cycle (8-bit, LSB-aligned).
|
||||
* @param[in] channel Channel select (0..15).
|
||||
**************************************************************************/
|
||||
void neorv32_pwm_set(int channel, uint8_t dc) {
|
||||
void neorv32_pwm_ch_enable(int channel) {
|
||||
|
||||
if (channel > 11) {
|
||||
return; // out-of-range
|
||||
}
|
||||
channel &= 0xf; // constrain range
|
||||
|
||||
const uint32_t dc_mask = 0xff;
|
||||
uint32_t dc_new = (uint32_t)dc;
|
||||
|
||||
uint32_t tmp = NEORV32_PWM->DC[channel/4];
|
||||
|
||||
tmp &= ~(dc_mask << ((channel % 4) * 8)); // clear previous duty cycle
|
||||
tmp |= dc_new << ((channel % 4) * 8); // set new duty cycle
|
||||
|
||||
NEORV32_PWM->DC[channel/4] = tmp;
|
||||
NEORV32_PWM->CHANNEL_CFG[channel] |= ((uint32_t)(1 << PWM_CFG_EN));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Get duty cycle from channel.
|
||||
* Disable PWM channel.
|
||||
*
|
||||
* @param[in] channel Channel select (0..11).
|
||||
* @return Duty cycle (8-bit, LSB-aligned) of channel 'channel'.
|
||||
* @param[in] channel Channel select (0..15).
|
||||
**************************************************************************/
|
||||
uint8_t neorv32_pwm_get(int channel) {
|
||||
void neorv32_pwm_ch_disable(int channel) {
|
||||
|
||||
if (channel > 11) {
|
||||
return 0; // out of range
|
||||
}
|
||||
channel &= 0xf; // constrain range
|
||||
|
||||
uint32_t rd = NEORV32_PWM->DC[channel/4] >> (((channel % 4) * 8));
|
||||
|
||||
return (uint8_t)rd;
|
||||
NEORV32_PWM->CHANNEL_CFG[channel] &= ~((uint32_t)(1 << PWM_CFG_EN));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Set PWM channel's clock configuration.
|
||||
*
|
||||
* @param[in] channel Channel select (0..15).
|
||||
* @param[in] prsc Coarse clock prescaler select (3-bit, LSB-aligned). See #NEORV32_CLOCK_PRSC_enum.
|
||||
* @param[in] cdiv Fine clock divider value (10-bit, LSB-aligned).
|
||||
**************************************************************************/
|
||||
void neorv32_pwm_ch_set_clock(int channel, int prsc, int cdiv) {
|
||||
|
||||
channel &= 0xf; // constrain range
|
||||
|
||||
uint32_t tmp = NEORV32_PWM->CHANNEL_CFG[channel];
|
||||
tmp &= 0x800000ffU; // clear current prsc and cdiv, keep enable and duty
|
||||
tmp |= ((uint32_t)(prsc & 0x7U)) << PWM_CFG_PRSC_LSB;
|
||||
tmp |= ((uint32_t)(cdiv & 0x3ffU)) << PWM_CFG_CDIV_LSB;
|
||||
NEORV32_PWM->CHANNEL_CFG[channel] = tmp;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Set PWM channel's duty cycle.
|
||||
*
|
||||
* @param[in] channel Channel select (0..15).
|
||||
* @param[in] duty Duty cycle (8-bit, LSB-aligned).
|
||||
**************************************************************************/
|
||||
void neorv32_pwm_ch_set_duty(int channel, int duty) {
|
||||
|
||||
channel &= 0xf; // constrain range
|
||||
|
||||
uint32_t tmp = NEORV32_PWM->CHANNEL_CFG[channel];
|
||||
tmp &= 0xffffff00U; // clear current duty cycle configuration
|
||||
tmp |= (uint32_t)(duty & 0x000000ffU); // set new configuration
|
||||
NEORV32_PWM->CHANNEL_CFG[channel] = tmp;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* @see https://stnolting.github.io/neorv32/sw/files.html
|
||||
*/
|
||||
|
||||
#include "neorv32.h"
|
||||
#include <neorv32.h>
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue