OpenCores
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

powered by: WebSVN 2.1.0

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