URL
https://opencores.org/ocsvn/neo430/neo430/trunk
Subversion Repositories neo430
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 193 to Rev 194
- ↔ Reverse comparison
Rev 193 → Rev 194
/neo430/trunk/neo430/README.md
1,10 → 1,8
# The NEO430 Processor |
|
[![Build Status](https://travis-ci.com/stnolting/neo430.svg?branch=master)](https://travis-ci.com/stnolting/neo430) |
[![GitHub release](https://img.shields.io/github/v/release/stnolting/neo430?include_prereleases)](https://GitHub.com/stnolting/neo430/releases/) |
[![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) |
[![documentation](https://img.shields.io/badge/documentation-available-brightgreen)](https://raw.githubusercontent.com/stnolting/neo430/master/doc/NEO430.pdf) |
[![license](https://img.shields.io/github/license/stnolting/neo430)](https://github.com/stnolting/neo430/blob/master/LICENSE) |
|
## Table of Content |
12,6 → 10,7
* [Introduction](#Introduction) |
* [Processor Features](#Processor-Features) |
* [Differences to the Original MSP430 Processors](#Differences-to-the-Original-MSP430-Processors) |
* [Top Entity](#Top-Entity) |
* [Implementation Results](#Implementation-Results) |
* [Performance](#Performance) |
* [Quick Start](#Quick-Start) |
98,7 → 97,7
- No hardware debugging interface |
- No analog components |
- No support of TI's Code Composer Studio |
- No support of CPU's DADD instruction (which is never used by the compiler...) |
- No support of CPU's DADD operation |
- Just 4 CPU interrupt channels |
- Single clock domain for complete processor |
- Different numbers of instruction execution cycles |
109,6 → 108,71
|
|
|
## Top Entity |
|
The top entity of the processor is [neo430_top.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_top.vhd) (in the rtl\core folder). |
Just instantiate this file in you project and you are ready to go! All signals of this top entity are of type *std_ulogic* or *std_ulogic_vector*, respectively. |
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 | |
|:-------------|:-----------------------:|:-------------:|:---------------------------------------------------------| |
| CLOCK_SPEED | natural | 100000000 | Clock speed of CPU clock input "clk_i" in Hz | |
| 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 | |
| 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 | |
|
|
|
## Implementation Results |
|
Mapping results generated for HW version 0x0320. The full (default) hardware configuration includes |
186,30 → 250,33
evaluates to **7.33 cycles/instruction resulting in 0.136 MIPS per MHz (worst case)**. |
|
|
### Coremark Benchmark |
### CoreMark Benchmark |
|
The [coremark CPU benchmark](https://www.eembc.org/coremark/) was executed on the NEO430 and is available in the |
The [CoreMark CPU benchmark](https://www.eembc.org/coremark/) was executed on the NEO430 and is available in the |
project's [sw/example/coremark](https://github.com/stnolting/neo430/blob/master/sw/example/coremark) folder This benchmark |
tests the capabilities of the CPU itself rather than the functions provided by the whole system / SoC. |
|
~~~ |
Hardware: 100 MHz, 32kB IMEM, 12kB DMEM, HW verison 0x0401, no peripherals used (except for the TIMER and the UART) |
Hardware: 100 MHz, 32kB IMEM, 12kB DMEM, HW verison 0x0404, no peripherals used (except for the TIMER and the UART) |
Software: msp430-gcc 8.3.0 for Linux, MEM_METHOD is MEM_STACK, 2000 coremark iterations |
~~~ |
|
|__Optimization__ | __Coremark Score__ | __Relative Score__ | |
|:-------------------:|:------------------:|:---------------------:| |
| -Os | 6.56 | 0.066 Coremarks/MHz | |
| -O3 | 6.92 | 0.069 Coremarks/MHz | |
| -O3 + NEO430_MULDIV | 14.82 | 0.148 Coremarks/MHz | |
|__Optimization__ | __Coremark Score__ | __Relative Score__ | |
|:--------------------:|:------------------:|:---------------------:| |
| -Os | 6.57 | 0.065 Coremarks/MHz | |
| -O2 | 7.16 | 0.072 Coremarks/MHz | |
| -Os + NEO430_MULDIV* | 12.98 | 0.129 Coremarks/MHz | |
| -O2 + NEO430_MULDIV* | 15.26 | 0.152 Coremarks/MHz | |
|
Even though a score of 6.38 can outnumber certain architectures and configurations (see the score table on the coremark |
homepage), the relative score of 0.064 coremarks per second might pretty low. But you have to keep in mind that benchmark |
*) 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 |
was executed using only the resources of the CPU itself. The CPU consists of only ~500 Intel Cyclone IV LUTs and does not |
contain any sophisticated ALU operations like multiplication or barrel shifting. Also, all instructions are executed in a |
multi-cycle scheme requiring several clock cycles to complete. When explicitly using the NEO430 MULDIV unit for performing |
the matrix-operations benchmark scenario (among other operations, it is based on matrix-scalar, matrix-vector and |
matrix-matrix multiplications) the **coremark score is increased to 12.56**. By using additional HW accelerators from the |
matrix-matrix multiplications) the **coremark score is increased to 15.26**. By using additional HW accelerators from the |
NEO430 ecosystem (like the CRC unit) or by using the MULDIV unit also for address and index computations the performance |
and thus, the coremark score can be further increased |
|
/neo430/trunk/neo430/doc/NEO430.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/neo430/trunk/neo430/rtl/core/neo430_bootloader_image.vhd
970,8 → 970,8
000959 => x"3a56", |
000960 => x"4d20", |
000961 => x"7261", |
000962 => x"3220", |
000963 => x"2039", |
000962 => x"3320", |
000963 => x"2031", |
000964 => x"3032", |
000965 => x"3032", |
000966 => x"480a", |
/neo430/trunk/neo430/rtl/core/neo430_control.vhd
54,8 → 54,7
irq_vec_o : out std_ulogic_vector(01 downto 0); -- irq channel address |
imm_o : out std_ulogic_vector(15 downto 0); -- branch offset |
-- irq lines -- |
irq_i : in std_ulogic_vector(03 downto 0); -- IRQ lines |
irq_ack_o : out std_ulogic_vector(03 downto 0) -- IRQ acknowledge |
irq_i : in std_ulogic_vector(03 downto 0) -- IRQ lines^ |
); |
end neo430_control; |
|
697,9 → 696,6
end case; |
end process; |
|
-- ack output -- |
irq_ack_o <= irq_ack_mask; |
|
-- interrupt priority encoder -- |
irq_priority: process(irq_buf) |
begin |
711,7 → 707,7
irq_vec_nxt <= "01"; |
when "0100" | "1100" => -- "-100" |
irq_vec_nxt <= "10"; |
when others => -- "1000" |
when others => -- "1000" ("0000" -> dont't care) |
irq_vec_nxt <= "11"; |
end case; |
end process irq_priority; |
/neo430/trunk/neo430/rtl/core/neo430_cpu.vhd
58,8 → 58,7
mem_data_o : out std_ulogic_vector(15 downto 0); -- write data |
mem_data_i : in std_ulogic_vector(15 downto 0); -- read data |
-- interrupt system -- |
irq_i : in std_ulogic_vector(03 downto 0); -- interrupt requests |
irq_ack_o : out std_ulogic_vector(03 downto 0) -- IRQ acknowledge |
irq_i : in std_ulogic_vector(03 downto 0) -- interrupt requests |
); |
end neo430_cpu; |
|
99,8 → 98,7
irq_vec_o => irq_sel, -- irq channel address |
imm_o => imm, -- branch offset |
-- irq lines -- |
irq_i => irq_i, -- IRQ lines |
irq_ack_o => irq_ack_o -- IRQ acknowledge |
irq_i => irq_i -- IRQ lines |
); |
|
|
/neo430/trunk/neo430/rtl/core/neo430_exirq.vhd
71,12 → 71,12
architecture neo430_exirq_rtl of neo430_exirq is |
|
-- control register bits -- |
constant ctrl_irq_sel0_c : natural := 0; -- r/w: IRQ source bit 0 (r); SW IRQ select / ACK select (w) |
constant ctrl_irq_sel1_c : natural := 1; -- r/w: IRQ source bit 1 (r); SW IRQ select / ACK select (w) |
constant ctrl_irq_sel2_c : natural := 2; -- r/w: IRQ source bit 2 (r); SW IRQ select / ACK select (w) |
constant ctrl_irq_sel0_c : natural := 0; -- r/w: IRQ source bit 0 (r); SW IRQ select (w) |
constant ctrl_irq_sel1_c : natural := 1; -- r/w: IRQ source bit 1 (r); SW IRQ select (w) |
constant ctrl_irq_sel2_c : natural := 2; -- r/w: IRQ source bit 2 (r); SW IRQ select (w) |
constant ctrl_en_c : natural := 3; -- r/w: unit enable |
constant ctrl_sw_irq_c : natural := 4; -- -/w: use irq_sel as SW IRQ trigger, auto-clears |
constant ctrl_ack_irq_c : natural := 5; -- -/w: use irq_sel as ACK select, auto-clears |
constant ctrl_ack_irq_c : natural := 5; -- -/w: ACK current IRQ, auto-clears |
-- ... |
constant ctrl_en_irq0_c : natural := 8; -- r/w: IRQ channel 0 enable |
constant ctrl_en_irq1_c : natural := 9; -- r/w: IRQ channel 1 enable |
175,6 → 175,9
irq_core: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- ack output -- |
ext_ack_o <= ack_mask; |
|
-- irq buffer -- |
for i in 0 to 7 loop |
-- keep requests until they are acknowledged |
184,20 → 187,17
|
-- mini state FSM - defaults -- |
cpu_irq_o <= '0'; |
ext_ack_o <= (others => '0'); |
|
-- mini state FSM -- |
if (state = '0') or (enable = '0') then -- idle or deactivated |
state <= '0'; |
irq_src_reg <= irq_src; -- capture source |
if (irq_fire = '1') then |
cpu_irq_o <= '1'; -- trigger CPU |
cpu_irq_o <= '1'; -- trigger CPU interrupt |
state <= '1'; -- go to active IRQ state |
end if; |
else -- active IRQ |
if (ack_trig = '1') then |
ext_ack_o <= ack_mask; |
state <= '0'; |
if (ack_trig = '1') or (enable = '0') then |
state <= '0'; |
end if; |
end if; |
end if; |
219,10 → 219,10
|
-- ACK priority decoder ----------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
ack_priority_dec: process(ack_trig, irq_src_reg) |
ack_priority_dec: process(state, ack_trig, irq_src_reg) |
variable irq_ack_v : std_ulogic_vector(3 downto 0); |
begin |
irq_ack_v := ack_trig & irq_src_reg; |
irq_ack_v := (ack_trig and state) & irq_src_reg; |
case irq_ack_v is |
when "1000" => ack_mask <= "00000001"; |
when "1001" => ack_mask <= "00000010"; |
/neo430/trunk/neo430/rtl/core/neo430_package.vhd
401,8 → 401,7
irq_vec_o : out std_ulogic_vector(01 downto 0); -- irq channel address |
imm_o : out std_ulogic_vector(15 downto 0); -- branch offset |
-- irq lines -- |
irq_i : in std_ulogic_vector(03 downto 0); -- IRQ lines |
irq_ack_o : out std_ulogic_vector(03 downto 0) -- IRQ acknowledge |
irq_i : in std_ulogic_vector(03 downto 0) -- IRQ lines |
); |
end component; |
|
485,8 → 484,7
mem_data_o : out std_ulogic_vector(15 downto 0); -- write data |
mem_data_i : in std_ulogic_vector(15 downto 0); -- read data |
-- interrupt system -- |
irq_i : in std_ulogic_vector(03 downto 0); -- interrupt requests |
irq_ack_o : out std_ulogic_vector(03 downto 0) -- IRQ acknowledge |
irq_i : in std_ulogic_vector(03 downto 0) -- interrupt requests |
); |
end component; |
|
/neo430/trunk/neo430/rtl/core/neo430_pwm.vhd
157,8 → 157,8
end if; |
-- channels -- |
for i in 0 to num_pwm_channels_c-1 loop |
-- constrain counter to virtual size configured by SIZE register |
if (unsigned(pwm_cnt and mask) >= unsigned(pwm_ch(i))) or (enable = '0') then |
-- constrain to virtual size configured by SIZE register |
if (unsigned(pwm_cnt and mask) >= unsigned(pwm_ch(i) and mask)) or (enable = '0') then |
pwm_out(i) <= '0'; |
else |
pwm_out(i) <= '1'; |
/neo430/trunk/neo430/rtl/core/neo430_timer.vhd
91,7 → 91,7
|
-- timer regs -- |
signal cnt : std_ulogic_vector(15 downto 0); -- r/-: counter register |
signal thres : std_ulogic_vector(15 downto 0); -- r/w: threshold 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 -- |
175,7 → 175,7
match <= '1' when (cnt = thres) else '0'; |
|
-- interrupt line -- |
irq_fire <= match and ctrl(ctrl_en_c) and ctrl(ctrl_irq_en_c) and ctrl(ctrl_run_c); |
irq_fire <= match and ctrl(ctrl_en_c) and ctrl(ctrl_irq_en_c); -- and ctrl(ctrl_run_c); |
|
-- edge detector -- |
irq_o <= irq_fire and (not irq_fire_ff); |
219,12 → 219,12
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); |
elsif (addr = timer_cnt_addr_c) then |
else--if (addr = timer_cnt_addr_c) then |
data_o <= cnt; |
else--if (addr = timer_thres_addr_c) then |
data_o <= thres; |
-- else -- timer_nco_addr_c |
-- data_o <= nco_tuning_word; |
-- else--if (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; |
/neo430/trunk/neo430/rtl/core/neo430_top.vhd
133,7 → 133,7
-- generators -- |
signal rst_i_sync0 : std_ulogic; |
signal rst_i_sync1 : std_ulogic; |
signal rst_gen : std_ulogic_vector(03 downto 0) := (others => '0'); -- perform reset on bitstream upload |
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; |
182,16 → 182,13
signal sysconfig_rdata : std_ulogic_vector(15 downto 0); |
|
-- interrupt system -- |
signal irq : std_ulogic_vector(03 downto 0); |
signal irq_ack : std_ulogic_vector(03 downto 0); |
signal timer_irq : std_ulogic; |
signal uart_irq : std_ulogic; |
signal spi_irq : std_ulogic; |
signal twi_irq : std_ulogic; |
signal gpio_irq : std_ulogic; |
signal xirq_sync0 : std_ulogic; |
signal xirq_sync1 : std_ulogic; |
signal ext_irq : std_ulogic; |
signal irq : std_ulogic_vector(03 downto 0); |
signal timer_irq : std_ulogic; |
signal uart_irq : std_ulogic; |
signal spi_irq : std_ulogic; |
signal twi_irq : std_ulogic; |
signal gpio_irq : std_ulogic; |
signal ext_irq : std_ulogic; |
|
-- misc -- |
signal imem_up_en : std_ulogic; |
233,7 → 230,8
if (sys_rst = '0') then |
clk_div <= (others => '0'); |
elsif rising_edge(clk_i) 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) = '1') then -- anybody needing clocks? |
-- 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 |
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1); |
end if; |
end if; |
276,8 → 274,7
mem_data_o => cpu_bus.wdata, -- write data |
mem_data_i => cpu_bus.rdata, -- read data |
-- interrupt system -- |
irq_i => irq, -- interrupt request lines |
irq_ack_o => irq_ack -- IRQ acknowledge |
irq_i => irq -- interrupt request lines |
); |
|
-- final CPU read data -- |
732,22 → 729,11
neo430_exirq_inst_false: |
if (EXIRQ_USE = false) generate |
exirq_rdata <= (others => '0'); |
ext_ack_o <= "0000000" & irq_ack(3); |
ext_irq <= xirq_sync1; |
ext_ack_o <= (others => '0'); |
ext_irq <= '0'; |
end generate; |
|
-- sync for single external IRQ if EXIRQ is not implemented -- |
external_irq_sync: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (EXIRQ_USE = false) then |
xirq_sync0 <= ext_irq_i(0); |
xirq_sync1 <= xirq_sync0; |
end if; |
end if; |
end process external_irq_sync; |
|
|
-- System Configuration ----------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
neo430_sysconfig_inst: neo430_sysconfig |
/neo430/trunk/neo430/sw/example/coremark/core_main.c
102,7 → 102,7
|
#ifndef RUN_COREMARK |
#pragma warning ("COREMARK HAS NOT BEEN COMPILED! Use >>make clean compile CC_USER_FLAGS+=-DRUN_COREMARK<< to compile it.") |
while(1) {} |
return 0; |
#endif |
// ----------------------------------------------- |
|
/neo430/trunk/neo430/sw/example/coremark/core_portme.c
135,12 → 135,15
(1<<TMR_CT_ARST) | // auto-reset on match |
(1<<TMR_CT_IRQ) | // interrupt enable |
(0<<TMR_CT_RUN); // timer not running yet |
neo430_timer_config_freq(NEO430_TIMER_F); |
|
neo430_printf("NEO430: clock speed : %n Hz\n", CLOCKSPEED_32bit); |
neo430_printf("NEO430: timer THRES : %u\n", TMR_THRES); |
neo430_printf("NEO430: timer CTRL : %x\n", TMR_CT); |
neo430_printf("NEO430: timer IRQs/s : %u\n", (uint16_t)NEO430_TIMER_F); |
uint16_t timer_thres; |
if (neo430_timer_config_freq(NEO430_TIMER_F, &timer_thres)) { |
neo430_printf("NEO430: timer frequency config error!\n"); |
while(1); |
} |
|
neo430_printf("NEO430: clock speed = %n Hz\n", CLOCKSPEED_32bit); |
neo430_printf("NEO430: timer IRQs/s = %u\n", (uint16_t)NEO430_TIMER_F); |
#if USE_NEO430_MUL |
neo430_printf("NEO430: using NEO430 MULDIV unit for matrix core operations\n"); |
#endif |
/neo430/trunk/neo430/sw/example/coremark/core_portme.h
32,8 → 32,8
// Manual NEO430 config: |
#define BAUD_RATE (19200) |
#define ITERATIONS (2000) |
#define NEO430_TIMER_F (10) // Hertz |
#define FLAGS_STR "-Os" // compiler optimization |
#define NEO430_TIMER_F (10) // Hz |
#define FLAGS_STR "-> see makefile" // compiler optimization |
|
#ifndef USE_NEO430_MULTIPLIER |
#define USE_NEO430_MUL 0 // set 1 to use MULDIV unit for matrix core operations |
/neo430/trunk/neo430/sw/example/game_of_life/main.c
38,10 → 38,11
#include <neo430.h> |
|
// Configuration |
#define NUM_CELLS_X 160 // must be a multiple of 8 |
#define NUM_CELLS_Y 40 |
#define BAUD_RATE 19200 |
#define UNI_DELAY 500 // delay between iterations in ms |
#define NUM_CELLS_X 160 // must be a multiple of 8 |
#define NUM_CELLS_Y 40 |
#define BAUD_RATE 19200 |
#define GEN_DELAY 500 // delay between iterations in ms |
#define TRNG_TAP_MASK 0b01010001000000 // highly experimental! |
|
// Global variables |
uint8_t universe[2][NUM_CELLS_X/8][NUM_CELLS_Y]; |
62,6 → 63,8
|
uint8_t u = 0, cell = 0, n = 0; |
int16_t x, y; |
uint16_t trng_available = 0; |
uint8_t trng_data = 0; |
|
// setup UART |
neo430_uart_setup(BAUD_RATE); |
77,15 → 80,36
neo430_printf("Press any key to start a random-initialized torus-style universe of %ux%u cells.\n", NUM_CELLS_X, NUM_CELLS_Y); |
neo430_printf("You can pause/restart the simulation by pressing any key.\n"); |
|
// randomize until key pressed |
while (neo430_uart_char_received() == 0) { |
neo430_xorshift32(); |
// check if TRNG was synthesized |
if ((SYS_FEATURES & (1<<SYS_TRNG_EN))) { |
neo430_printf("TRNG detected. Using TRNG for universe initialization.\n"); |
neo430_trng_enable(TRNG_TAP_MASK); |
trng_available = 1; |
} |
|
if (trng_available) { |
neo430_uart_getc(); // wait for pressed key |
} |
else { |
// randomize until key pressed |
while (neo430_uart_char_received() == 0) { |
neo430_xorshift32(); |
} |
} |
|
// initialize universe using random data |
for (x=0; x<NUM_CELLS_X/8; x++) { |
for (y=0; y<NUM_CELLS_Y; y++) { |
universe[0][x][y] = (uint8_t)neo430_xorshift32(); |
if (trng_available) { |
if (neo430_trng_get(&trng_data)) { |
neo430_printf("TRNG error!\n"); |
return 1; |
} |
universe[0][x][y] = (uint8_t)trng_data; // use data from TRNG |
} |
else { |
universe[0][x][y] = (uint8_t)neo430_xorshift32(); // use data von PRNG |
} |
} |
} |
|
123,7 → 147,7
generation++; |
|
// wait 500ms |
neo430_cpu_delay_ms(UNI_DELAY); |
neo430_cpu_delay_ms(GEN_DELAY); |
} |
|
return 0; |
/neo430/trunk/neo430/sw/example/nested_irqs/main.c
83,8 → 83,10
|
// configure timer frequency |
neo430_timer_disable(); |
if (neo430_timer_config_freq(1000)) // 1kHz to increment every 1ms |
uint16_t timer_thres; |
if (neo430_timer_config_freq(1000, &timer_thres)) { // 1kHz to increment every 1ms |
neo430_uart_br_print("Invalid TIMER frequency!\n"); |
} |
|
neo430_printf("THR: %x, CTR: %x\n", TMR_THRES, TMR_CT); |
TMR_CT |= (1<<TMR_CT_EN) | (1<<TMR_CT_ARST) | (1<<TMR_CT_IRQ) | (1<<TMR_CT_RUN); // enable timer, auto-reset, irq enabled, start timer |
/neo430/trunk/neo430/sw/example/timer_simple/main.c
76,8 → 76,10
|
// configure timer frequency |
neo430_timer_disable(); |
if (neo430_timer_config_freq(BLINK_FREQ)) |
uint16_t timer_thres; |
if (neo430_timer_config_freq(BLINK_FREQ, &timer_thres)) { |
neo430_uart_br_print("Invalid TIMER frequency!\n"); |
} |
|
TMR_CT |= (1<<TMR_CT_EN) | (1<<TMR_CT_ARST) | (1<<TMR_CT_IRQ) | (1<<TMR_CT_RUN); // enable timer, auto-reset, irq enabled, timer start |
|
/neo430/trunk/neo430/sw/lib/neo430/include/neo430.h
218,7 → 218,7
// ---------------------------------------------------------------------------- |
#define TMR_CT (*(REG16 0xFFB0)) // r/w: control register |
#define TMR_CNT (*(ROM16 0xFFB2)) // r/-: counter register |
#define TMR_THRES (*(REG16 0xFFB4)) // r/w: threshold register |
#define TMR_THRES (*(REG16 0xFFB4)) // -/w: threshold register |
#define TMR_NCO (*(REG16 0xFFB6)) // -/w: frequency generator |
|
// Timer control register |
401,9 → 401,9
#define EXIRQ_CT (*(REG16 0xFFEE)) // r/w: control register |
|
// EXIRQ control register |
#define EXIRQ_CT_SEL0 0 // r/w: IRQ source bit 0 / SW_IRQ select / ACK select |
#define EXIRQ_CT_SEL1 1 // r/w: IRQ source bit 1 / SW_IRQ select / ACK select |
#define EXIRQ_CT_SEL2 2 // r/w: IRQ source bit 2 / SW_IRQ select / ACK select |
#define EXIRQ_CT_SEL0 0 // r/w: IRQ source bit 0 / SW_IRQ select |
#define EXIRQ_CT_SEL1 1 // r/w: IRQ source bit 1 / SW_IRQ select |
#define EXIRQ_CT_SEL2 2 // r/w: IRQ source bit 2 / SW_IRQ select |
#define EXIRQ_CT_EN 3 // r/w: unit enable |
#define EXIRQ_CT_SW_IRQ 4 // -/w: use irq_sel as SW IRQ trigger, auto-clears |
#define EXIRQ_CT_ACK_IRQ 5 // -/w: use irq_sel as ACK select, auto-clears |
/neo430/trunk/neo430/sw/lib/neo430/include/neo430_timer.h
40,7 → 40,7
void neo430_timer_disable(void); // disable 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); // configure timer frequency |
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 |
/neo430/trunk/neo430/sw/lib/neo430/source/neo430_exirq.c
95,7 → 95,7
|
// apply sw irq enable bit and according irq select |
uint16_t exirq_ctrl = EXIRQ_CT & (~(0b111 << EXIRQ_CT_SEL0)); // clear IRQ src output |
EXIRQ_CT = exirq_ctrl | (1<<EXIRQ_CT_SW_IRQ) | (irq_sel<<EXIRQ_CT_SEL0); |
EXIRQ_CT = exirq_ctrl | (1<<EXIRQ_CT_SW_IRQ) | (irq_sel<<EXIRQ_CT_SEL0); // set dst. IRQ and set SW_IRQ flag |
} |
|
|
/neo430/trunk/neo430/sw/lib/neo430/source/neo430_timer.c
77,10 → 77,10
|
/* ------------------------------------------------------------ |
* INFO Configure timer period |
* PARAM Timer frequency in Hz (1Hz ... F_CPU/2) |
* RETURN 0 if successful, !=0 if error |
* PARAM Timer frequency in Hz (1 ... F_CPU/2), uint16_t pointer to store computed THRES value |
* RETURN 0 if successful, 0xff if error |
* ------------------------------------------------------------ */ |
uint8_t neo430_timer_config_freq(uint32_t f_timer) { |
uint8_t neo430_timer_config_freq(uint32_t f_timer, uint16_t *thres) { |
|
uint32_t clock = CLOCKSPEED_32bit; |
uint32_t ticks = (clock / f_timer) >> 1; // divide by lowest prescaler (= f/2) |
92,18 → 92,22
|
// find prescaler |
while(prsc < 8) { |
if (ticks <= 0x0000ffff) |
if (ticks <= 0x0000ffff) { |
break; |
} |
else { |
if ((prsc == 2) || (prsc == 4)) |
if ((prsc == 2) || (prsc == 4)) { |
ticks >>= 3; |
else |
} |
else { |
ticks >>= 1; |
} |
prsc++; |
} |
} |
|
TMR_THRES = (uint16_t)ticks; |
*thres = (uint16_t)ticks; |
TMR_CT &= ~(7<<TMR_CT_PRSC0); // clear prsc bits |
TMR_CT |= (prsc<<TMR_CT_PRSC0); |
|