URL
https://opencores.org/ocsvn/neo430/neo430/trunk
Subversion Repositories neo430
Compare Revisions
- This comparison shows the changes necessary to convert path
/neo430
- from Rev 194 to Rev 195
- ↔ Reverse comparison
Rev 194 → Rev 195
/trunk/neo430/README.md
3,7 → 3,9
[![Build Status](https://travis-ci.com/stnolting/neo430.svg?branch=master)](https://travis-ci.com/stnolting/neo430) |
[![last commit](https://img.shields.io/github/last-commit/stnolting/neo430)](https://github.com/stnolting/neo430/commits/master) |
[![issues](https://img.shields.io/github/issues/stnolting/neo430)](https://github.com/stnolting/neo430/issues) |
[![release](https://img.shields.io/github/v/release/stnolting/neo430)](https://github.com/stnolting/neo430/releases) |
[![license](https://img.shields.io/github/license/stnolting/neo430)](https://github.com/stnolting/neo430/blob/master/LICENSE) |
[![documentary](https://img.shields.io/badge/datasheet-neo430.pdf-blue)](https://raw.githubusercontent.com/stnolting/neo430/master/doc/NEO430.pdf) |
|
## Table of Content |
|
11,9 → 13,10
* [Processor Features](#Processor-Features) |
* [Differences to the Original MSP430 Processors](#Differences-to-the-Original-MSP430-Processors) |
* [Top Entity](#Top-Entity) |
* [Implementation Results](#Implementation-Results) |
* [FPGA Implementation Results](#FPGA-Implementation-Results) |
* [HW-SW Ecosystem](#HW-SW-Ecosystem) |
* [Performance](#Performance) |
* [Quick Start](#Quick-Start) |
* [**Quick Start**](#Quick-Start) |
* [Change Log](#Change-Log) |
* [Contact](#Contact) |
* [Disclaimer, Proprietary and Legal Notice](#Disclaimer-Proprietary-and-Legal-Notice) |
60,7 → 63,7
- 16-bit open source soft-core microcontroller-like processor system |
- Full support of the original [MSP430 instruction set architecture](https://raw.githubusercontent.com/stnolting/neo430/master/doc/instruction_set.pdf) |
- Code-efficient CISC-like instruction capabilities |
- Tool chain based on free [TI msp430-gcc compiler](http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/latest/index_FDS.html "TI `msp430-gcc` compiler") |
- Tool chain based on free [TI msp430-gcc compiler](http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/latest/index_FDS.html "TI `msp430-gcc` compiler") (also available here [on github](https://github.com/stnolting/msp430-gcc)) |
- Application compilation scripts ([makefiles](https://github.com/stnolting/neo430/blob/master/sw/example/blink_led/Makefile)) for Windows Powershell / Windows Subsystem for Linux / native Linux |
- Software requirements (regardless of platform): |
- TI `msp430-gcc` compiler |
72,7 → 75,7
- Internal [DMEM](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_dmem.vhd) (RAM, for data) and [IMEM](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_imem.vhd) (RAM or ROM, for code), configurable sizes |
- Customizable processor hardware configuration: |
- Optional multiplier/divider unit ([MULDIV](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_muldiv.vhd)) |
- Optional high-precision timer ([TIMER](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_timer.vhd)) with arbitrary frequency generator output |
- Optional high-precision timer ([TIMER](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_timer.vhd)) |
- Optional universal asynchronous receiver and transmitter ([UART](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_uart.vhd)) |
- Optional serial peripheral interface ([SPI](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_spi.vhd)), 8 or 16 bit tansfer data size, 6 dedicated CS lines |
- Optional I2C-compatible two wire serial interface ([TWI](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_twi.vhd)) supporting clock stretching |
84,6 → 87,7
- Optional 4 channel PWM controller with 4 or 8 bit resolution ([PWM](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_pwm.vhd)) |
- Optional Galois Ring Oscillator (GARO) based true random number generator ([TRNG](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_trng.vhd)) with de-biasing and internal post-processing |
- Optional external interrupts controller with 8 independent channels ([EXIRQ](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_exirq.vhd)), can also be used for software-triggered interrupts (traps, breakpoints, etc.) |
- Optional NCO-based programmable frequency generator with 3 independent channels ([FREQ_GEN](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_freq_gen.vhd)) |
- Optional internal [bootloader](https://github.com/stnolting/neo430/blob/master/sw/bootloader/bootloader.c) (2kB ROM) with serial user console and automatic boot from external SPI flash (like the FPGA configuration storage) |
|
|
115,6 → 119,7
If you need a top entity with resolved signals, take a look at the [top_templates](https://github.com/stnolting/neo430/blob/master/rtl/top_templates) folder. |
These alternative top entities also support AXI or Avalon connectivity. |
|
|
### Generics |
|
| Generic Name | Type | Default Value | Function | |
123,114 → 128,147
| IMEM_SIZE | natural | 4*1024 | Size of internal instruction memory in bytes (max 48 kB) | |
| DMEM_SIZE | natural | 2*1024 | Size of internal data memory in bytes (max 12 kB) | |
| USER_CODE | std_ulogic_vector(15:0) | x"0000" | 16-bit custom user code, can be read by user software | |
| MULDIV_USE | boolean | true | Implement multiplier/divider unit | |
| WB32_USE | boolean | true | Implement Wishbone interface adapter | |
| WDT_USE | boolean | true | Implement watchdog timer | |
| GPIO_USE | boolean | true | Implement general purpose parallel in/out port | |
| TIMER_USE | boolean | true | Implement high-precision timer | |
| UART_USE | boolean | true | Implement UART serial communication unit | |
| CRC_USE | boolean | true | Implement checksum computation unit | |
| CFU_USE | boolean | false | Implement custom functions unit | |
| PWM_USE | boolean | true | Implement pulse width controller | |
| TWI_USE | boolean | true | Implement two wire serial interface unit | |
| SPI_USE | boolean | true | Implement serial peripheral interface unit | |
| TRNG_USE | boolean | false | Implement true random number generator | |
| EXIRQ_USE | boolean | true | Implement external interrupts controller | |
| MULDIV_USE | boolean | true | Implement multiplier/divider unit (MULDIV) | |
| WB32_USE | boolean | true | Implement Wishbone interface adapter (WB32) | |
| WDT_USE | boolean | true | Implement watchdog timer (WDT) | |
| GPIO_USE | boolean | true | Implement general purpose parallel in/out port (GPIO) | |
| TIMER_USE | boolean | true | Implement high-precision timer (TIMER) | |
| UART_USE | boolean | true | Implement UART serial communication unit (UART) | |
| CRC_USE | boolean | true | Implement checksum computation unit (CRC16/32) | |
| CFU_USE | boolean | false | Implement custom functions unit (CFU) | |
| PWM_USE | boolean | true | Implement pulse width controller (PWM) | |
| TWI_USE | boolean | true | Implement two wire serial interface unit (TWI) | |
| SPI_USE | boolean | true | Implement serial peripheral interface unit (SPI) | |
| TRNG_USE | boolean | false | Implement true random number generator (TRNG) | |
| EXIRQ_USE | boolean | true | Implement external interrupts controller (EXIRQ) | |
| FREQ_GEN_USE | boolean | true | Implement programmable frequency generator (FREQ_GEN) | |
| BOOTLD_USE | boolean | true | Implement and auto-start internal bootloader | |
| IMEM_AS_ROM | boolean | false | Implement internal instruction memory as read-only | |
|
|
### Signals |
|
Note regarding unused unit's IO: Connect all unused inputs to low and leave all unused outputs 'open'. |
Signal driections are seen from the processor. |
|
| Signal Name | Width | Direction | HW Unit | Function | |
|:-------------|:-----:|:---------:|:-------:|:---------------------------------------------------------| |
| clk_i | 1 | In | - | Global clock line; all FFs triggering on rising edge | |
| rst_i | 1 | In | - | Global reset, low-active | |
| gpio_o | 16 | Out | GPIO | General purpose parallel output | |
| gpio_i | 16 | In | GPIO | General purpose parallel input | |
| pwm_o | 4 | Out | PWM | Pulse width modulation channels | |
| timer_fg_o | 1 | Out | TIMER | Arbitrar frequency generator output | |
| uart_txd_o | 1 | Out | UART | UART serial transmitter | |
| uart_rxd_i | 1 | In | UART | UARt serial receiver | |
| spi_sclk_o | 1 | Out | SPI | SPI master clock | |
| spi_mosi_o | 1 | Out | SPI | SPI serial data output | |
| spi_miso_i | 1 | In | SPI | SPI serial data input | |
| spi_cs_o | 8 | Out | SPI | SPI chip select lines (active-low) | |
| twi_sda_io | 1 | InOut | TWI | TWI master serial data line | |
| twi_scl_io | 1 | InOut | TWI | TWI master serial clock line | |
| wb_adr_o | 32 | Out | WB32 | Slave address | |
| wb_dat_i | 32 | In | WB32 | Write data | |
| wb_dat_o | 32 | Out | WB32 | Read data | |
| wb_we_o | 1 | Out | WB32 | Write enable | |
| wb_sel_o | 1 | Out | WB32 | Byte enable | |
| wb_stb_o | 1 | Out | WB32 | Strobe | |
| wb_cyc_o | 1 | Out | WB32 | Valid cycle | |
| wb_ack_i | 1 | In | WB32 | Transfer acknowledge | |
| ext_irq_i | 8 | In | EXIRQ | Interrupt request lines, high-active | |
| ext_ack_o | 8 | Out | EXIRQ | Interrupt acknowledge, high-active, single-shot | |
| Signal Name | Width | Direction | HW Unit | Function | |
|:-------------|:-----:|:---------:|:--------:|:---------------------------------------------------------| |
| clk_i | 1 | In | - | Global clock line; all FFs triggering on rising edge | |
| rst_i | 1 | In | - | Global reset, low-active | |
| gpio_o | 16 | Out | GPIO | General purpose parallel output | |
| gpio_i | 16 | In | GPIO | General purpose parallel input | |
| pwm_o | 4 | Out | PWM | Pulse width modulation channels | |
| timer_fg_o | 1 | Out | FREQ_GEN | Programmable frequency generator output | |
| uart_txd_o | 1 | Out | UART | UART serial transmitter | |
| uart_rxd_i | 1 | In | UART | UARt serial receiver | |
| spi_sclk_o | 1 | Out | SPI | SPI master clock | |
| spi_mosi_o | 1 | Out | SPI | SPI serial data output | |
| spi_miso_i | 1 | In | SPI | SPI serial data input | |
| spi_cs_o | 8 | Out | SPI | SPI chip select lines (active-low) | |
| twi_sda_io | 1 | InOut | TWI | TWI master serial data line (external pull-up required) | |
| twi_scl_io | 1 | InOut | TWI | TWI master serial clock line (external pull-up required) | |
| wb_adr_o | 32 | Out | WB32 | Wishbone slave address | |
| wb_dat_i | 32 | In | WB32 | Wishbone write data | |
| wb_dat_o | 32 | Out | WB32 | Wishbone read data | |
| wb_we_o | 1 | Out | WB32 | Wishbone write enable | |
| wb_sel_o | 1 | Out | WB32 | Wishbone byte enable | |
| wb_stb_o | 1 | Out | WB32 | Wishbone strobe | |
| wb_cyc_o | 1 | Out | WB32 | Wishbone valid cycle | |
| wb_ack_i | 1 | In | WB32 | Wishbone transfer acknowledge | |
| ext_irq_i | 8 | In | EXIRQ | Interrupt request lines, high-active | |
| ext_ack_o | 8 | Out | EXIRQ | Interrupt acknowledge, high-active, single-shot | |
|
|
|
## Implementation Results |
## FPGA Implementation Results |
|
Mapping results generated for HW version 0x0320. The full (default) hardware configuration includes |
Mapping results generated for HW version 0x0406. The full (default) hardware configuration includes |
all optional processor modules (excluding the CFU and the TRNG), an IMEM size of 4kB and a DMEM |
size of 2kB. The minimal configuration only includes the CPU and the GPIO module. Results generated with Xilinx Vivado 2017.3, |
Intel Quartus Prime Lite 17.1 and Lattice Radiant 1.1 (Synplify) |
size of 2kB. The minimal configuration only includes the CPU (including IMEM and DMEM) and the GPIO module. |
Results generated with Xilinx Vivado 2019.2, Intel Quartus Prime Lite 17.1 and Lattice Radiant 1.1 (Synplify) |
|
| __Xilinx Artix-7 (XC7A35TICSG324-1L)__ | LUTs | FFs | BRAMs | DSPs | f_max* | |
|:----------------------------------------|:----------:|:-----------:|:--------:|:------:|:-------:| |
| Full (default) configuration: | 983 (4.7%) | 1014 (2.5%) | 2.5 (5%) | 0 (0%) | 100 MHz | |
| Minimal configuration (CPU + GPIO): | 685 (3.3%) | 290 (0.7%) | 1 (2%) | 0 (0%) | 100 MHz | |
| __Xilinx Artix-7 (XC7A35TICSG324-1L)__ | LUTs | FFs | BRAMs | DSPs | f_max* | |
|:---------------------------------------|:---------:|:------------:|:--------:|:------:|:-------:| |
| Full (default) configuration: | 1036 (5%) | 1144 (2.75%) | 2.5 (5%) | 0 (0%) | 100 MHz | |
| Minimal configuration (CPU + GPIO): | 576 (3%) | 266 (0.6%) | 1 (2%) | 0 (0%) | 100 MHz | |
|
| __Intel Cyclone IV (EP4CE22F17C6)__ | LUTs | FFs | Memory bits | DSPs | f_max | |
|:-------------------------------------|:---------:|:--------:|:-----------:|:------:|:-------:| |
| Full (default) configuration: | 1648 (7%) | 990 (4%) | 65800 (11%) | 0 (0%) | 122 MHz | |
| Minimal configuration (CPU + GPIO): | 596 (3%) | 233 (1%) | 49408 (8%) | 0 (0%) | 126 MHz | |
| __Intel Cyclone IV (EP4CE22F17C6)__ | LUTs | FFs | Memory bits | DSPs | f_max | |
|:------------------------------------|:---------:|:---------:|:-----------:|:------:|:-------:| |
| Full (default) configuration: | 1869 (8%) | 1137 (5%) | 65800 (11%) | 0 (0%) | 121 MHz | |
| Minimal configuration (CPU + GPIO): | 590 (3%) | 230 (1%) | 49408 (8%) | 0 (0%) | 122 MHz | |
|
| __Lattice iCE40 UltraPlus (iCE40UP5K-SG48I)__ | LUTs | FFs | EBRs | DSPs | SRAMs | f_max* | |
|:-----------------------------------------------|:----------:|:----------:|:--------:|:------:|:------:|:------:| |
| Full (default) configuration: | 2600 (49%) | 1152 (21%) | 16 (53%) | 0 (0%) | 0 (0%) | 20 MHz | |
| Minimal configuration (CPU + GPIO): | 1365 (25%) | 493 (9%) | 12 (40%) | 0 (0%) | 0 (0%) | 20 MHz | |
| __Lattice iCE40 UltraPlus** (iCE40UP5K-SG48I)__ | LUTs | FFs | EBRs | DSPs | SRAMs | f_max* | |
|:-------------------------------------------------|:----------:|:----------:|:-------:|:------:|:-------:|:---------:| |
| Full (default) configuration: | 3928 (74%) | 1923 (36%) | 9 (30%) | 0 (0%) | 2 (50%) | 20.25 MHz | |
| Minimal configuration (CPU + GPIO + Bootloader): | 1812 (34%) | 755 (14%) | 4 (13%) | 0 (0%) | 2 (50%) | 20.25 MHz | |
|
*) Constrained |
|
**) Using optimized memory modules for IMEM (32kB) & DMEM(12kB) from the `rtl\fpga_specific\lattice_ice40up` folder |
|
|
### Device Utilization by Entity |
|
The following table shows the required resources for each module of the NEO430 processor system. Note that the provided |
numbers only represent a coarse overview as logic elements might be merged and optimized beyond module boundaries. |
numbers only represent a coarse overview as logic elements might be merged and optimized beyond entity boundaries. |
|
Mapping results generated for HW version 0x0320. The full (default) hardware configuration includes all optional |
Mapping results generated for HW version 0x0406. The full (default) hardware configuration includes all optional |
processor modules (excluding the CFU but including the TRNG), an IMEM size of 4kB and a DMEM size of |
2kB. Results were generated using Intel Quartus Prime Lite 17.1. |
|
| __Intel Cyclone IV (EP4CE22F17C6)__ | LUTs | FFs | Memory Bits | DSPs | |
|:---------------------------------------|:----:|:---:|:------------|:----:| |
|:---------------------------------------|:----:|:---:|:-----------:|:----:| |
| Bootloader Memory (Boot ROM, 2kB) | 2 | 1 | 16384 | 0 | |
| Central Processing Unit (CPU) | 506 | 171 | 256 | 0 | |
| Checksum Unit (CRC) | 110 | 94 | 0 | 0 | |
| Central Processing Unit (CPU) | 525 | 169 | 264 | 0 | |
| Checksum Unit (CRC) | 111 | 94 | 0 | 0 | |
| Custom Functions Unit (CFU)* | - | - | - | - | |
| Data Memory (DMEM, 2kB) | 6 | 1 | 16384 | 0 | |
| External Interrupts Controller (EXIRQ) | 72 | 54 | 0 | 0 | |
| High-Precision Timer (TIMER) | 70 | 55 | 0 | 0 | |
| Instruction Memory (IMEM, 4kB) | 4 | 1 | 32768 | 0 | |
| IO Port Unit (GPIO) | 49 | 45 | 0 | 0 | |
| Multiplier & Divider (MULDIV) | 184 | 131 | 0 | 0 | |
| Pulse-Width Modulation Unit (PWM) | 80 | 66 | 0 | 0 | |
| Serial Peripheral Interface (SPI) | 57 | 43 | 0 | 0 | |
| System Info Memory (SYSCONFIG) | 15 | 13 | 0 | 0 | |
| True Random Number Generator (TRNG) | 44 | 36 | 0 | 0 | |
| Two Wire Interface (TWI) | 80 | 41 | 0 | 0 | |
| Universal Asynchronous Rx/Tx (UART) | 129 | 89 | 0 | 0 | |
| Watchdog TImer (WDT) | 49 | 36 | 0 | 0 | |
| Wishbone Interface (WB32) | 128 | 117 | 0 | 0 | |
| Data Memory (DMEM, 2kB) | 5 | 1 | 16384 | 0 | |
| External Interrupts Controller (EXIRQ) | 70 | 55 | 0 | 0 | |
| Frequency Generator (FREQ_GEN) | 140 | 130 | 0 | 0 | |
| GPIO Port Unit (GPIO) | 50 | 45 | 0 | 0 | |
| High-Precision Timer (TIMER) | 66 | 57 | 0 | 0 | |
| Instruction Memory (IMEM, 4kB) | 5 | 1 | 32768 | 0 | |
| Multiplier & Divider (MULDIV) | 209 | 134 | 0 | 0 | |
| Pulse-Width Modulation Unit (PWM) | 96 | 66 | 0 | 0 | |
| Serial Peripheral Interface (SPI) | 82 | 59 | 0 | 0 | |
| System Info Memory (SYSCONFIG) | 12 | 11 | 0 | 0 | |
| True Random Number Generator (TRNG) | 92 | 76 | 0 | 0 | |
| Two Wire Interface (TWI) | 78 | 43 | 0 | 0 | |
| Universal Asynchronous Rx/Tx (UART) | 130 | 91 | 0 | 0 | |
| Watchdog Timer (WDT) | 53 | 37 | 0 | 0 | |
| Wishbone Interface (WB32) | 129 | 117 | 0 | 0 | |
|
*) Hardware requirements defined by user application |
|
|
|
## HW-SW Ecosystem |
|
The NEO430 Processor porjects provides driver libraries for the CPU itself and all included peripheral modules. These libraries |
provide a certain level of hardware abstraction and allow an easier usage of the different hardware module. Hw modules that cannot |
be "explicitly" used (like CPU modules or the different memories) are not listed below. Also, there is no CFU driver library or |
example project - this has to be provided by the CFU designer. |
|
| Hardware unit | VHDL source | C library source | C library header | SW example project | |
|:---------------------------------------|:-----------:|:----------------:|:----------------:|:------------------:| |
| Main CPU defines file | - | - | [neo430.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430.h) | - | |
| Central Processing Unit (CPU) | [neo430_cpu.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_cpu.vhd) | [neo430_cpu.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_cpu.c) | [neo430_cpu.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_cpu.h) |- | |
| Checksum Unit (CRC16/32) | [neo430_crc.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_crc.vhd) | [neo430_crc.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_crc.c) | [neo430_crc.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_crc.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/crc_test) | |
| External Interrupts Controller (EXIRQ) | [neo430_exirq.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_exirq.vhd) | [neo430_exirq.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_exirq.c) | [neo430_exirq.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_exirq.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/exirq_test) | |
| Frequency Generator (FREQ_GEN) | [neo430_freq_gen.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_freq_gen.vhd) | [neo430_freq_gen.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_freq_gen.c) | [neo430_freq_gen.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_freq_gen.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/freq_gen_demo) | |
| IO Port Unit (GPIO) | [neo430_gpio.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_gpio.vhd) | [neo430_gpio.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_gpio.c) | [neo430_gpio.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_gpio.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/blink_led) | |
| Multiplier & Divider (MULDIV) | [neo430_muldiv.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_muldiv.vhd) | [neo430_muldiv.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_muldiv.c) | [neo430_muldiv.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_muldiv.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/muldiv_test) | |
| Pulse-Width Modulation Unit (PWM) | [neo430_pwm.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_pwm.vhd) | [neo430_pwm.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_pwm.c) | [neo430_pwm.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_pwm.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/pwm_demo) | |
| Serial Peripheral Interface (SPI) | [neo430_spi.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_spi.vhd) | [neo430_spi.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_spi.c) | [neo430_spi.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_spi.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/bootloader) | |
| High-Precision Timer (TIMER) | [neo430_timer.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_timer.vhd) | [neo430_timer.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_timer.c) | [neo430_timer.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_timer.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/timer_simple) | |
| True Random Number Generator (TRNG) | [neo430_trng.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_trng.vhd) | [neo430_trng.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_trng.c) | [neo430_trng.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_trng.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/trng_test) | |
| Two Wire Interface (TWI) | [neo430_twi.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_twi.vhd) | [neo430_twi.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_twi.c) | [neo430_twi.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_twi.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/twi_test) | |
| Universal Asynchronous Rx/Tx (UART) | [neo430_uart.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_uart.vhd) | [neo430_uart.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_uart.c) | [neo430_uart.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_uart.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/uart_irq) | |
| Watchdog Timer (WDT) | [neo430_wdt.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_wdt.vhd) | [neo430_wdt.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_wdt.c) | [neo430_wdt.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_wdt.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/wdt_test) | |
| Wishbone Interface (WB32) | [neo430_wb_interface.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_wb_interface.vhd) | [neo430_wishbone.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_wishbone.c) | [neo430_wishbone.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_wishbone.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/wb_terminal) | |
|
|
|
## Performance |
|
In contrast to most mainstream processors the NEO430 processor does not implement a pipelined instruction execution. Instead, |
268,7 → 306,7
| -Os + NEO430_MULDIV* | 12.98 | 0.129 Coremarks/MHz | |
| -O2 + NEO430_MULDIV* | 15.26 | 0.152 Coremarks/MHz | |
|
*) Using the NEO430 MULDIV unit for the core of the matrix multiplications |
*) Using the NEO430 MULDIV unit for the core of the matrix multiplications. |
|
Even though a score of 6.57 can outnumber certain architectures and configurations (see the score table on the coremark |
homepage), the relative score of 0.065 coremarks per second might pretty low. But you have to keep in mind that benchmark |
297,9 → 335,13
* Next, install the free `MSP430-GCC` compiler toolchain from the TI homepage (select the "compiler only" package according to your system OS): |
|
https://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/latest/index_FDS.html |
|
* Alternatively, you can [directly download a copy](https://github.com/stnolting/msp430-gcc) of the msp430-gcc toolchain for Windows/Linux from github |
|
* Make sure `GNU Make` and a native `GCC` compiler are installed (double check for the newest versions) |
|
* Create a new HW project with your FPGA synthesis tool of choice. Add all files from the `rtl\core` folder to this project (and add them to a new library called "neo430"). |
|
* Follow the instructions from the "Let's Get It Started" section of the NEO430 documentary: [![NEO430 Datasheet](https://raw.githubusercontent.com/stnolting/neo430/master/doc/figures/PDF_32.png) NEO430 Datasheet](https://raw.githubusercontent.com/stnolting/neo430/master/doc/NEO430.pdf "NEO430 Datasheet from GitHub") |
|
* This documentary will guide you to create a simple test setup, which serves as ["hello word" FPGA demo](https://github.com/stnolting/neo430/blob/master/rtl/top_templates/neo430_test.vhd): |
330,7 → 372,7
|
## Citation |
|
If you are using the NEO430 for some kind of publication, please cite it as follows: |
If you are using the NEO430 in some kind of publication, please cite it as follows: |
|
> S. Nolting, "The NEO430 Processor", github.com/stnolting/neo430 |
|
340,8 → 382,6
|
This is a hobby project released under the BSD 3-Clause license. No copyright infringement intended. |
|
|
|
**BSD 3-Clause License** |
|
Copyright (c) 2020, Stephan Nolting. All rights reserved. |
382,7 → 422,11
"AXI", "AXI4" and "AXI4-Lite" are trademarks of Arm Holdings plc. |
|
|
[![Continous Integration provided by Travis CI](https://travis-ci.com/images/logos/TravisCI-Full-Color.png)](https://travis-ci.com/stnolting/neo430) |
|
Continous integration provided by [Travis CI](https://travis-ci.com/stnolting/neo430). |
|
|
![Open Source Hardware Logo https://www.oshwa.org](https://raw.githubusercontent.com/stnolting/neo430/master/doc/figures/oshw_logo.png) |
|
This project is not affiliated with or endorsed by the Open Source Initiative (https://www.oshwa.org / https://opensource.org). |
/trunk/neo430/doc/NEO430.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/neo430/doc/figures/neo430_arch.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/neo430/rtl/core/neo430_bootloader_image.vhd
516,25 → 516,25
000505 => x"4382", |
000506 => x"ffee", |
000507 => x"4382", |
000508 => x"ffa8", |
000509 => x"435c", |
000510 => x"12b0", |
000511 => x"f6a6", |
000512 => x"40b2", |
000513 => x"f00a", |
000514 => x"c000", |
000515 => x"403c", |
000516 => x"4b00", |
000517 => x"434d", |
000518 => x"12b0", |
000519 => x"f532", |
000508 => x"ff88", |
000509 => x"4382", |
000510 => x"ffa8", |
000511 => x"435c", |
000512 => x"12b0", |
000513 => x"f6a6", |
000514 => x"40b2", |
000515 => x"f00a", |
000516 => x"c000", |
000517 => x"403c", |
000518 => x"4b00", |
000519 => x"434d", |
000520 => x"12b0", |
000521 => x"f5d2", |
000522 => x"436c", |
000523 => x"12b0", |
000524 => x"f660", |
000525 => x"4382", |
000526 => x"ffb6", |
000521 => x"f532", |
000522 => x"12b0", |
000523 => x"f5d2", |
000524 => x"436c", |
000525 => x"12b0", |
000526 => x"f660", |
000527 => x"4382", |
000528 => x"ffb0", |
000529 => x"4038", |
968,10 → 968,10
000957 => x"0a0a", |
000958 => x"4c42", |
000959 => x"3a56", |
000960 => x"4d20", |
000961 => x"7261", |
000962 => x"3320", |
000963 => x"2031", |
000960 => x"4120", |
000961 => x"7270", |
000962 => x"3120", |
000963 => x"2037", |
000964 => x"3032", |
000965 => x"3032", |
000966 => x"480a", |
/trunk/neo430/rtl/core/neo430_control.vhd
375,6 → 375,8
ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback (only relevant for last two 'when') |
ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast) (only relevant for last two 'when' 4) |
mem_rd <= '1'; -- Memory read (only relevant for last two 'when' 5) |
ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2 |
ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC |
-- |
case am is -- addressing mode |
-- "000-" = CLASS II, SRC/DST: register direct [ACTUAL DON'T CARE; STATE NOT USED] |
408,10 → 410,10
-- "1101" = CLASS I, SRC: indirect, DST: indexed |
-- |
-- "1111" = CLASS I, SRC: indirect auto inc, DST: indexed |
ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC |
--> ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC |
ctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus |
--> ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast) |
ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2 |
--> ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2 |
--> ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back |
ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory |
420,10 → 422,10
|
when others => |
-- "1011" = CLASS I, SRC: indexed/symbolic/absolute, DST: indexed |
ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC |
--> ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC |
ctrl_nxt(ctrl_adr_mar_wr_c) <= '1'; -- write to MAR |
--> mem_rd <= '1'; -- Memory read |
ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2 |
--> ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2 |
--> ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back |
state_nxt <= TRANS_2; |
/trunk/neo430/rtl/core/neo430_freq_gen.vhd
0,0 → 1,194
-- ################################################################################################# |
-- # << NEO430 - Arbitrary Frequency Generator >> # |
-- # ********************************************************************************************* # |
-- # Number controlled oscillator-based frequency generator with three independent channels. Each # |
-- # channel has its enable flag, 16-bit tuning word register and prescaler selector. The phase # |
-- # accumulator of each channel is 17 bit wide. # |
-- # f_out(x) = ((f_cpu / nco_prsc(x)) * tuning_word(x)) / 2^17 for channels x = 0,1,2 # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
-- # # |
-- # Redistribution and use in source and binary forms, with or without modification, are # |
-- # permitted provided that the following conditions are met: # |
-- # # |
-- # 1. Redistributions of source code must retain the above copyright notice, this list of # |
-- # conditions and the following disclaimer. # |
-- # # |
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
-- # conditions and the following disclaimer in the documentation and/or other materials # |
-- # provided with the distribution. # |
-- # # |
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
-- # endorse or promote products derived from this software without specific prior written # |
-- # permission. # |
-- # # |
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
-- # OF THE POSSIBILITY OF SUCH DAMAGE. # |
-- # ********************************************************************************************* # |
-- # The NEO430 Processor - https://github.com/stnolting/neo430 # |
-- ################################################################################################# |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
library neo430; |
use neo430.neo430_package.all; |
|
entity neo430_freq_gen is |
port ( |
-- host access -- |
clk_i : in std_ulogic; -- global clock line |
rden_i : in std_ulogic; -- read enable |
wren_i : in std_ulogic; -- write enable |
addr_i : in std_ulogic_vector(15 downto 0); -- address |
data_i : in std_ulogic_vector(15 downto 0); -- data in |
data_o : out std_ulogic_vector(15 downto 0); -- data out |
-- clock generator -- |
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- frequency generator -- |
freq_gen_o : out std_ulogic_vector(02 downto 0) -- programmable frequency output |
); |
end neo430_freq_gen; |
|
architecture neo430_freq_gen_rtl of neo430_freq_gen is |
|
-- IO space: module base address -- |
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit |
constant lo_abb_c : natural := index_size_f(freq_gen_size_c); -- low address boundary bit |
|
-- control reg bits -- |
constant ctrl_en_ch0_c : natural := 0; -- r/w: enable NCO channel 0 |
constant ctrl_en_ch1_c : natural := 1; -- r/w: enable NCO channel 1 |
constant ctrl_en_ch2_c : natural := 2; -- r/w: enable NCO channel 2 |
constant ctrl_ch0_prsc0_c : natural := 3; -- r/w: prescaler select bit 0 for channel 0 |
constant ctrl_ch0_prsc1_c : natural := 4; -- r/w: prescaler select bit 1 for channel 0 |
constant ctrl_ch0_prsc2_c : natural := 5; -- r/w: prescaler select bit 2 for channel 0 |
constant ctrl_ch1_prsc0_c : natural := 6; -- r/w: prescaler select bit 0 for channel 1 |
constant ctrl_ch1_prsc1_c : natural := 7; -- r/w: prescaler select bit 1 for channel 1 |
constant ctrl_ch1_prsc2_c : natural := 8; -- r/w: prescaler select bit 2 for channel 1 |
constant ctrl_ch2_prsc0_c : natural := 9; -- r/w: prescaler select bit 0 for channel 2 |
constant ctrl_ch2_prsc1_c : natural := 10; -- r/w: prescaler select bit 1 for channel 2 |
constant ctrl_ch2_prsc2_c : natural := 11; -- r/w: prescaler select bit 2 for channel 2 |
|
-- access control -- |
signal acc_en : std_ulogic; -- module access enable |
signal addr : std_ulogic_vector(15 downto 0); -- access address |
signal wren : std_ulogic; -- word write enable |
signal rden : std_ulogic; -- word read enable |
|
-- accessible regs -- |
signal ctrl : std_ulogic_vector(11 downto 0); -- r/w: control register |
type tuning_word_t is array (0 to 2) of std_ulogic_vector(15 downto 0); |
signal tuning_word : tuning_word_t; -- -/w: tuning word channel 0,1,2 |
|
-- nco core -- |
type phase_accu_t is array (0 to 2) of std_ulogic_vector(16 downto 0); |
signal nco_phase_accu : phase_accu_t; |
signal nco_prsc_tick : std_ulogic_vector(2 downto 0); |
|
begin |
|
-- Access Control ----------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = freq_gen_base_c(hi_abb_c downto lo_abb_c)) else '0'; |
addr <= freq_gen_base_c(15 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 1) & '0'; -- word aligned |
wren <= acc_en and wren_i; |
rden <= acc_en and rden_i; |
|
|
-- Write access ------------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
wr_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (wren = '1') then |
if (addr = freq_gen_ctrl_addr_c) then |
ctrl(ctrl_en_ch0_c) <= data_i(ctrl_en_ch0_c); |
ctrl(ctrl_en_ch1_c) <= data_i(ctrl_en_ch1_c); |
ctrl(ctrl_en_ch2_c) <= data_i(ctrl_en_ch2_c); |
ctrl(ctrl_ch0_prsc0_c) <= data_i(ctrl_ch0_prsc0_c); |
ctrl(ctrl_ch0_prsc1_c) <= data_i(ctrl_ch0_prsc1_c); |
ctrl(ctrl_ch0_prsc2_c) <= data_i(ctrl_ch0_prsc2_c); |
ctrl(ctrl_ch1_prsc0_c) <= data_i(ctrl_ch1_prsc0_c); |
ctrl(ctrl_ch1_prsc1_c) <= data_i(ctrl_ch1_prsc1_c); |
ctrl(ctrl_ch1_prsc2_c) <= data_i(ctrl_ch1_prsc2_c); |
ctrl(ctrl_ch2_prsc0_c) <= data_i(ctrl_ch2_prsc0_c); |
ctrl(ctrl_ch2_prsc1_c) <= data_i(ctrl_ch2_prsc1_c); |
ctrl(ctrl_ch2_prsc2_c) <= data_i(ctrl_ch2_prsc2_c); |
end if; |
if (addr = freq_gen_tw_ch0_addr_c) then |
tuning_word(0) <= data_i; |
end if; |
if (addr = freq_gen_tw_ch1_addr_c) then |
tuning_word(1) <= data_i; |
end if; |
if (addr = freq_gen_tw_ch2_addr_c) then |
tuning_word(2) <= data_i; |
end if; |
end if; |
end if; |
end process wr_access; |
|
|
-- NCO core (number controlled oscillator) ---------------------------------- |
-- ----------------------------------------------------------------------------- |
nco_core: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- enable external clock generator -- |
clkgen_en_o <= ctrl(ctrl_en_ch0_c) or ctrl(ctrl_en_ch1_c) or ctrl(ctrl_en_ch2_c); |
-- NCOs -- |
for i in 0 to 2 loop |
-- NCO clock enable -- |
nco_prsc_tick(i) <= clkgen_i(to_integer(unsigned(ctrl(ctrl_ch0_prsc2_c + 3*i downto ctrl_ch0_prsc0_c + 3*i)))); |
-- phase accu -- |
if (ctrl(ctrl_en_ch0_c + i) = '0') then -- disabled |
nco_phase_accu(i) <= (others => '0'); |
elsif (nco_prsc_tick(i) = '1') then -- enabled; wait for clock enable tick |
nco_phase_accu(i) <= std_ulogic_vector(unsigned(nco_phase_accu(i)) + unsigned('0' & tuning_word(i))); |
end if; |
-- output -- |
freq_gen_o(i) <= nco_phase_accu(i)(16); -- MSB (carry_out) is output |
end loop; -- i - NCO channel |
end if; |
end process nco_core; |
|
|
-- Read access -------------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
rd_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
data_o <= (others => '0'); |
if (rden = '1') then |
-- if (addr = freq_gen_ctrl_addr_c) then |
data_o(ctrl_en_ch0_c) <= ctrl(ctrl_en_ch0_c); |
data_o(ctrl_en_ch1_c) <= ctrl(ctrl_en_ch1_c); |
data_o(ctrl_en_ch2_c) <= ctrl(ctrl_en_ch2_c); |
data_o(ctrl_ch0_prsc0_c) <= ctrl(ctrl_ch0_prsc0_c); |
data_o(ctrl_ch0_prsc1_c) <= ctrl(ctrl_ch0_prsc1_c); |
data_o(ctrl_ch0_prsc2_c) <= ctrl(ctrl_ch0_prsc2_c); |
data_o(ctrl_ch1_prsc0_c) <= ctrl(ctrl_ch1_prsc0_c); |
data_o(ctrl_ch1_prsc1_c) <= ctrl(ctrl_ch1_prsc1_c); |
data_o(ctrl_ch1_prsc2_c) <= ctrl(ctrl_ch1_prsc2_c); |
data_o(ctrl_ch2_prsc0_c) <= ctrl(ctrl_ch2_prsc0_c); |
data_o(ctrl_ch2_prsc1_c) <= ctrl(ctrl_ch2_prsc1_c); |
data_o(ctrl_ch2_prsc2_c) <= ctrl(ctrl_ch2_prsc2_c); |
-- end if; |
end if; |
end if; |
end process rd_access; |
|
|
end neo430_freq_gen_rtl; |
/trunk/neo430/rtl/core/neo430_muldiv.vhd
1,14 → 1,12
-- ################################################################################################# |
-- # << NEO430 - 16-Bit Unsigned Multiplier & Divider Unit >> # |
-- # ********************************************************************************************* # |
-- # NOTE: This unit uses "repeated trial subtraction" as division algorithm. # |
-- # NOTE: This unit uses "repeated trial subtraction" as division algorithm (restoring). # |
-- # NOTE: This unit uses "shifted add" as multiplication algorithm. Set 'use_dsp_mul_c' in the # |
-- # package file to TRUE to use DSP slices for multiplication. # |
-- # # |
-- # OpA is used for storing the first operand as well as for function configuration. Set this # |
-- # register to 0 reset the unit. Afterwards, set it to 0b01 for multiplication or to 0b10 for # |
-- # division. Afterwards, write the actual operand. The actual operation is started by # |
-- # writing OpB. # |
-- # The division unit only supports unsigned divisions. # |
-- # The multiplication unit supports signed and unsigned division. # |
-- # # |
-- # Division: DIVIDEND / DIVIDER = QUOTIENT + REMAINDER (16-bit) / DIVIDER (16-bit) # |
-- # Multiplication: FACTOR1 * FACTOR2 = PRODUCT (32-bit) # |
73,25 → 71,28
signal acc_en : std_ulogic; -- module access enable |
signal addr : std_ulogic_vector(15 downto 0); -- access address |
signal wr_en : std_ulogic; -- only full 16-bit word accesses! |
signal rd_en : std_ulogic; |
|
-- control -- |
signal ctrl_state : std_ulogic; |
signal operation : std_ulogic; -- '1' division, '0' multiplication |
signal func_rst : std_ulogic; |
|
-- accessible regs -- |
signal opa, opb : std_ulogic_vector(15 downto 0); |
signal resx, resy : std_ulogic_vector(15 downto 0); |
signal operation : std_ulogic; -- '1' division, '0' multiplication |
signal signed_op : std_ulogic; |
|
-- arithmetic core & arbitration -- |
signal start : std_ulogic; |
signal run : std_ulogic; |
signal enable : std_ulogic_vector(15 downto 0); |
signal try_sub : std_ulogic_vector(16 downto 0); |
signal remainder : std_ulogic_vector(15 downto 0); |
signal quotient : std_ulogic_vector(15 downto 0); |
signal product : std_ulogic_vector(31 downto 0); |
signal do_add : std_ulogic_vector(16 downto 0); |
signal start : std_ulogic; |
signal run : std_ulogic; |
signal enable : std_ulogic_vector(15 downto 0); |
signal try_sub : std_ulogic_vector(16 downto 0); |
signal remainder : std_ulogic_vector(15 downto 0); |
signal quotient : std_ulogic_vector(15 downto 0); |
signal product : std_ulogic_vector(31 downto 0); |
signal do_add : std_ulogic_vector(16 downto 0); |
signal sign_cycle : std_ulogic; |
signal opa_sext : std_ulogic; |
signal opb_sext : std_ulogic; |
signal p_sext : std_ulogic; |
signal dsp_mul_res : std_ulogic_vector(33 downto 0); |
|
begin |
|
100,6 → 101,7
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = muldiv_base_c(hi_abb_c downto lo_abb_c)) else '0'; |
addr <= muldiv_base_c(15 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 1) & '0'; -- word aligned |
wr_en <= acc_en and wren_i; |
rd_en <= acc_en and rden_i; |
|
|
-- Write access ------------------------------------------------------------- |
107,34 → 109,37
wr_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
start <= '0'; |
start <= '0'; |
opa_sext <= opa(opa'left) and signed_op; |
opb_sext <= opb(opb'left) and signed_op; |
if (wr_en = '1') then -- only full word accesses! |
-- operands -- |
if (addr = muldiv_opa_ctrl_addr_c) then -- reset/control OR dividend or mul_factor a |
opa <= data_i; |
if (addr = muldiv_opa_resx_addr_c) then -- dividend or factor 1 |
opa <= data_i; |
end if; |
if (addr = muldiv_opb_addr_c) then -- divisor or mul_factor b |
if (addr = muldiv_opb_umul_resy_addr_c) or |
(addr = muldiv_opb_smul_addr_c) or |
(addr = muldiv_opb_udiv_addr_c) then -- divisor or factor 2 |
opb <= data_i; |
start <= '1'; -- start operation |
start <= '1'; -- trigger operation |
end if; |
-- operation configuration -- |
if (func_rst = '1') then -- reset configuration |
ctrl_state <= '0'; |
elsif (ctrl_state = '0') then -- get new configuration |
if (wr_en = '1') then |
operation <= opa(1); -- '1' division, '0' multiplication |
ctrl_state <= '1'; |
end if; |
-- else -- execute configuration |
-- operation: division/multiplication -- |
if (addr = muldiv_opb_umul_resy_addr_c) or (addr = muldiv_opb_smul_addr_c) then -- multiplication |
operation <= '0'; |
else -- division |
operation <= '1'; |
end if; |
-- signed/unsigned operation -- |
if (addr = muldiv_opb_smul_addr_c) then |
signed_op <= '1'; |
else |
signed_op <= '0'; |
end if; |
end if; |
end if; |
end process wr_access; |
|
-- reset when OpA is zero -- |
func_rst <= '1' when (opa = x"0000") else '0'; |
|
|
-- Arithmetic core ---------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
arithmetic_core: process(clk_i) |
165,7 → 170,7
else |
if (use_dsp_mul_c = false) then -- implement serial multiplication |
if (start = '1') then -- load factor 1 |
product(31 downto 16) <= (others => '0'); |
product(31 downto 16) <= (others => opa_sext); |
product(15 downto 0) <= opa; |
elsif (run = '1') then |
product(31 downto 15) <= do_add(16 downto 0); |
172,19 → 177,36
product(14 downto 0) <= product(15 downto 1); |
end if; |
else -- use DSP for multiplication |
product(31 downto 0) <= std_ulogic_vector(unsigned(opa) * unsigned(opb)); |
product(31 downto 0) <= dsp_mul_res(31 downto 0); |
end if; |
end if; |
end if; |
end process arithmetic_core; |
|
-- DSP multiplication -- |
dsp_mul_res <= std_ulogic_vector(signed(opa_sext & opa) * signed(opb_sext & opb)); |
|
-- DIV: try another subtraction -- |
try_sub <= std_ulogic_vector(unsigned('0' & remainder(14 downto 0) & quotient(15)) - unsigned('0' & opb)); |
|
-- MUL: do another addition |
do_add <= std_ulogic_vector(unsigned('0' & product(31 downto 16)) + unsigned('0' & opb)) when (product(0) = '1') else ('0' & product(31 downto 16)); |
-- MUL: do another addition -- |
mul_update: process(product, sign_cycle, p_sext, opb_sext, opb) |
begin |
if (product(0) = '1') then |
if (sign_cycle = '1') then -- for signed operation only: take care of negative weighted MSB |
do_add <= std_ulogic_vector(unsigned(p_sext & product(31 downto 16)) - unsigned(opb_sext & opb)); |
else |
do_add <= std_ulogic_vector(unsigned(p_sext & product(31 downto 16)) + unsigned(opb_sext & opb)); |
end if; |
else |
do_add <= p_sext & product(31 downto 16); |
end if; |
end process mul_update; |
|
sign_cycle <= enable(enable'left) and signed_op; |
p_sext <= product(product'left) and signed_op; |
|
|
-- Read access -------------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
rd_access: process(clk_i) |
191,10 → 213,10
begin |
if rising_edge(clk_i) then |
data_o <= (others => '0'); |
if (acc_en = '1') and (rden_i = '1') then -- valid read access |
if (addr = muldiv_resx_addr_c) then |
if (rd_en = '1') then -- valid read access |
if (addr = muldiv_opa_resx_addr_c) then |
data_o <= resx; -- quotient or product low word |
else -- muldiv_resy_addr_c => |
else -- muldiv_opb_umul_resy_addr_c => |
data_o <= resy; -- remainder or product high word |
end if; |
end if; |
/trunk/neo430/rtl/core/neo430_package.vhd
40,7 → 40,7
|
-- Processor Hardware Version ------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant hw_version_c : std_ulogic_vector(15 downto 0) := x"0404"; -- no touchy! |
constant hw_version_c : std_ulogic_vector(15 downto 0) := x"0406"; -- no touchy! |
|
-- Danger Zone (Advanced Hardware Configuration) ------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
79,8 → 79,8
|
-- Boot ROM -- |
constant boot_base_c : std_ulogic_vector(15 downto 0) := x"F000"; -- bootloader base address, fixed! |
constant boot_size_c : natural := 2048; -- bytes, max 2048 bytes! |
constant boot_max_size_c : natural := 2048; -- bytes, fixed! |
constant boot_size_c : natural := 2*1024; -- bytes, max 2048 bytes! |
constant boot_max_size_c : natural := 2*1024; -- bytes, fixed! |
|
-- IO: Peripheral Devices ("IO") Area -- |
-- Each device must use 2 bytes or a multiple of 2 bytes as address space! |
92,19 → 92,19
constant muldiv_base_c : std_ulogic_vector(15 downto 0) := x"FF80"; |
constant muldiv_size_c : natural := 8; -- bytes |
|
constant muldiv_opa_ctrl_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0000"); |
constant muldiv_opb_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0002"); |
constant muldiv_resx_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0004"); |
constant muldiv_resy_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0006"); |
constant muldiv_opa_resx_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0000"); |
constant muldiv_opb_umul_resy_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0002"); |
constant muldiv_opb_smul_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0004"); |
constant muldiv_opb_udiv_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(muldiv_base_c) + x"0006"); |
|
-- IO: reserved -- |
--constant reserved_base_c : std_ulogic_vector(15 downto 0) := x"FF88"; |
--constant reserved_size_c : natural := 8; -- bytes |
-- IO: Frequency Generator (FREQ_GEN) -- |
constant freq_gen_base_c : std_ulogic_vector(15 downto 0) := x"FF88"; |
constant freq_gen_size_c : natural := 8; -- bytes |
|
--constant reserved_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(reserved_base_c) + x"0000"); |
--constant reserved_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(reserved_base_c) + x"0002"); |
--constant reserved_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(reserved_base_c) + x"0004"); |
--constant reserved_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(reserved_base_c) + x"0006"); |
constant freq_gen_ctrl_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(freq_gen_base_c) + x"0000"); |
constant freq_gen_tw_ch0_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(freq_gen_base_c) + x"0002"); |
constant freq_gen_tw_ch1_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(freq_gen_base_c) + x"0004"); |
constant freq_gen_tw_ch2_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(freq_gen_base_c) + x"0006"); |
|
-- IO: Wishbone32 Interface (WB32) -- |
constant wb32_base_c : std_ulogic_vector(15 downto 0) := x"FF90"; |
149,7 → 149,7
constant timer_ctrl_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(timer_base_c) + x"0000"); |
constant timer_cnt_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(timer_base_c) + x"0002"); |
constant timer_thres_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(timer_base_c) + x"0004"); |
constant timer_nco_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(timer_base_c) + x"0006"); |
--constant timer_???_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(timer_base_c) + x"0006"); |
|
-- IO: Watchdog Timer (WDT) -- |
constant wdt_base_c : std_ulogic_vector(15 downto 0) := x"FFB8"; |
360,8 → 360,8
gpio_i : in std_ulogic_vector(15 downto 0); -- parallel input |
-- pwm channels -- |
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels |
-- timer frequency generator -- |
timer_fg_o : out std_ulogic; -- programmable frequency output |
-- arbitrary frequency generator -- |
freq_gen_o : out std_ulogic_vector(02 downto 0); -- programmable frequency output |
-- serial com -- |
uart_txd_o : out std_ulogic; -- UART send data |
uart_rxd_i : in std_ulogic; -- UART receive data |
652,8 → 652,6
-- clock generator -- |
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- frequency generator -- |
timer_fg_o : out std_ulogic; -- programmable frequency output |
-- interrupt -- |
irq_o : out std_ulogic -- interrupt request |
); |
788,6 → 786,25
); |
end component; |
|
-- Component: Arbitrary Frequency Generator (FREG_GEN)) ----------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neo430_freq_gen |
port ( |
-- host access -- |
clk_i : in std_ulogic; -- global clock line |
rden_i : in std_ulogic; -- read enable |
wren_i : in std_ulogic; -- write enable |
addr_i : in std_ulogic_vector(15 downto 0); -- address |
data_i : in std_ulogic_vector(15 downto 0); -- data in |
data_o : out std_ulogic_vector(15 downto 0); -- data out |
-- clock generator -- |
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- frequency generator -- |
freq_gen_o : out std_ulogic_vector(02 downto 0) -- programmable frequency output |
); |
end component; |
|
-- Component: System Configuration (SYSCONFIG) -------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neo430_sysconfig |
812,6 → 829,7
SPI_USE : boolean := true; -- implement SPI? |
TRNG_USE : boolean := true; -- implement TRNG? |
EXIRQ_USE : boolean := true; -- implement EXIRQ? |
FREQ_GEN_USE : boolean := true; -- implement FREQ_GEN? |
-- boot configuration -- |
BOOTLD_USE : boolean := true; -- implement and use bootloader? |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? |
/trunk/neo430/rtl/core/neo430_pwm.vhd
157,7 → 157,7
end if; |
-- channels -- |
for i in 0 to num_pwm_channels_c-1 loop |
-- constrain to virtual size configured by SIZE register |
-- constrain to virtual size configured by SIZE control register bit |
if (unsigned(pwm_cnt and mask) >= unsigned(pwm_ch(i) and mask)) or (enable = '0') then |
pwm_out(i) <= '0'; |
else |
/trunk/neo430/rtl/core/neo430_sysconfig.vhd
64,6 → 64,7
SPI_USE : boolean := true; -- implement SPI? |
TRNG_USE : boolean := true; -- implement TRNG? |
EXIRQ_USE : boolean := true; -- implement EXIRQ? |
FREQ_GEN_USE : boolean := true; -- implement FREQ_GEN? |
-- boot configuration -- |
BOOTLD_USE : boolean := true; -- implement and use bootloader? |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? |
114,22 → 115,22
sysinfo_mem(0) <= hw_version_c; -- HW version |
|
-- CPUID1: System setup (available HW units / IO / peripheral devices) -- |
sysinfo_mem(1)(00) <= bool_to_ulogic_f(MULDIV_USE); -- MULDIV present? |
sysinfo_mem(1)(01) <= bool_to_ulogic_f(WB32_USE); -- WB32 present? |
sysinfo_mem(1)(02) <= bool_to_ulogic_f(WDT_USE); -- WDT present? |
sysinfo_mem(1)(03) <= bool_to_ulogic_f(GPIO_USE); -- GPIO present? |
sysinfo_mem(1)(04) <= bool_to_ulogic_f(TIMER_USE); -- TIMER present? |
sysinfo_mem(1)(05) <= bool_to_ulogic_f(UART_USE); -- UART present? |
sysinfo_mem(1)(06) <= '0'; -- reserved |
sysinfo_mem(1)(07) <= bool_to_ulogic_f(BOOTLD_USE); -- bootloader present? |
sysinfo_mem(1)(08) <= bool_to_ulogic_f(IMEM_AS_ROM); -- IMEM implemented as true ROM? |
sysinfo_mem(1)(09) <= bool_to_ulogic_f(CRC_USE); -- CRC present? |
sysinfo_mem(1)(10) <= bool_to_ulogic_f(CFU_USE); -- CFU present? |
sysinfo_mem(1)(11) <= bool_to_ulogic_f(PWM_USE); -- PWM present? |
sysinfo_mem(1)(12) <= bool_to_ulogic_f(TWI_USE); -- TWI present? |
sysinfo_mem(1)(13) <= bool_to_ulogic_f(SPI_USE); -- SPI present? |
sysinfo_mem(1)(14) <= bool_to_ulogic_f(TRNG_USE); -- TRNG present? |
sysinfo_mem(1)(15) <= bool_to_ulogic_f(EXIRQ_USE); -- EXIRQ present? |
sysinfo_mem(1)(00) <= '1' when (MULDIV_USE = true) else '0'; -- MULDIV present? |
sysinfo_mem(1)(01) <= '1' when (WB32_USE = true) else '0'; -- WB32 present? |
sysinfo_mem(1)(02) <= '1' when (WDT_USE = true) else '0'; -- WDT present? |
sysinfo_mem(1)(03) <= '1' when (GPIO_USE = true) else '0'; -- GPIO present? |
sysinfo_mem(1)(04) <= '1' when (TIMER_USE = true) else '0'; -- TIMER present? |
sysinfo_mem(1)(05) <= '1' when (UART_USE = true) else '0'; -- UART present? |
sysinfo_mem(1)(06) <= '1' when (FREQ_GEN_USE = true) else '0'; -- FREQ_GEN present? |
sysinfo_mem(1)(07) <= '1' when (BOOTLD_USE = true) else '0'; -- bootloader present? |
sysinfo_mem(1)(08) <= '1' when (IMEM_AS_ROM = true) else '0'; -- IMEM implemented as true ROM? |
sysinfo_mem(1)(09) <= '1' when (CRC_USE = true) else '0'; -- CRC present? |
sysinfo_mem(1)(10) <= '1' when (CFU_USE = true) else '0'; -- CFU present? |
sysinfo_mem(1)(11) <= '1' when (PWM_USE = true) else '0'; -- PWM present? |
sysinfo_mem(1)(12) <= '1' when (TWI_USE = true) else '0'; -- TWI present? |
sysinfo_mem(1)(13) <= '1' when (SPI_USE = true) else '0'; -- SPI present? |
sysinfo_mem(1)(14) <= '1' when (TRNG_USE = true) else '0'; -- TRNG present? |
sysinfo_mem(1)(15) <= '1' when (EXIRQ_USE = true) else '0'; -- EXIRQ present? |
|
-- CPUID2: User code -- |
sysinfo_mem(2) <= USER_CODE; |
/trunk/neo430/rtl/core/neo430_timer.vhd
5,8 → 5,6
-- # counter value reaches the programmable threshold an interrupt can be triggered. Optionally, # |
-- # the counter can be automatically reset when reaching the threshold value to restart counting. # |
-- # Configure THRES before enabling the timer to prevent false interrupt requests. # |
-- # The time also features a numerically controlled oscillator (NCO) for generating arbitrary # |
-- # frequency outputs: f_out = ((f_cpu / nco_prsc) * tuning_word[15:0]) / 2^17 # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
58,8 → 56,6
-- clock generator -- |
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- frequency generator -- |
timer_fg_o : out std_ulogic; -- programmable frequency output |
-- interrupt -- |
irq_o : out std_ulogic -- interrupt request |
); |
79,10 → 75,6
constant ctrl_prsc0_c : natural := 4; -- r/w: prescaler select bit 0 |
constant ctrl_prsc1_c : natural := 5; -- r/w: prescaler select bit 1 |
constant ctrl_prsc2_c : natural := 6; -- r/w: prescaler select bit 2 |
constant ctrl_nco_en_c : natural := 7; -- r/w: enable NCO |
constant ctrl_nco_prsc0_c : natural := 8; -- r/w: NCO prescaler select bit 0 |
constant ctrl_nco_prsc1_c : natural := 9; -- r/w: NCO prescaler select bit 1 |
constant ctrl_nco_prsc2_c : natural := 10; -- r/w: NCO prescaler select bit 2 |
|
-- access control -- |
signal acc_en : std_ulogic; -- module access enable |
90,23 → 82,18
signal wr_en : std_ulogic; -- word write enable |
|
-- timer regs -- |
signal ctrl : std_ulogic_vector(06 downto 0); -- r/w: control register |
signal thres : std_ulogic_vector(15 downto 0); -- -/w: threshold register |
signal cnt : std_ulogic_vector(15 downto 0); -- r/-: counter register |
signal thres : std_ulogic_vector(15 downto 0); -- -/w: threshold register |
signal ctrl : std_ulogic_vector(10 downto 0); -- r/w: control register |
|
-- prescaler clock generator -- |
signal prsc_tick : std_ulogic; |
|
-- timer control -- |
signal match : std_ulogic; -- thres = cnt |
signal match : std_ulogic; -- set if thres == cnt |
signal irq_fire : std_ulogic; |
signal irq_fire_ff : std_ulogic; |
|
-- nco -- |
signal nco_prsc_tick : std_ulogic; |
signal nco_tuning_word : std_ulogic_vector(15 downto 0); -- -/w: NCO tuning word |
signal nco_phase_accu : std_ulogic_vector(16 downto 0); |
|
begin |
|
-- Access Control ----------------------------------------------------------- |
126,21 → 113,14
thres <= data_i; |
end if; |
if (addr = timer_ctrl_addr_c) then |
ctrl(ctrl_en_c) <= data_i(ctrl_en_c); |
ctrl(ctrl_arst_c) <= data_i(ctrl_arst_c); |
ctrl(ctrl_irq_en_c) <= data_i(ctrl_irq_en_c); |
ctrl(ctrl_run_c) <= data_i(ctrl_run_c); |
ctrl(ctrl_prsc0_c) <= data_i(ctrl_prsc0_c); |
ctrl(ctrl_prsc1_c) <= data_i(ctrl_prsc1_c); |
ctrl(ctrl_prsc2_c) <= data_i(ctrl_prsc2_c); |
ctrl(ctrl_nco_en_c) <= data_i(ctrl_nco_en_c); |
ctrl(ctrl_nco_prsc0_c) <= data_i(ctrl_nco_prsc0_c); |
ctrl(ctrl_nco_prsc1_c) <= data_i(ctrl_nco_prsc1_c); |
ctrl(ctrl_nco_prsc2_c) <= data_i(ctrl_nco_prsc2_c); |
ctrl(ctrl_en_c) <= data_i(ctrl_en_c); |
ctrl(ctrl_arst_c) <= data_i(ctrl_arst_c); |
ctrl(ctrl_irq_en_c) <= data_i(ctrl_irq_en_c); |
ctrl(ctrl_run_c) <= data_i(ctrl_run_c); |
ctrl(ctrl_prsc0_c) <= data_i(ctrl_prsc0_c); |
ctrl(ctrl_prsc1_c) <= data_i(ctrl_prsc1_c); |
ctrl(ctrl_prsc2_c) <= data_i(ctrl_prsc2_c); |
end if; |
if (addr = timer_nco_addr_c) then |
nco_tuning_word <= data_i; |
end if; |
end if; |
end if; |
end process wr_access; |
181,25 → 161,6
irq_o <= irq_fire and (not irq_fire_ff); |
|
|
-- NCO core (number controlled oscillator) ---------------------------------- |
-- ----------------------------------------------------------------------------- |
nco_core: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- NCO clock enable -- |
nco_prsc_tick <= clkgen_i(to_integer(unsigned(ctrl(ctrl_nco_prsc2_c downto ctrl_nco_prsc0_c)))); |
-- phase accu -- |
if ((ctrl(ctrl_en_c) and ctrl(ctrl_nco_en_c)) = '0') then -- disabled |
nco_phase_accu <= (others => '0'); |
elsif (nco_prsc_tick = '1') then -- enabled; wait for clock enable tick |
nco_phase_accu <= std_ulogic_vector(unsigned(nco_phase_accu) + unsigned('0' & nco_tuning_word)); |
end if; |
-- output -- |
timer_fg_o <= nco_phase_accu(nco_phase_accu'left); -- MSB (carry_out) is output |
end if; |
end process nco_core; |
|
|
-- Read access -------------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
rd_access: process(clk_i) |
208,23 → 169,17
data_o <= (others => '0'); |
if (rden_i = '1') and (acc_en = '1') then |
if (addr = timer_ctrl_addr_c) then |
data_o(ctrl_en_c) <= ctrl(ctrl_en_c); |
data_o(ctrl_arst_c) <= ctrl(ctrl_arst_c); |
data_o(ctrl_irq_en_c) <= ctrl(ctrl_irq_en_c); |
data_o(ctrl_run_c) <= ctrl(ctrl_run_c); |
data_o(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c); |
data_o(ctrl_prsc1_c) <= ctrl(ctrl_prsc1_c); |
data_o(ctrl_prsc2_c) <= ctrl(ctrl_prsc2_c); |
data_o(ctrl_nco_en_c) <= ctrl(ctrl_nco_en_c); |
data_o(ctrl_nco_prsc0_c) <= ctrl(ctrl_nco_prsc0_c); |
data_o(ctrl_nco_prsc1_c) <= ctrl(ctrl_nco_prsc1_c); |
data_o(ctrl_nco_prsc2_c) <= ctrl(ctrl_nco_prsc2_c); |
data_o(ctrl_en_c) <= ctrl(ctrl_en_c); |
data_o(ctrl_arst_c) <= ctrl(ctrl_arst_c); |
data_o(ctrl_irq_en_c) <= ctrl(ctrl_irq_en_c); |
data_o(ctrl_run_c) <= ctrl(ctrl_run_c); |
data_o(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c); |
data_o(ctrl_prsc1_c) <= ctrl(ctrl_prsc1_c); |
data_o(ctrl_prsc2_c) <= ctrl(ctrl_prsc2_c); |
else--if (addr = timer_cnt_addr_c) then |
data_o <= cnt; |
-- else--if (addr = timer_thres_addr_c) then |
-- else -- (addr = timer_thres_addr_c) then |
-- data_o <= thres; |
-- else -- timer_nco_addr_c |
-- data_o <= nco_tuning_word; |
end if; |
end if; |
end if; |
/trunk/neo430/rtl/core/neo430_top.vhd
16,7 → 16,7
-- # - Optional 16-bit multiplier/divider unit (MULDIV) # |
-- # - Optional 16-bit IN and 16-bit OUT GPIO port with pin-change interrupt (GPIO) # |
-- # - Optional 32-bit Wishbone interface (WB32) # |
-- # - Optional High precision timer (TIMER) with frequency generator output # |
-- # - Optional High precision timer (TIMER) # |
-- # - Optional Universal Asynchronous Receiver and Transmitter (UART) # |
-- # - Optional Serial Peripheral Interface (SPI) # |
-- # - Optional Internal ROM for bootloader (BOOTLD) # |
27,6 → 27,7
-- # - Optional Two Wire Serial Interface (TWI) # |
-- # - Optional True Random Number Generator (TRNG) # |
-- # - Optional External Interrupts Controller (EXIRQ) # |
-- # - Optional Arbitrary Frequency Generator (FREQ_GEN) # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
102,8 → 103,8
gpio_i : in std_ulogic_vector(15 downto 0); -- parallel input |
-- pwm channels -- |
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels |
-- timer frequency generator -- |
timer_fg_o : out std_ulogic; -- programmable frequency output |
-- arbitrary frequency generator -- |
freq_gen_o : out std_ulogic_vector(02 downto 0); -- programmable frequency output |
-- serial com -- |
uart_txd_o : out std_ulogic; -- UART send data |
uart_rxd_i : in std_ulogic; -- UART receive data |
131,23 → 132,24
architecture neo430_top_rtl of neo430_top is |
|
-- generators -- |
signal rst_i_sync0 : std_ulogic; |
signal rst_i_sync1 : std_ulogic; |
signal rst_gen : std_ulogic_vector(03 downto 0) := (others => '0'); -- reset on bitstream upload |
signal ext_rst : std_ulogic; |
signal sys_rst : std_ulogic; |
signal wdt_rst : std_ulogic; |
signal clk_div : std_ulogic_vector(11 downto 0); |
signal clk_div_ff : std_ulogic_vector(11 downto 0); |
signal clk_gen : std_ulogic_vector(07 downto 0); |
signal timer_cg_en : std_ulogic; |
signal uart_cg_en : std_ulogic; |
signal spi_cg_en : std_ulogic; |
signal wdt_cg_en : std_ulogic; |
signal pwm_cg_en : std_ulogic; |
signal twi_cg_en : std_ulogic; |
signal cfu_cg_en : std_ulogic; |
|
signal rst_i_sync0 : std_ulogic; |
signal rst_i_sync1 : std_ulogic; |
signal rst_gen : std_ulogic_vector(03 downto 0) := (others => '0'); -- reset on bitstream upload |
signal ext_rst : std_ulogic; |
signal sys_rst : std_ulogic; |
signal wdt_rst : std_ulogic; |
signal clk_div : std_ulogic_vector(11 downto 0); |
signal clk_div_ff : std_ulogic_vector(11 downto 0); |
signal clk_gen : std_ulogic_vector(07 downto 0); |
signal timer_cg_en : std_ulogic; |
signal uart_cg_en : std_ulogic; |
signal spi_cg_en : std_ulogic; |
signal wdt_cg_en : std_ulogic; |
signal pwm_cg_en : std_ulogic; |
signal twi_cg_en : std_ulogic; |
signal cfu_cg_en : std_ulogic; |
signal freq_gen_cg_en : std_ulogic; |
|
type cpu_bus_t is record |
rd_en : std_ulogic; |
wr_en : std_ulogic_vector(01 downto 0); |
179,6 → 181,7
signal twi_rdata : std_ulogic_vector(15 downto 0); |
signal trng_rdata : std_ulogic_vector(15 downto 0); |
signal exirq_rdata : std_ulogic_vector(15 downto 0); |
signal freq_gen_rdata : std_ulogic_vector(15 downto 0); |
signal sysconfig_rdata : std_ulogic_vector(15 downto 0); |
|
-- interrupt system -- |
231,7 → 234,7
clk_div <= (others => '0'); |
elsif rising_edge(clk_i) then |
-- anybody needing fresh clocks? |
if ((timer_cg_en or uart_cg_en or spi_cg_en or wdt_cg_en or pwm_cg_en or twi_cg_en or cfu_cg_en) = '1') then |
if ((timer_cg_en or uart_cg_en or spi_cg_en or wdt_cg_en or pwm_cg_en or twi_cg_en or cfu_cg_en or freq_gen_cg_en) = '1') then |
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1); |
end if; |
end if; |
279,7 → 282,7
|
-- final CPU read data -- |
cpu_bus.rdata <= rom_rdata or ram_rdata or boot_rdata or muldiv_rdata or |
wb_rdata or uart_rdata or spi_rdata or gpio_rdata or |
wb_rdata or uart_rdata or spi_rdata or gpio_rdata or freq_gen_rdata or |
timer_rdata or wdt_rdata or sysconfig_rdata or crc_rdata or |
cfu_rdata or pwm_rdata or twi_rdata or trng_rdata or exirq_rdata; |
|
524,8 → 527,6
-- clock generator -- |
clkgen_en_o => timer_cg_en, -- enable clock generator |
clkgen_i => clk_gen, |
-- frequency generator -- |
timer_fg_o => timer_fg_o, -- programmable frequency output |
-- interrupt -- |
irq_o => timer_irq -- interrupt request |
); |
536,7 → 537,6
timer_rdata <= (others => '0'); |
timer_irq <= '0'; |
timer_cg_en <= '0'; |
timer_fg_o <= '0'; |
end generate; |
|
|
734,6 → 734,35
end generate; |
|
|
-- Arbitrary Frequency Generator (FREW_GEN)) -------------------------------- |
-- ----------------------------------------------------------------------------- |
neo430_freq_gen_inst_true: |
if (FREQ_GEN_USE = true) generate |
neo430_freq_gen_inst: neo430_freq_gen |
port map ( |
-- host access -- |
clk_i => clk_i, -- global clock line |
rden_i => io_rd_en, -- read enable |
wren_i => io_wr_en, -- write enable |
addr_i => cpu_bus.addr, -- address |
data_i => cpu_bus.wdata, -- data in |
data_o => freq_gen_rdata, -- data out |
-- clock generator -- |
clkgen_en_o => freq_gen_cg_en, -- enable clock generator |
clkgen_i => clk_gen, |
-- frequency generator -- |
freq_gen_o => freq_gen_o -- programmable frequency output |
); |
end generate; |
|
neo430_freq_gen_inst_false: |
if (FREQ_GEN_USE = false) generate |
freq_gen_cg_en <= '0'; |
freq_gen_rdata <= (others => '0'); |
freq_gen_o <= (others => '0'); |
end generate; |
|
|
-- System Configuration ----------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
neo430_sysconfig_inst: neo430_sysconfig |
758,6 → 787,7
SPI_USE => SPI_USE, -- implement SPI? |
TRNG_USE => TRNG_USE, -- implement TRNG? |
EXIRQ_USE => EXIRQ_USE, -- implement EXIRQ? |
FREQ_GEN_USE => FREQ_GEN_USE, -- implement FREQ_GEN? |
-- boot configuration -- |
BOOTLD_USE => BOOTLD_USE, -- implement and use bootloader? |
IMEM_AS_ROM => IMEM_AS_ROM -- implement IMEM as read-only memory? |
/trunk/neo430/rtl/top_templates/neo430_test.vhd
71,28 → 71,29
neo430_top_test_inst: neo430_top |
generic map ( |
-- general configuration -- |
CLOCK_SPEED => 100000000, -- main clock in Hz |
IMEM_SIZE => 4*1024, -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE => 2*1024, -- internal DMEM size in bytes, max 12kB (default=2kB) |
CLOCK_SPEED => 100000000, -- main clock in Hz |
IMEM_SIZE => 4*1024, -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE => 2*1024, -- internal DMEM size in bytes, max 12kB (default=2kB) |
-- additional configuration -- |
USER_CODE => x"CAFE", -- custom user code |
USER_CODE => x"CAFE", -- custom user code |
-- module configuration -- |
MULDIV_USE => true, -- implement multiplier/divider unit? (default=true) |
WB32_USE => true, -- implement WB32 unit? (default=true) |
WDT_USE => true, -- implement WDT? (default=true) |
GPIO_USE => true, -- implement GPIO unit? (default=true) |
TIMER_USE => true, -- implement timer? (default=true) |
UART_USE => true, -- implement UART? (default=true) |
CRC_USE => true, -- implement CRC unit? (default=true) |
CFU_USE => false, -- implement custom functions unit? (default=false) |
PWM_USE => true, -- implement PWM controller? (default=true) |
TWI_USE => true, -- implement two wire serial interface? (default=true) |
SPI_USE => true, -- implement SPI? (default=true) |
TRNG_USE => false, -- implement TRNG? (default=false) |
EXIRQ_USE => true, -- implement EXIRQ? (default=true) |
MULDIV_USE => true, -- implement multiplier/divider unit? (default=true) |
WB32_USE => true, -- implement WB32 unit? (default=true) |
WDT_USE => true, -- implement WDT? (default=true) |
GPIO_USE => true, -- implement GPIO unit? (default=true) |
TIMER_USE => true, -- implement timer? (default=true) |
UART_USE => true, -- implement UART? (default=true) |
CRC_USE => true, -- implement CRC unit? (default=true) |
CFU_USE => false, -- implement custom functions unit? (default=false) |
PWM_USE => true, -- implement PWM controller? (default=true) |
TWI_USE => true, -- implement two wire serial interface? (default=true) |
SPI_USE => true, -- implement SPI? (default=true) |
TRNG_USE => false, -- implement TRNG? (default=false) |
EXIRQ_USE => true, -- implement EXIRQ? (default=true) |
FREQ_GEN_USE => true, -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE => true, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => false -- implement IMEM as read-only memory? (default=false) |
BOOTLD_USE => true, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => false -- implement IMEM as read-only memory? (default=false) |
) |
port map ( |
-- global control -- |
103,8 → 104,8
gpio_i => x"0000", -- parallel input |
-- pwm channels -- |
pwm_o => open, -- pwm channels |
-- timer frequency generator -- |
timer_fg_o => open, -- programmable frequency output |
-- arbitrary frequency generator -- |
freq_gen_o => open, -- programmable frequency output |
-- serial com -- |
uart_txd_o => uart_txd_o, -- UART send data |
uart_rxd_i => uart_rxd_i, -- UART receive data |
/trunk/neo430/rtl/top_templates/neo430_top_avm.vhd
42,28 → 42,29
entity neo430_top_avm is |
generic ( |
-- general configuration -- |
CLOCK_SPEED : natural := 100000000; -- main clock in Hz |
IMEM_SIZE : natural := 4*1024; -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE : natural := 2*1024; -- internal DMEM size in bytes, max 12kB (default=2kB) |
CLOCK_SPEED : natural := 100000000; -- main clock in Hz |
IMEM_SIZE : natural := 4*1024; -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE : natural := 2*1024; -- internal DMEM size in bytes, max 12kB (default=2kB) |
-- additional configuration -- |
USER_CODE : std_logic_vector(15 downto 0) := x"0000"; -- custom user code |
USER_CODE : std_logic_vector(15 downto 0) := x"0000"; -- custom user code |
-- module configuration -- |
MULDIV_USE : boolean := true; -- implement multiplier/divider unit? (default=true) |
WB32_USE : boolean := true; -- implement WB32 unit? (default=true) |
WDT_USE : boolean := true; -- implement WDT? (default=true) |
GPIO_USE : boolean := true; -- implement GPIO unit? (default=true) |
TIMER_USE : boolean := true; -- implement timer? (default=true) |
UART_USE : boolean := true; -- implement UART? (default=true) |
CRC_USE : boolean := true; -- implement CRC unit? (default=true) |
CFU_USE : boolean := false; -- implement custom functions unit? (default=false) |
PWM_USE : boolean := true; -- implement PWM controller? |
TWI_USE : boolean := true; -- implement two wire serial interface? (default=true) |
SPI_USE : boolean := true; -- implement SPI? (default=true) |
TRNG_USE : boolean := false; -- implement TRNG? (default=false) |
EXIRQ_USE : boolean := true; -- implement EXIRQ? (default=true) |
MULDIV_USE : boolean := true; -- implement multiplier/divider unit? (default=true) |
WB32_USE : boolean := true; -- implement WB32 unit? (default=true) |
WDT_USE : boolean := true; -- implement WDT? (default=true) |
GPIO_USE : boolean := true; -- implement GPIO unit? (default=true) |
TIMER_USE : boolean := true; -- implement timer? (default=true) |
UART_USE : boolean := true; -- implement UART? (default=true) |
CRC_USE : boolean := true; -- implement CRC unit? (default=true) |
CFU_USE : boolean := false; -- implement custom functions unit? (default=false) |
PWM_USE : boolean := true; -- implement PWM controller? |
TWI_USE : boolean := true; -- implement two wire serial interface? (default=true) |
SPI_USE : boolean := true; -- implement SPI? (default=true) |
TRNG_USE : boolean := false; -- implement TRNG? (default=false) |
EXIRQ_USE : boolean := true; -- implement EXIRQ? (default=true) |
FREQ_GEN_USE : boolean := true; -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE : boolean := true; -- implement and use bootloader? (default=true) |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? (default=false) |
BOOTLD_USE : boolean := true; -- implement and use bootloader? (default=true) |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? (default=false) |
); |
port ( |
-- global control -- |
74,8 → 75,8
gpio_i : in std_logic_vector(15 downto 0); -- parallel input |
-- pwm channels -- |
pwm_o : out std_logic_vector(03 downto 0); -- pwm channels |
-- timer frequency generator -- |
timer_fg_o : out std_logic; -- programmable frequency output |
-- arbitrary frequency generator -- |
freq_gen_o : out std_logic_vector(02 downto 0); -- programmable frequency output |
-- UART -- |
uart_txd_o : out std_logic; -- UART send data |
uart_rxd_i : in std_logic; -- UART receive data |
142,7 → 143,7
signal spi_cs_o_int : std_ulogic_vector(05 downto 0); |
signal irq_i_int : std_ulogic_vector(07 downto 0); |
signal irq_ack_o_int : std_ulogic_vector(07 downto 0); |
signal timer_fg_o_int : std_ulogic; |
signal freq_gen_o_int : std_ulogic_vector(02 downto 0); |
constant usrcode_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(USER_CODE); |
|
-- misc -- |
155,28 → 156,29
neo430_top_inst: neo430_top |
generic map ( |
-- general configuration -- |
CLOCK_SPEED => CLOCK_SPEED, -- main clock in Hz |
IMEM_SIZE => IMEM_SIZE, -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE => DMEM_SIZE, -- internal DMEM size in bytes, max 12kB (default=2kB) |
CLOCK_SPEED => CLOCK_SPEED, -- main clock in Hz |
IMEM_SIZE => IMEM_SIZE, -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE => DMEM_SIZE, -- internal DMEM size in bytes, max 12kB (default=2kB) |
-- additional configuration -- |
USER_CODE => usrcode_c, -- custom user code |
USER_CODE => usrcode_c, -- custom user code |
-- module configuration -- |
MULDIV_USE => MULDIV_USE, -- implement multiplier/divider unit? (default=true) |
WB32_USE => WB32_USE, -- implement WB32 unit? (default=true) |
WDT_USE => WDT_USE, -- implement WDT? (default=true) |
GPIO_USE => GPIO_USE, -- implement GPIO unit? (default=true) |
TIMER_USE => TIMER_USE, -- implement timer? (default=true) |
UART_USE => UART_USE, -- implement UART? (default=true) |
CRC_USE => CRC_USE, -- implement CRC unit? (default=true) |
CFU_USE => CFU_USE, -- implement CF unit? (default=false) |
PWM_USE => PWM_USE, -- implement PWM controller? (default=true) |
TWI_USE => TWI_USE, -- implement two wire serial interface? (default=true) |
SPI_USE => SPI_USE, -- implement SPI? (default=true) |
TRNG_USE => TRNG_USE, -- implement TRNG? (default=false) |
EXIRQ_USE => EXIRQ_USE, -- implement EXIRQ? (default=true) |
MULDIV_USE => MULDIV_USE, -- implement multiplier/divider unit? (default=true) |
WB32_USE => WB32_USE, -- implement WB32 unit? (default=true) |
WDT_USE => WDT_USE, -- implement WDT? (default=true) |
GPIO_USE => GPIO_USE, -- implement GPIO unit? (default=true) |
TIMER_USE => TIMER_USE, -- implement timer? (default=true) |
UART_USE => UART_USE, -- implement UART? (default=true) |
CRC_USE => CRC_USE, -- implement CRC unit? (default=true) |
CFU_USE => CFU_USE, -- implement CF unit? (default=false) |
PWM_USE => PWM_USE, -- implement PWM controller? (default=true) |
TWI_USE => TWI_USE, -- implement two wire serial interface? (default=true) |
SPI_USE => SPI_USE, -- implement SPI? (default=true) |
TRNG_USE => TRNG_USE, -- implement TRNG? (default=false) |
EXIRQ_USE => EXIRQ_USE, -- implement EXIRQ? (default=true) |
FREQ_GEN_USE => FREQ_GEN_USE, -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE => BOOTLD_USE, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => IMEM_AS_ROM -- implement IMEM as read-only memory? (default=false) |
BOOTLD_USE => BOOTLD_USE, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => IMEM_AS_ROM -- implement IMEM as read-only memory? (default=false) |
) |
port map ( |
-- global control -- |
187,6 → 189,8
gpio_i => gpio_i_int, -- parallel input |
-- pwm channels -- |
pwm_o => pwm_o_int, -- pwm channels |
-- arbitrary frequency generator -- |
freq_gen_o => freq_gen_o_int, -- programmable frequency output |
-- serial com -- |
uart_txd_o => uart_txd_o_int, -- UART send data |
uart_rxd_i => uart_rxd_i_int, -- UART receive data |
227,7 → 231,7
spi_mosi_o <= std_logic(spi_mosi_o_int); |
spi_cs_o <= std_logic_vector(spi_cs_o_int); |
ext_ack_o <= std_logic_vector(irq_ack_o_int); |
timer_fg_o <= std_logic(timer_fg_o_int); |
freq_gen_o <= std_logic_vector(freq_gen_o_int); |
|
|
-- Wishbone-to-Avalon Bridge ------------------------------------------------ |
/trunk/neo430/rtl/top_templates/neo430_top_axi4lite.vhd
42,28 → 42,29
entity neo430_top_axi4lite is |
generic ( |
-- general configuration -- |
CLOCK_SPEED : natural := 100000000; -- main clock in Hz |
IMEM_SIZE : natural := 4*1024; -- internal IMEM size in bytes, max 32kB (default=4kB) |
DMEM_SIZE : natural := 2*1024; -- internal DMEM size in bytes, max 28kB (default=2kB) |
CLOCK_SPEED : natural := 100000000; -- main clock in Hz |
IMEM_SIZE : natural := 4*1024; -- internal IMEM size in bytes, max 32kB (default=4kB) |
DMEM_SIZE : natural := 2*1024; -- internal DMEM size in bytes, max 28kB (default=2kB) |
-- additional configuration -- |
USER_CODE : std_logic_vector(15 downto 0) := x"0000"; -- custom user code |
USER_CODE : std_logic_vector(15 downto 0) := x"0000"; -- custom user code |
-- module configuration -- |
MULDIV_USE : boolean := true; -- implement multiplier/divider unit? (default=true) |
WB32_USE : boolean := true; -- implement WB32 unit? (default=true) |
WDT_USE : boolean := true; -- implement WDT? (default=true) |
GPIO_USE : boolean := true; -- implement GPIO unit? (default=true) |
TIMER_USE : boolean := true; -- implement timer? (default=true) |
UART_USE : boolean := true; -- implement UART? (default=true) |
CRC_USE : boolean := true; -- implement CRC unit? (default=true) |
CFU_USE : boolean := false; -- implement custom functions unit? (default=false) |
PWM_USE : boolean := true; -- implement PWM controller? |
TWI_USE : boolean := true; -- implement two wire serial interface? (default=true) |
SPI_USE : boolean := true; -- implement SPI? (default=true) |
TRNG_USE : boolean := false; -- implement TRNG? (default=false) |
EXIRQ_USE : boolean := true; -- implement EXIRQ? (default=true) |
MULDIV_USE : boolean := true; -- implement multiplier/divider unit? (default=true) |
WB32_USE : boolean := true; -- implement WB32 unit? (default=true) |
WDT_USE : boolean := true; -- implement WDT? (default=true) |
GPIO_USE : boolean := true; -- implement GPIO unit? (default=true) |
TIMER_USE : boolean := true; -- implement timer? (default=true) |
UART_USE : boolean := true; -- implement UART? (default=true) |
CRC_USE : boolean := true; -- implement CRC unit? (default=true) |
CFU_USE : boolean := false; -- implement custom functions unit? (default=false) |
PWM_USE : boolean := true; -- implement PWM controller? |
TWI_USE : boolean := true; -- implement two wire serial interface? (default=true) |
SPI_USE : boolean := true; -- implement SPI? (default=true) |
TRNG_USE : boolean := false; -- implement TRNG? (default=false) |
EXIRQ_USE : boolean := true; -- implement EXIRQ? (default=true) |
FREQ_GEN_USE : boolean := true; -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE : boolean := true; -- implement and use bootloader? (default=true) |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? (default=false) |
BOOTLD_USE : boolean := true; -- implement and use bootloader? (default=true) |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? (default=false) |
); |
port ( |
-- GPIO -- |
71,8 → 72,8
gpio_i : in std_logic_vector(15 downto 0); -- parallel input |
-- pwm channels -- |
pwm_o : out std_logic_vector(03 downto 0); -- pwm channels |
-- timer frequency generator -- |
timer_fg_o : out std_logic; -- programmable frequency output |
-- arbitrary frequency generator -- |
freq_gen_o : out std_logic_vector(02 downto 0); -- programmable frequency output |
-- UART -- |
uart_txd_o : out std_logic; -- UART send data |
uart_rxd_i : in std_logic; -- UART receive data |
144,7 → 145,7
signal spi_cs_o_int : std_ulogic_vector(05 downto 0); |
signal irq_i_int : std_ulogic_vector(07 downto 0); |
signal irq_ack_o_int : std_ulogic_vector(07 downto 0); |
signal timer_fg_o_int : std_ulogic; |
signal freq_gen_o_int : std_ulogic_vector(02 downto 0); |
constant usrcode_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(USER_CODE); |
|
-- AXI arbiter -- |
162,28 → 163,29
neo430_top_inst: neo430_top |
generic map ( |
-- general configuration -- |
CLOCK_SPEED => CLOCK_SPEED, -- main clock in Hz |
IMEM_SIZE => IMEM_SIZE, -- internal IMEM size in bytes, max 32kB (default=4kB) |
DMEM_SIZE => DMEM_SIZE, -- internal DMEM size in bytes, max 28kB (default=2kB) |
CLOCK_SPEED => CLOCK_SPEED, -- main clock in Hz |
IMEM_SIZE => IMEM_SIZE, -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE => DMEM_SIZE, -- internal DMEM size in bytes, max 12kB (default=2kB) |
-- additional configuration -- |
USER_CODE => usrcode_c, -- custom user code |
USER_CODE => usrcode_c, -- custom user code |
-- module configuration -- |
MULDIV_USE => MULDIV_USE, -- implement multiplier/divider unit? (default=true) |
WB32_USE => WB32_USE, -- implement WB32 unit? (default=true) |
WDT_USE => WDT_USE, -- implement WDT? (default=true) |
GPIO_USE => GPIO_USE, -- implement GPIO unit? (default=true) |
TIMER_USE => TIMER_USE, -- implement timer? (default=true) |
UART_USE => UART_USE, -- implement UART? (default=true) |
CRC_USE => CRC_USE, -- implement CRC unit? (default=true) |
CFU_USE => CFU_USE, -- implement CF unit? (default=false) |
PWM_USE => PWM_USE, -- implement PWM controller? (default=true) |
TWI_USE => TWI_USE, -- implement two wire serial interface? (default=true) |
SPI_USE => SPI_USE, -- implement SPI? (default=true) |
TRNG_USE => TRNG_USE, -- implement TRNG? (default=false) |
EXIRQ_USE => EXIRQ_USE, -- implement EXIRQ? (default=true) |
MULDIV_USE => MULDIV_USE, -- implement multiplier/divider unit? (default=true) |
WB32_USE => WB32_USE, -- implement WB32 unit? (default=true) |
WDT_USE => WDT_USE, -- implement WDT? (default=true) |
GPIO_USE => GPIO_USE, -- implement GPIO unit? (default=true) |
TIMER_USE => TIMER_USE, -- implement timer? (default=true) |
UART_USE => UART_USE, -- implement UART? (default=true) |
CRC_USE => CRC_USE, -- implement CRC unit? (default=true) |
CFU_USE => CFU_USE, -- implement CF unit? (default=false) |
PWM_USE => PWM_USE, -- implement PWM controller? (default=true) |
TWI_USE => TWI_USE, -- implement two wire serial interface? (default=true) |
SPI_USE => SPI_USE, -- implement SPI? (default=true) |
TRNG_USE => TRNG_USE, -- implement TRNG? (default=false) |
EXIRQ_USE => EXIRQ_USE, -- implement EXIRQ? (default=true) |
FREQ_GEN_USE => FREQ_GEN_USE, -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE => BOOTLD_USE, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => IMEM_AS_ROM -- implement IMEM as read-only memory? (default=false) |
BOOTLD_USE => BOOTLD_USE, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => IMEM_AS_ROM -- implement IMEM as read-only memory? (default=false) |
) |
port map ( |
-- global control -- |
194,6 → 196,8
gpio_i => gpio_i_int, -- parallel input |
-- pwm channels -- |
pwm_o => pwm_o_int, -- pwm channels |
-- arbitrary frequency generator -- |
freq_gen_o => freq_gen_o_int, -- programmable frequency output |
-- serial com -- |
uart_txd_o => uart_txd_o_int, -- UART send data |
uart_rxd_i => uart_rxd_i_int, -- UART receive data |
232,7 → 236,7
spi_mosi_o <= std_logic(spi_mosi_o_int); |
spi_cs_o <= std_logic_vector(spi_cs_o_int); |
ext_ack_o <= std_logic_vector(irq_ack_o_int); |
timer_fg_o <= std_logic(timer_fg_o_int); |
freq_gen_o <= std_logic_vector(freq_gen_o_int); |
|
|
-- Wishbone-to-AXI4-Lite-compatible Bridge ---------------------------------- |
/trunk/neo430/rtl/top_templates/neo430_top_std_logic.vhd
42,28 → 42,29
entity neo430_top_std_logic is |
generic ( |
-- general configuration -- |
CLOCK_SPEED : natural := 100000000; -- main clock in Hz |
IMEM_SIZE : natural := 4*1024; -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE : natural := 2*1024; -- internal DMEM size in bytes, max 12kB (default=2kB) |
CLOCK_SPEED : natural := 100000000; -- main clock in Hz |
IMEM_SIZE : natural := 4*1024; -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE : natural := 2*1024; -- internal DMEM size in bytes, max 12kB (default=2kB) |
-- additional configuration -- |
USER_CODE : std_logic_vector(15 downto 0) := x"0000"; -- custom user code |
USER_CODE : std_logic_vector(15 downto 0) := x"0000"; -- custom user code |
-- module configuration -- |
MULDIV_USE : boolean := true; -- implement multiplier/divider unit? (default=true) |
WB32_USE : boolean := true; -- implement WB32 unit? (default=true) |
WDT_USE : boolean := true; -- implement WDT? (default=true) |
GPIO_USE : boolean := true; -- implement GPIO unit? (default=true) |
TIMER_USE : boolean := true; -- implement timer? (default=true) |
UART_USE : boolean := true; -- implement UART? (default=true) |
CRC_USE : boolean := true; -- implement CRC unit? (default=true) |
CFU_USE : boolean := false; -- implement custom functions unit? (default=false) |
PWM_USE : boolean := true; -- implement PWM controller? |
TWI_USE : boolean := true; -- implement two wire serial interface? (default=true) |
SPI_USE : boolean := true; -- implement SPI? (default=true) |
TRNG_USE : boolean := false; -- implement TRNG? (default=false) |
EXIRQ_USE : boolean := true; -- implement EXIRQ? (default=true) |
MULDIV_USE : boolean := true; -- implement multiplier/divider unit? (default=true) |
WB32_USE : boolean := true; -- implement WB32 unit? (default=true) |
WDT_USE : boolean := true; -- implement WDT? (default=true) |
GPIO_USE : boolean := true; -- implement GPIO unit? (default=true) |
TIMER_USE : boolean := true; -- implement timer? (default=true) |
UART_USE : boolean := true; -- implement UART? (default=true) |
CRC_USE : boolean := true; -- implement CRC unit? (default=true) |
CFU_USE : boolean := false; -- implement custom functions unit? (default=false) |
PWM_USE : boolean := true; -- implement PWM controller? |
TWI_USE : boolean := true; -- implement two wire serial interface? (default=true) |
SPI_USE : boolean := true; -- implement SPI? (default=true) |
TRNG_USE : boolean := false; -- implement TRNG? (default=false) |
EXIRQ_USE : boolean := true; -- implement EXIRQ? (default=true) |
FREQ_GEN_USE : boolean := true; -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE : boolean := true; -- implement and use bootloader? (default=true) |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? (default=false) |
BOOTLD_USE : boolean := true; -- implement and use bootloader? (default=true) |
IMEM_AS_ROM : boolean := false -- implement IMEM as read-only memory? (default=false) |
); |
port ( |
-- global control -- |
74,8 → 75,8
gpio_i : in std_logic_vector(15 downto 0); -- parallel input |
-- pwm channels -- |
pwm_o : out std_logic_vector(03 downto 0); -- pwm channels |
-- timer frequency generator -- |
timer_fg_o : out std_logic; -- programmable frequency output |
-- arbitrary frequency generator -- |
freq_gen_o : out std_logic_vector(02 downto 0); -- programmable frequency output |
-- serial com -- |
uart_txd_o : out std_logic; -- UART send data |
uart_rxd_i : in std_logic; -- UART receive data |
125,7 → 126,7
signal wb_stb_o_int : std_ulogic; |
signal wb_cyc_o_int : std_ulogic; |
signal wb_ack_i_int : std_ulogic; |
signal timer_fg_o_int : std_ulogic; |
signal freq_gen_o_int : std_ulogic_vector(02 downto 0); |
|
begin |
|
134,28 → 135,29
neo430_top_inst: neo430_top |
generic map ( |
-- general configuration -- |
CLOCK_SPEED => CLOCK_SPEED, -- main clock in Hz |
IMEM_SIZE => IMEM_SIZE, -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE => DMEM_SIZE, -- internal DMEM size in bytes, max 12kB (default=2kB) |
CLOCK_SPEED => CLOCK_SPEED, -- main clock in Hz |
IMEM_SIZE => IMEM_SIZE, -- internal IMEM size in bytes, max 48kB (default=4kB) |
DMEM_SIZE => DMEM_SIZE, -- internal DMEM size in bytes, max 12kB (default=2kB) |
-- additional configuration -- |
USER_CODE => usrcode_c, -- custom user code |
USER_CODE => usrcode_c, -- custom user code |
-- module configuration -- |
MULDIV_USE => MULDIV_USE, -- implement multiplier/divider unit? (default=true) |
WB32_USE => WB32_USE, -- implement WB32 unit? (default=true) |
WDT_USE => WDT_USE, -- implement WDT? (default=true) |
GPIO_USE => GPIO_USE, -- implement GPIO unit? (default=true) |
TIMER_USE => TIMER_USE, -- implement timer? (default=true) |
UART_USE => UART_USE, -- implement UART? (default=true) |
CRC_USE => CRC_USE, -- implement CRC unit? (default=true) |
CFU_USE => CFU_USE, -- implement CF unit? (default=false) |
PWM_USE => PWM_USE, -- implement PWM controller? (default=true) |
TWI_USE => TWI_USE, -- implement two wire serial interface? (default=true) |
SPI_USE => SPI_USE, -- implement SPI? (default=true) |
TRNG_USE => TRNG_USE, -- implement TRNG? (default=false) |
EXIRQ_USE => EXIRQ_USE, -- implement EXIRQ? (default=true) |
MULDIV_USE => MULDIV_USE, -- implement multiplier/divider unit? (default=true) |
WB32_USE => WB32_USE, -- implement WB32 unit? (default=true) |
WDT_USE => WDT_USE, -- implement WDT? (default=true) |
GPIO_USE => GPIO_USE, -- implement GPIO unit? (default=true) |
TIMER_USE => TIMER_USE, -- implement timer? (default=true) |
UART_USE => UART_USE, -- implement UART? (default=true) |
CRC_USE => CRC_USE, -- implement CRC unit? (default=true) |
CFU_USE => CFU_USE, -- implement CF unit? (default=false) |
PWM_USE => PWM_USE, -- implement PWM controller? (default=true) |
TWI_USE => TWI_USE, -- implement two wire serial interface? (default=true) |
SPI_USE => SPI_USE, -- implement SPI? (default=true) |
TRNG_USE => TRNG_USE, -- implement TRNG? (default=false) |
EXIRQ_USE => EXIRQ_USE, -- implement EXIRQ? (default=true) |
FREQ_GEN_USE => FREQ_GEN_USE, -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE => BOOTLD_USE, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => IMEM_AS_ROM -- implement IMEM as read-only memory? (default=false) |
BOOTLD_USE => BOOTLD_USE, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => IMEM_AS_ROM -- implement IMEM as read-only memory? (default=false) |
) |
port map ( |
-- global control -- |
166,6 → 168,8
gpio_i => gpio_i_int, -- parallel input |
-- pwm channels -- |
pwm_o => pwm_o_int, -- pwm channels |
-- arbitrary frequency generator -- |
freq_gen_o => freq_gen_o_int, -- programmable frequency output |
-- serial com -- |
uart_txd_o => uart_txd_o_int, -- UART send data |
uart_rxd_i => uart_rxd_i_int, -- UART receive data |
214,7 → 218,7
wb_stb_o <= std_logic(wb_stb_o_int); |
wb_cyc_o <= std_logic(wb_cyc_o_int); |
ext_ack_o <= std_logic_vector(irq_ack_o_int); |
timer_fg_o <= std_logic(timer_fg_o_int); |
freq_gen_o <= std_logic_vector(freq_gen_o_int); |
|
|
end neo430_top_std_logic_rtl; |
/trunk/neo430/sim/ghdl/ghdl_run.sh
26,6 → 26,7
ghdl -a --work=neo430 $srcdir_core/neo430_crc.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_dmem.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_exirq.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_freq_gen.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_gpio.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_imem.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_muldiv.vhd |
/trunk/neo430/sim/neo430_tb.vhd
122,6 → 122,7
SPI_USE => true, -- implement SPI? (default=true) |
TRNG_USE => false, -- implement TRNG? (default=false) - CANNOT BE SIMULATED! |
EXIRQ_USE => true, -- implement EXIRQ? (default=true) |
FREQ_GEN_USE => true, -- implement FREQ_GEN? (default=true) |
-- boot configuration -- |
BOOTLD_USE => false, -- implement and use bootloader? (default=true) |
IMEM_AS_ROM => false -- implement IMEM as read-only memory? (default=false) |
135,8 → 136,8
gpio_i => x"0000", -- parallel input |
-- pwm channels -- |
pwm_o => open, -- pwm channels |
-- timer frequency generator -- |
timer_fg_o => open, -- programmable frequency output |
-- arbitrary frequency generator -- |
freq_gen_o => open, -- programmable frequency output |
-- serial com -- |
uart_txd_o => uart_txd, -- UART send data |
uart_rxd_i => uart_txd, -- UART receive data |
/trunk/neo430/sw/bootloader/bootloader.c
139,6 → 139,9
// disable EXIRQ |
EXIRQ_CT = 0; |
|
// disable FREQ_GEN |
FREQ_GEN_CT = 0; |
|
// init GPIO |
GPIO_IRQMASK = 0; // no pin change interrupt please, thanks |
neo430_gpio_port_set(1<<STATUS_LED); // activate status LED, clear all others |
159,7 → 162,6
|
// Timeout counter: init timer, irq tick @ ~1Hz (prescaler = 4096) |
// THR = f_main / (1Hz + 4096) -1 |
TMR_NCO = 0; // disable frequency generator |
TMR_CT = 0; // reset timer |
//uint32_t clock = CLOCKSPEED_32bit >> 14; // divide by 4096 |
TMR_THRES = (CLOCKSPEED_HI << 2) -1; // "fake" ;D |
/trunk/neo430/sw/example/README.md
File deleted
\ No newline at end of file
/trunk/neo430/sw/example/freq_gen_demo/main.c
0,0 → 1,84
// ################################################################################################# |
// # < Frequency generator example program > # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
// # # |
// # Redistribution and use in source and binary forms, with or without modification, are # |
// # permitted provided that the following conditions are met: # |
// # # |
// # 1. Redistributions of source code must retain the above copyright notice, this list of # |
// # conditions and the following disclaimer. # |
// # # |
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
// # conditions and the following disclaimer in the documentation and/or other materials # |
// # provided with the distribution. # |
// # # |
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
// # endorse or promote products derived from this software without specific prior written # |
// # permission. # |
// # # |
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
// # OF THE POSSIBILITY OF SUCH DAMAGE. # |
// # ********************************************************************************************* # |
// # The NEO430 Processor - https://github.com/stnolting/neo430 # |
// ################################################################################################# |
|
|
// Libraries |
#include <stdint.h> |
#include <neo430.h> |
|
// Macros |
#define xstr(a) str(a) |
#define str(a) #a |
|
// Configuration |
#define BAUD_RATE 19200 |
#define FREQ_GEN_CHANNEL 0 |
|
|
/* ------------------------------------------------------------ |
* INFO Main function |
* ------------------------------------------------------------ */ |
int main(void) { |
|
// setup UART |
neo430_uart_setup(BAUD_RATE); |
|
// check if FREQ_GEN unit was synthesized, exit if not |
if (!(SYS_FEATURES & (1<<SYS_FREQ_GEN_EN))) { |
neo430_uart_br_print("Error! No frequency generator unit synthesized!"); |
return 1; |
} |
|
// intro text |
neo430_uart_br_print("\nFrequency generator test program\n" |
"Using FREQ_GEN channel "xstr(FREQ_GEN_CHANNEL)"\n\n"); |
|
neo430_freq_gen_reset(); // reset frequency generator |
neo430_freq_gen_enable_ch(FREQ_GEN_CHANNEL); // enable channel |
|
// just sweep through all possible frequency configurations |
uint32_t target_frequency = 0; |
for (target_frequency=0; target_frequency<0xffffffffL; target_frequency++) { |
|
neo430_uart_br_print("Target frequency: 0x"); |
neo430_uart_print_hex_dword(target_frequency); |
neo430_uart_br_print(" Hz, real frequency: 0x"); |
neo430_uart_print_hex_dword(neo430_freq_gen_set_freq(FREQ_GEN_CHANNEL, target_frequency)); // try to set target frequency, returns actual freq. |
neo430_uart_br_print(" Hz\n"); |
|
neo430_cpu_delay_ms(500); // wait 0.5 seconds |
} |
|
return 0; |
} |
/trunk/neo430/sw/example/freq_gen_demo/makefile
0,0 → 1,204
################################################################################################# |
# < NEO430 Application Compile Script - Linux / Windows Powershell / Windows Linux Subsystem > # |
# ********************************************************************************************* # |
# BSD 3-Clause License # |
# # |
# Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
# # |
# Redistribution and use in source and binary forms, with or without modification, are # |
# permitted provided that the following conditions are met: # |
# # |
# 1. Redistributions of source code must retain the above copyright notice, this list of # |
# conditions and the following disclaimer. # |
# # |
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
# conditions and the following disclaimer in the documentation and/or other materials # |
# provided with the distribution. # |
# # |
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
# endorse or promote products derived from this software without specific prior written # |
# permission. # |
# # |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
# OF THE POSSIBILITY OF SUCH DAMAGE. # |
# ********************************************************************************************* # |
# The NEO430 Processor - https://github.com/stnolting/neo430 # |
################################################################################################# |
|
|
#******************************************************************************* |
# USER CONFIGURATION |
#******************************************************************************* |
# Compiler effort (-Os = optimize for size) |
EFFORT = -Os |
|
# User's application sources (add additional files here) |
APP_SRC = main.c |
|
# User's application include folders (don't forget the '-I' before each entry) |
APP_INC = -I . |
|
# Relative or absolute path to the NEO430 home folder |
NEO430_HOME = ../../.. |
#******************************************************************************* |
|
|
|
#------------------------------------------------------------------------------- |
# NEO430 framework |
#------------------------------------------------------------------------------- |
# Path to NEO430 linker script and startup file |
NEO430_COM_PATH=$(NEO430_HOME)/sw/common |
# Path to main NEO430 library include files |
NEO430_INC_PATH=$(NEO430_HOME)/sw/lib/neo430/include |
# Path to main NEO430 library source files |
NEO430_SRC_PATH=$(NEO430_HOME)/sw/lib/neo430/source |
# Path to NEO430 executable generator |
NEO430_EXE_PATH=$(NEO430_HOME)/sw/tools/image_gen |
# Path to NEO430 core rtl folder |
NEO430_RTL_PATH=$(NEO430_HOME)/rtl/core |
|
|
#------------------------------------------------------------------------------- |
# Add NEO430 sources to input SRCs |
#------------------------------------------------------------------------------- |
APP_SRC += $(wildcard $(NEO430_SRC_PATH)/*.c) |
|
|
#------------------------------------------------------------------------------- |
# Make defaults |
#------------------------------------------------------------------------------- |
.SUFFIXES: |
.PHONY: all |
.DEFAULT_GOAL := help |
|
|
#------------------------------------------------------------------------------- |
# Application output definitions |
#------------------------------------------------------------------------------- |
APP_BIN = main.bin |
APP_ASM = main.s |
|
compile: $(APP_ASM) $(APP_BIN) |
install: $(APP_ASM) neo430_application_image.vhd |
all: $(APP_ASM) $(APP_BIN) neo430_application_image.vhd |
|
# define all object files |
OBJ = $(APP_SRC:.c=.o) |
|
|
#------------------------------------------------------------------------------- |
# Tools |
#------------------------------------------------------------------------------- |
#C ompiler tools |
AS = msp430-elf-as |
CC = msp430-elf-gcc |
LD = msp430-elf-ld |
STRIP = msp430-elf-strip |
OBJDUMP = msp430-elf-objdump |
OBJCOPY = msp430-elf-objcopy |
SIZE = msp430-elf-size |
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
# Linker flags |
LD_OPTS = -mcpu=msp430 -Wl,--gc-sections -mrelax -minrt -nostartfiles |
|
|
#------------------------------------------------------------------------------- |
# PC Host Compiler |
#------------------------------------------------------------------------------- |
CC_X86 = g++ -Wall -O -g |
|
|
#------------------------------------------------------------------------------- |
# Tool Targets |
#------------------------------------------------------------------------------- |
# install/compile tools |
$(IMAGE_GEN): $(NEO430_EXE_PATH)/main.cpp |
@echo Compiling $(IMAGE_GEN) |
@$(CC_X86) $< -o $(IMAGE_GEN) |
|
|
#------------------------------------------------------------------------------- |
# Application Targets |
#------------------------------------------------------------------------------- |
# Assemble startup code |
crt0.elf: $(NEO430_COM_PATH)/crt0.asm |
@$(AS) -mY -mcpu=msp430 $< -o $@ |
|
# Compile app sources |
$(OBJ): %.o : %.c crt0.elf |
@$(CC) -c $(CC_OPTS) $(EFFORT) -I $(NEO430_INC_PATH) $(APP_INC) $< -o $@ |
|
# Link object files |
main.elf: $(OBJ) |
@$(CC) $(LD_OPTS) $(EFFORT) -I $(NEO430_INC_PATH) $(APP_INC) -T $(NEO430_COM_PATH)/neo430_linker_script.x $(OBJ) -o $@ -lm |
@echo Memory utilization: |
@$(SIZE) main.elf |
|
# Generate final executable (from .image section only) |
image.dat: main.elf |
@$(OBJCOPY) -I elf32-little $< -j .text -O binary text.dat |
@$(OBJCOPY) -I elf32-little $< -j .rodata -O binary rodata.dat |
@$(OBJCOPY) -I elf32-little $< -j .data -O binary data.dat |
@cat text.dat rodata.dat data.dat > $@ |
@rm -f text.dat rodata.dat data.dat |
|
# Assembly listing file (for debugging) |
$(APP_ASM): main.elf |
@$(OBJDUMP) -D -S -z $< > $@ |
@if grep -qR "dadd" $@; then echo "NEO430: WARNING! 'DADD' instruction might be used!"; fi |
|
# Generate NEO430 executable image for bootloader update |
$(APP_BIN): image.dat $(IMAGE_GEN) |
@set -e |
@$(IMAGE_GEN) -app_bin $< $@ |
|
# Generate NEO430 executable VHDL boot image |
neo430_application_image.vhd: image.dat $(IMAGE_GEN) |
@$(IMAGE_GEN) -app_img $< $@ |
@echo Installing application image to $(NEO430_RTL_PATH)/neo430_application_image.vhd |
@cp neo430_application_image.vhd $(NEO430_RTL_PATH)/. |
@rm -f neo430_application_image.vhd |
|
|
#------------------------------------------------------------------------------- |
# Help |
#------------------------------------------------------------------------------- |
help: |
@echo "NEO430 Application Compilation Script" |
@echo "Make sure to add the msp430-gcc bin folder to your system's PATH variable." |
@echo "Targets:" |
@echo " help - show this text" |
@echo " compile - compile and generate *.bin executable for upload via bootloader" |
@echo " install - compile, generate and install VHDL boot image" |
@echo " all - compile and generate *.bin executable for upload via bootloader and generate and install VHDL boot image" |
@echo " clean - clean up project" |
@echo " clean_all - clean up project, core libraries and helper tools" |
|
|
#------------------------------------------------------------------------------- |
# Clean up |
#------------------------------------------------------------------------------- |
clean: |
@rm -f *.elf *.o *.dat *.vhd *.s *.bin |
|
clean_all: |
@rm -f $(OBJ) *.elf *.dat *.bin *.vhd *.s $(IMAGE_GEN) |
|
|
#------------------------------------------------------------------------------- |
# eof |
/trunk/neo430/sw/example/timer_simple/main.c
86,26 → 86,10
// enable global IRQs |
neo430_eint(); |
|
|
// test frequency generator |
neo430_timer_nco_enable(); |
uint32_t nco_target_frequency = 0, nco_real_frequency; |
|
while(1) { |
neo430_uart_br_print("Target freq.: 0x"); |
neo430_uart_print_hex_dword(nco_target_frequency); |
|
nco_real_frequency = neo430_timer_nco_set(nco_target_frequency); |
|
neo430_uart_br_print(", Real freq.: 0x"); |
neo430_uart_print_hex_dword(nco_real_frequency); |
neo430_uart_br_print("\n"); |
|
nco_target_frequency++; // go through all possible frequencies |
neo430_cpu_delay_ms(250); // wait 250ms |
neo430_sleep(); |
} |
|
|
return 0; |
} |
|
/trunk/neo430/sw/lib/neo430/include/neo430.h
86,26 → 86,46
// ---------------------------------------------------------------------------- |
// Unsigned Multiplier/Divider Unit (MULDIV) |
// ---------------------------------------------------------------------------- |
#define MULDIV_OPA_CTRL (*(REG16 0xFF80)) // -/w: operand A (dividend or factor1) / function config |
#define MULDIV_OPB (*(REG16 0xFF82)) // -/w: operand B (factor2) for multiplication |
#define MULDIV_RESX (*(ROM16 0xFF84)) // r/-: quotient or product low word |
#define MULDIV_RESY (*(ROM16 0xFF86)) // r/-: remainder or product high word |
#define MULDIV_R32bit (*(ROM32 (&MULDIV_RESX))) // r/-: read result as 32-bit data word |
#define MULDIV_OPA_RESX (*(REG16 0xFF80)) // r/w: operand A (dividend or factor1) / resx: quotient or product low word |
#define MULDIV_OPB_UMUL_RESY (*(REG16 0xFF82)) // r/w: operand B (factor2) for unsigned multiplication / resy: remainder or product high word |
#define MULDIV_OPB_SMUL (*(REG16 0xFF84)) // -/w: operand B (factor2) for signed multiplication |
#define MULDIV_OPB_UDIV (*(REG16 0xFF86)) // -/w: operand B (divisor) for unsigned division |
#define MULDIV_R32bit (*(ROM32 (&MULDIV_OPA_RESX))) // r/-: read result as 32-bit data word |
|
// function config bits |
#define MULDIV_CONFIG_MUL ((uint16_t)(0b01 << 0)) |
#define MULDIV_CONFIG_DIV ((uint16_t)(0b10 << 0)) |
|
|
// ---------------------------------------------------------------------------- |
// reserved |
// Frequency Generator (FREQ_GEN) |
// ---------------------------------------------------------------------------- |
//#define reserved (*(REG16 0xFF88)) // -/-: reserved |
//#define reserved (*(REG16 0xFF8A)) // -/-: reserved |
//#define reserved (*(REG16 0xFF8E)) // -/-: reserved |
//#define reserved (*(REG16 0xFF8E)) // -/-: reserved |
#define FREQ_GEN_CT (*(REG16 0xFF88)) // r/w: control register |
#define FREQ_GEN_TW_CH0 (*(REG16 0xFF8A)) // -/w: tuning word channel 0 |
#define FREQ_GEN_TW_CH1 (*(REG16 0xFF8C)) // -/w: tuning word channel 1 |
#define FREQ_GEN_TW_CH2 (*(REG16 0xFF8E)) // -/w: tuning word channel 2 |
|
// FREQ_GEN control register |
#define FREQ_GEN_CT_CH0_EN 0 // r/w: enable NCO channel 0 |
#define FREQ_GEN_CT_CH1_EN 1 // r/w: enable NCO channel 1 |
#define FREQ_GEN_CT_CH2_EN 2 // r/w: enable NCO channel 2 |
#define FREQ_GEN_CT_CH0_PRSC0 3 // r/w: prescaler select bit 0 for channel 0 |
#define FREQ_GEN_CT_CH0_PRSC1 4 // r/w: prescaler select bit 1 for channel 0 |
#define FREQ_GEN_CT_CH0_PRSC2 5 // r/w: prescaler select bit 2 for channel 0 |
#define FREQ_GEN_CT_CH1_PRSC0 6 // r/w: prescaler select bit 0 for channel 1 |
#define FREQ_GEN_CT_CH1_PRSC1 7 // r/w: prescaler select bit 1 for channel 1 |
#define FREQ_GEN_CT_CH1_PRSC2 8 // r/w: prescaler select bit 2 for channel 1 |
#define FREQ_GEN_CT_CH2_PRSC0 9 // r/w: prescaler select bit 0 for channel 2 |
#define FREQ_GEN_CT_CH2_PRSC1 10 // r/w: prescaler select bit 1 for channel 2 |
#define FREQ_GEN_CT_CH2_PRSC2 11 // r/w: prescaler select bit 2 for channel 2 |
|
// clock prescalers |
#define FREQ_GEN_PRSC_2 0 // CLK/2 |
#define FREQ_GEN_PRSC_4 1 // CLK/4 |
#define FREQ_GEN_PRSC_8 2 // CLK/8 |
#define FREQ_GEN_PRSC_64 3 // CLK/64 |
#define FREQ_GEN_PRSC_128 4 // CLK/128 |
#define FREQ_GEN_PRSC_1024 5 // CLK/1024 |
#define FREQ_GEN_PRSC_2048 6 // CLK/2048 |
#define FREQ_GEN_PRSC_4096 7 // CLK/4096 |
|
|
// ---------------------------------------------------------------------------- |
// Wishbone Bus Adapter (WB32) |
// ---------------------------------------------------------------------------- |
216,23 → 236,19
// ---------------------------------------------------------------------------- |
// High-Precision Timer (TIMER) |
// ---------------------------------------------------------------------------- |
#define TMR_CT (*(REG16 0xFFB0)) // r/w: control register |
#define TMR_CNT (*(ROM16 0xFFB2)) // r/-: counter register |
#define TMR_THRES (*(REG16 0xFFB4)) // -/w: threshold register |
#define TMR_NCO (*(REG16 0xFFB6)) // -/w: frequency generator |
#define TMR_CT (*(REG16 0xFFB0)) // r/w: control register |
#define TMR_CNT (*(ROM16 0xFFB2)) // r/-: counter register |
#define TMR_THRES (*(REG16 0xFFB4)) // -/w: threshold register |
//#define reserved (*(REG16 0xFFB6)) // reserved |
|
// Timer control register |
#define TMR_CT_EN 0 // r/w: timer unit global enable |
#define TMR_CT_ARST 1 // r/w: auto reset on match |
#define TMR_CT_IRQ 2 // r/w: interrupt enable |
#define TMR_CT_RUN 3 // r/w: start/stop timer |
#define TMR_CT_PRSC0 4 // r/w: clock prescaler select bit 0 |
#define TMR_CT_PRSC1 5 // r/w: clock prescaler select bit 1 |
#define TMR_CT_PRSC2 6 // r/w: clock prescaler select bit 2 |
#define TMR_CT_NCO_EN 7 // r/w: NCO enable |
#define TMR_CT_NCO_PRSC0 8 // r/w: NCO prescaler select bit 0 |
#define TMR_CT_NCO_PRSC1 9 // r/w: NCO prescaler select bit 1 |
#define TMR_CT_NCO_PRSC2 10 // r/w: NCO prescaler select bit 2 |
#define TMR_CT_EN 0 // r/w: timer unit global enable |
#define TMR_CT_ARST 1 // r/w: auto reset on match |
#define TMR_CT_IRQ 2 // r/w: interrupt enable |
#define TMR_CT_RUN 3 // r/w: start/stop timer |
#define TMR_CT_PRSC0 4 // r/w: clock prescaler select bit 0 |
#define TMR_CT_PRSC1 5 // r/w: clock prescaler select bit 1 |
#define TMR_CT_PRSC2 6 // r/w: clock prescaler select bit 2 |
|
// Timer clock prescaler select: |
#define TMR_PRSC_2 0 // CLK/2 |
450,7 → 466,7
#define SYS_GPIO_EN 3 // r/-: GPIO synthesized |
#define SYS_TIMER_EN 4 // r/-: TIMER synthesized |
#define SYS_UART_EN 5 // r/-: UART synthesized |
//#define SYS_???_EN 6 // r/-: reserved |
#define SYS_FREQ_GEN_EN 6 // r/-: FREQ_GEN synthesized |
#define SYS_BTLD_EN 7 // r/-: Bootloader installed and enabled |
#define SYS_IROM_EN 8 // r/-: Implement IMEM as true ROM |
#define SYS_CRC_EN 9 // r/-: CRC synthesized |
468,6 → 484,7
#include "neo430_cpu.h" |
#include "neo430_crc.h" |
#include "neo430_exirq.h" |
#include "neo430_freq_gen.h" |
#include "neo430_gpio.h" |
#include "neo430_muldiv.h" |
#include "neo430_pwm.h" |
/trunk/neo430/sw/lib/neo430/include/neo430_freq_gen.h
0,0 → 1,46
// ################################################################################################# |
// # < neo430_freq_gen.h - Frequency Generator helper functions > # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
// # # |
// # Redistribution and use in source and binary forms, with or without modification, are # |
// # permitted provided that the following conditions are met: # |
// # # |
// # 1. Redistributions of source code must retain the above copyright notice, this list of # |
// # conditions and the following disclaimer. # |
// # # |
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
// # conditions and the following disclaimer in the documentation and/or other materials # |
// # provided with the distribution. # |
// # # |
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
// # endorse or promote products derived from this software without specific prior written # |
// # permission. # |
// # # |
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
// # OF THE POSSIBILITY OF SUCH DAMAGE. # |
// # ********************************************************************************************* # |
// # The NEO430 Processor - https://github.com/stnolting/neo430 # |
// ################################################################################################# |
|
#ifndef neo430_freq_gen_h |
#define neo430_freq_gen_h |
|
// prototypes |
void neo430_freq_gen_enable_ch(uint16_t ch); // enable programmable frequency output channel ch |
void neo430_freq_gen_disable_ch(uint16_t ch); // disable programmable frequency output channel ch |
void neo430_freq_gen_disable(void); // disable all outputs |
void neo430_freq_gen_reset(void); // disable all outputs and reset device |
uint32_t neo430_freq_gen_set_freq(uint16_t ch, uint32_t frequency); // set programmable output frequency, returns actual output frequency |
void neo430_freq_gen_set(uint16_t ch, uint16_t tuning_word, uint16_t prsc); // set HW configuration |
|
#endif // neo430_freq_gen_h |
/trunk/neo430/sw/lib/neo430/include/neo430_timer.h
37,12 → 37,9
|
// prototypes |
void neo430_timer_enable(void); // enable timer unit |
void neo430_timer_disable(void); // disable timer unit |
void neo430_timer_disable(void); // disable (and reset) timer unit |
void neo430_timer_run(void); // run timer |
void neo430_timer_pause(void); // pause timer |
uint8_t neo430_timer_config_freq(uint32_t f_timer, uint16_t *thres); // configure timer frequency |
void neo430_timer_nco_enable(void); // enable programmable frequency output |
void neo430_timer_nco_disable(void); // disable programmable frequency output |
uint32_t neo430_timer_nco_set(uint32_t frequency); // set programmable output frequency, returns actual output frequency |
|
#endif // neo430_timer_h |
/trunk/neo430/sw/lib/neo430/source/neo430_freq_gen.c
0,0 → 1,205
// ################################################################################################# |
// # < neo430_freq_gen.c - Frequency Generator helper functions > # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
// # # |
// # Redistribution and use in source and binary forms, with or without modification, are # |
// # permitted provided that the following conditions are met: # |
// # # |
// # 1. Redistributions of source code must retain the above copyright notice, this list of # |
// # conditions and the following disclaimer. # |
// # # |
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
// # conditions and the following disclaimer in the documentation and/or other materials # |
// # provided with the distribution. # |
// # # |
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
// # endorse or promote products derived from this software without specific prior written # |
// # permission. # |
// # # |
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
// # OF THE POSSIBILITY OF SUCH DAMAGE. # |
// # ********************************************************************************************* # |
// # The NEO430 Processor - https://github.com/stnolting/neo430 # |
// ################################################################################################# |
|
#include "neo430.h" |
#include "neo430_freq_gen.h" |
|
// Private function prototypes |
static uint32_t neo430_freq_gen_nco_real_output(uint16_t tuning_word, uint16_t prsc_shift); |
|
|
/* ------------------------------------------------------------ |
* INFO Enable programmable frequency output channel ch (0..2) |
* ------------------------------------------------------------ */ |
void neo430_freq_gen_enable_ch(uint16_t ch) { |
|
if (ch > 2) { |
return; |
} |
|
FREQ_GEN_CT |= (1 << (FREQ_GEN_CT_CH0_EN+ch)); |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Disable programmable frequency output channel ch (0..2) |
* ------------------------------------------------------------ */ |
void neo430_freq_gen_disable_ch(uint16_t ch) { |
|
if (ch > 2) { |
return; |
} |
|
FREQ_GEN_CT &= ~(1 << (FREQ_GEN_CT_CH0_EN+ch)); |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Disable all programmable frequency outputs |
* ------------------------------------------------------------ */ |
void neo430_freq_gen_disable(void) { |
|
register uint16_t ct = FREQ_GEN_CT; |
ct &= ~(1 << FREQ_GEN_CT_CH0_EN); |
ct &= ~(1 << FREQ_GEN_CT_CH1_EN); |
ct &= ~(1 << FREQ_GEN_CT_CH2_EN); |
FREQ_GEN_CT = ct; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Disable all programmable frequency outputs and reset unit |
* ------------------------------------------------------------ */ |
void neo430_freq_gen_reset(void) { |
|
FREQ_GEN_CT = 0; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Set frequency programmable frequency output |
* INFO f_out = ((f_cpu / nco_prsc) * tuning_word[15:0]) / 2^17 |
* WARNING Imprecise due to rounding/truncation errors! |
* PARAM ch channel to configure (0..2) |
* PARAM frequency: output frequency in Hz (no fractions possible here) |
* RETURN the actual output frequency |
* ------------------------------------------------------------ */ |
uint32_t neo430_freq_gen_set_freq(uint16_t ch, uint32_t frequency) { |
|
// tuning_word = (f_out * 2^17) / (f_cpu / nco_prsc) |
|
uint32_t f_cpu = CLOCKSPEED_32bit; |
|
int16_t i; |
uint16_t prsc_shift = 12; // start with highest prescaler (4096 => 12) |
|
if (frequency > (f_cpu/4)) { |
return 0; |
} |
|
uint64_t freq_tmp; |
uint32_t freq_real; |
uint32_t freq_diff; |
|
uint32_t freq_diff_best = 0xffffffff; // max |
uint16_t tuning_word_best = 0; |
uint16_t prsc_best = 0; |
uint32_t freq_real_best = 0; |
|
// check all possible prescaler |
for(i=7; i>=0; i--) { |
|
freq_tmp = (uint64_t)frequency; |
freq_tmp = freq_tmp << (17 + prsc_shift); // multiply via bit shifts |
freq_tmp = freq_tmp / f_cpu; |
|
uint16_t tuning_word = (uint16_t)(freq_tmp); |
|
// add 1 to tuning word (for rounding issues) |
freq_real = neo430_freq_gen_nco_real_output(tuning_word+1, prsc_shift); |
|
freq_diff = freq_real - frequency; |
if ((int32_t)freq_diff < 0) { |
freq_diff = 0 - freq_diff; |
} |
|
// best result yet? |
if (freq_diff < freq_diff_best) { |
tuning_word_best = tuning_word; |
prsc_best = i; |
freq_diff_best = freq_diff; |
freq_real_best = freq_real; |
} |
|
// compute next prescaler |
if ((i == 5) || (i == 3)) { |
prsc_shift = prsc_shift - 3; |
} |
else { |
prsc_shift = prsc_shift - 1; |
} |
} |
|
|
// set tuning word and prescaler |
neo430_freq_gen_set(ch, tuning_word_best, prsc_best); |
|
return freq_real_best; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Compute actual NCO output frequency based on tuning word and prescaler |
* RETURN the actual output frequency in Hz |
* ------------------------------------------------------------ */ |
static uint32_t neo430_freq_gen_nco_real_output(uint16_t tuning_word, uint16_t prsc_shift) { |
|
// f_out = ((f_cpu/nco_prsc) * tuning_word[15:0]) / 2^17 |
|
uint32_t f_cpu = CLOCKSPEED_32bit; |
uint64_t f_out = (uint64_t)f_cpu; |
f_out = f_out * tuning_word; |
f_out = f_out >> (17 + prsc_shift); // divide by 2^17 * PRSC |
|
return (uint32_t)f_out; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Set HW configuration |
* PARAM ch channel 0,1,2 |
* PARAM 16-bit tuning word |
* PARAM 3-bit prescaler selector (0,...,7) |
* ------------------------------------------------------------ */ |
void neo430_freq_gen_set(uint16_t ch, uint16_t tuning_word, uint16_t prsc) { |
|
// set tuning word and prescaler |
register uint16_t ctrl = FREQ_GEN_CT; |
if (ch == 0) { |
FREQ_GEN_TW_CH0 = tuning_word; |
ctrl &= ~(0b111 << FREQ_GEN_CT_CH0_PRSC0); // clear old prescaler config |
ctrl |= (prsc << FREQ_GEN_CT_CH0_PRSC0); // set new prescaler config |
} |
else if (ch == 1) { |
FREQ_GEN_TW_CH1 = tuning_word; |
ctrl &= ~(0b111 << FREQ_GEN_CT_CH1_PRSC0); // clear old prescaler config |
ctrl |= (prsc << FREQ_GEN_CT_CH1_PRSC0); // set new prescaler config |
} |
else if (ch == 2) { |
FREQ_GEN_TW_CH2 = tuning_word; |
ctrl &= ~(0b111 << FREQ_GEN_CT_CH2_PRSC0); // clear old prescaler config |
ctrl |= (prsc << FREQ_GEN_CT_CH2_PRSC0); // set new prescaler config |
} |
FREQ_GEN_CT = ctrl; |
} |
/trunk/neo430/sw/lib/neo430/source/neo430_muldiv.c
35,11 → 35,7
#include "neo430.h" |
#include "neo430_muldiv.h" |
|
// private prototypes |
static inline void neo430_muldiv_set_mul(void); |
static inline void neo430_muldiv_set_div(void); |
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 16x16-bit multiplication |
* PARAM 16-bit factor a |
48,9 → 44,8
* ------------------------------------------------------------ */ |
uint32_t neo430_umul32(uint16_t a, uint16_t b) { |
|
neo430_muldiv_set_mul(); |
MULDIV_OPA_CTRL = a; |
MULDIV_OPB = b; |
MULDIV_OPA_RESX = a; |
MULDIV_OPB_UMUL_RESY = b; |
|
// HW processing delay |
asm volatile("nop"); |
69,18 → 64,9
* ------------------------------------------------------------ */ |
int32_t neo430_mul32(int16_t a, int16_t b) { |
|
int16_t sign = a ^ b; |
MULDIV_OPA_RESX = (uint16_t)a; |
MULDIV_OPB_SMUL = (uint16_t)b; |
|
// make positive / unsigned |
if (a < 0) |
a = 0 - a; |
if (b < 0) |
b = 0 - b; |
|
neo430_muldiv_set_mul(); |
MULDIV_OPA_CTRL = (uint16_t)a; |
MULDIV_OPB = (uint16_t)b; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
88,10 → 74,7
|
int32_t r = (int32_t)MULDIV_R32bit; |
|
if (sign < 0) |
return 0 - r; |
else |
return r; |
return r; |
} |
|
|
103,9 → 86,8
* ------------------------------------------------------------ */ |
uint16_t neo430_udiv16(uint16_t dividend, uint16_t divisor) { |
|
neo430_muldiv_set_div(); |
MULDIV_OPA_CTRL = dividend; |
MULDIV_OPB = divisor; |
MULDIV_OPA_RESX = dividend; |
MULDIV_OPB_UDIV = divisor; |
|
// HW processing delay |
asm volatile("nop"); |
112,7 → 94,7
asm volatile("nop"); |
asm volatile("nop"); |
|
return MULDIV_RESX; |
return MULDIV_OPA_RESX; |
} |
|
|
130,9 → 112,8
if (divisor < 0) |
divisor = 0 - divisor; |
|
neo430_muldiv_set_div(); |
MULDIV_OPA_CTRL = (uint16_t)dividend; |
MULDIV_OPB = (uint16_t)divisor; |
MULDIV_OPA_RESX = (uint16_t)dividend; |
MULDIV_OPB_UDIV = (uint16_t)divisor; |
|
// HW processing delay |
asm volatile("nop"); |
139,7 → 120,7
asm volatile("nop"); |
asm volatile("nop"); |
|
int16_t r = (int16_t)MULDIV_RESX; |
int16_t r = (int16_t)MULDIV_OPA_RESX; |
|
if (dividend < 0) |
return 0 - r; |
156,9 → 137,8
* ------------------------------------------------------------ */ |
uint16_t neo430_umod16(uint16_t dividend, uint16_t divisor) { |
|
neo430_muldiv_set_div(); |
MULDIV_OPA_CTRL = dividend; |
MULDIV_OPB = divisor; |
MULDIV_OPA_RESX = dividend; |
MULDIV_OPB_UDIV = divisor; |
|
// HW processing delay |
asm volatile("nop"); |
165,7 → 145,7
asm volatile("nop"); |
asm volatile("nop"); |
|
return MULDIV_RESY; |
return MULDIV_OPB_UMUL_RESY; |
} |
|
|
185,9 → 165,8
if (divisor < 0) |
divisor = 0 - divisor; |
|
neo430_muldiv_set_div(); |
MULDIV_OPA_CTRL = (uint16_t)dividend_int; |
MULDIV_OPB = (uint16_t)divisor; |
MULDIV_OPA_RESX = (uint16_t)dividend_int; |
MULDIV_OPB_UDIV = (uint16_t)divisor; |
|
// HW processing delay |
asm volatile("nop"); |
194,7 → 173,7
asm volatile("nop"); |
asm volatile("nop"); |
|
int16_t r = (int16_t)MULDIV_RESY; |
int16_t r = (int16_t)MULDIV_OPB_UMUL_RESY; |
|
if (dividend < 0) |
return 0 - r; |
212,9 → 191,8
* ------------------------------------------------------------ */ |
uint16_t neo430_umoddiv16(uint16_t *remainder, uint16_t dividend, uint16_t divisor) { |
|
neo430_muldiv_set_div(); |
MULDIV_OPA_CTRL = dividend; |
MULDIV_OPB = divisor; |
MULDIV_OPA_RESX = dividend; |
MULDIV_OPB_UDIV = divisor; |
|
// HW processing delay |
asm volatile("nop"); |
221,8 → 199,8
asm volatile("nop"); |
asm volatile("nop"); |
|
*remainder = MULDIV_RESY; |
return MULDIV_RESX; |
*remainder = MULDIV_OPB_UMUL_RESY; |
return MULDIV_OPA_RESX; |
} |
|
|
244,9 → 222,8
if (divisor < 0) |
divisor = 0 - divisor; |
|
neo430_muldiv_set_div(); |
MULDIV_OPA_CTRL = (uint16_t)dividend_int; |
MULDIV_OPB = (uint16_t)divisor; |
MULDIV_OPA_RESX = (uint16_t)dividend_int; |
MULDIV_OPB_UDIV = (uint16_t)divisor; |
|
// HW processing delay |
asm volatile("nop"); |
253,8 → 230,8
asm volatile("nop"); |
asm volatile("nop"); |
|
int16_t q = (int16_t)MULDIV_RESX; |
int16_t r = (int16_t)MULDIV_RESY; |
int16_t q = (int16_t)MULDIV_OPA_RESX; |
int16_t r = (int16_t)MULDIV_OPB_UMUL_RESY; |
|
if (dividend < 0) |
*remainder = 0 - r; |
266,24 → 243,3
else |
return q; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Configure MULDIV for multiplication |
* ------------------------------------------------------------ */ |
static inline void neo430_muldiv_set_mul(void) { |
|
MULDIV_OPA_CTRL = 0x0000; // reset |
MULDIV_OPA_CTRL = MULDIV_CONFIG_MUL; // configure for multiplication |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Configure MULDIV for division |
* ------------------------------------------------------------ */ |
static inline void neo430_muldiv_set_div(void) { |
|
MULDIV_OPA_CTRL = 0x0000; // reset |
MULDIV_OPA_CTRL = MULDIV_CONFIG_DIV; // configure for division |
} |
|
/trunk/neo430/sw/lib/neo430/source/neo430_timer.c
35,10 → 35,7
#include "neo430.h" |
#include "neo430_timer.h" |
|
// Private function prototypes |
static uint32_t neo430_timer_nco_real_output(uint16_t tuning_word, uint16_t prsc_shift); |
|
|
/* ------------------------------------------------------------ |
* INFO Activate Timer |
* ------------------------------------------------------------ */ |
49,7 → 46,7
|
|
/* ------------------------------------------------------------ |
* INFO Dectivate Timer |
* INFO Deactivate (and reset) Timer |
* ------------------------------------------------------------ */ |
void neo430_timer_disable(void) { |
|
67,7 → 64,7
|
|
/* ------------------------------------------------------------ |
* INFO Stop Timer |
* INFO Pause Timer |
* ------------------------------------------------------------ */ |
void neo430_timer_pause(void) { |
|
113,110 → 110,3
|
return 0; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Enable programmable frequency output (NCO) |
* ------------------------------------------------------------ */ |
void neo430_timer_nco_enable(void) { |
|
TMR_CT |= (1<<TMR_CT_NCO_EN); |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Disable programmable frequency output (NCO) |
* ------------------------------------------------------------ */ |
void neo430_timer_nco_disable(void) { |
|
TMR_CT &= ~(1<<TMR_CT_NCO_EN); |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Set frequency programmable frequency output |
* INFO f_out = ((f_cpu / nco_prsc) * tuning_word[15:0]) / 2^17 |
* PARAM frequency: output frequency in Hz (no fractions possible here) |
* RETURN the actual output frequency |
* ------------------------------------------------------------ */ |
uint32_t neo430_timer_nco_set(uint32_t frequency) { |
|
// tuning_word = (f_out * 2^17) / (f_cpu / nco_prsc) |
|
uint32_t f_cpu = CLOCKSPEED_32bit; |
|
int16_t i; |
uint16_t prsc_shift = 12; // start with highest prescaler (4096 => 12) |
|
if (frequency > (f_cpu/4)) { |
return 0; |
} |
|
uint64_t freq_tmp; |
uint32_t freq_real; |
uint32_t freq_diff; |
|
uint32_t freq_diff_best = 0xffffffff; // max |
uint16_t tuning_word_best = 0; |
uint16_t prsc_best = 0; |
uint32_t freq_real_best = 0; |
|
// check all possible prescaler |
for(i=7; i>=0; i--) { |
|
freq_tmp = (uint64_t)frequency; |
freq_tmp = freq_tmp << (17 + prsc_shift); // multiply via bit shifts |
freq_tmp = freq_tmp / f_cpu; |
|
uint16_t tuning_word = (uint16_t)(freq_tmp); |
|
// add 1 to tuning word (for rounding issues) |
freq_real = neo430_timer_nco_real_output(tuning_word+1, prsc_shift); |
|
freq_diff = freq_real - frequency; |
if ((int32_t)freq_diff < 0) { |
freq_diff = 0 - freq_diff; |
} |
|
// best result yet? |
if (freq_diff < freq_diff_best) { |
tuning_word_best = tuning_word; |
prsc_best = i; |
freq_diff_best = freq_diff; |
freq_real_best = freq_real; |
} |
|
// compute next prescaler |
if ((i == 5) || (i == 3)) { |
prsc_shift = prsc_shift - 3; |
} |
else { |
prsc_shift = prsc_shift - 1; |
} |
} |
|
// write config to NCO |
uint16_t timer_ctrl = TMR_CT; |
timer_ctrl &= ~(0b111 << TMR_CT_NCO_PRSC0); // clear old prescaler config |
TMR_CT = timer_ctrl | (prsc_best << TMR_CT_NCO_PRSC0); // set new prescaler config |
TMR_NCO = tuning_word_best; // set timer's NCO tuning word |
|
return freq_real_best; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Compute actual NCO output frequency based on tuning word and prescaler |
* RETURN the actual output frequency in Hz |
* ------------------------------------------------------------ */ |
static uint32_t neo430_timer_nco_real_output(uint16_t tuning_word, uint16_t prsc_shift) { |
|
// f_out = ((f_cpu/nco_prsc) * tuning_word[15:0]) / 2^17 |
|
uint32_t f_cpu = CLOCKSPEED_32bit; |
uint64_t f_out = (uint64_t)f_cpu; |
f_out = f_out * tuning_word; |
f_out = f_out >> (17 + prsc_shift); // divide by 2^17 * PRSC |
|
return (uint32_t)f_out; |
} |
/trunk/neo430/travis_ci/hw_check.sh
29,6 → 29,7
ghdl -a --work=neo430 $srcdir_core/neo430_crc.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_dmem.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_exirq.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_freq_gen.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_gpio.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_imem.vhd |
ghdl -a --work=neo430 $srcdir_core/neo430_muldiv.vhd |