URL
https://opencores.org/ocsvn/neo430/neo430/trunk
Subversion Repositories neo430
Compare Revisions
- This comparison shows the changes necessary to convert path
/neo430/trunk
- from Rev 122 to Rev 123
- ↔ Reverse comparison
Rev 122 → Rev 123
/doc/NEO430.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/rtl/cfu_templates/multiplier/README.txt
0,0 → 1,45
*************************************************************************************************** |
* Multiply-and-accumulate unit for the custom function unit (CFU) slot of the NEO430 processor * |
* By Stephan Nolting * |
*************************************************************************************************** |
|
This unit implements a 16-bit times 16-bit multiplier computing a 32-bit wide result. |
The operations can be either signed or unsigned. |
Furthermore, the unit provides an internal 32-bit accumulator to perform multiply-and-accumulate operations. |
It is partly compatible to the original MSP430 multiplier. |
|
|
This unit features seven interface registers, that can only be accessed in word (16-bit) mode. |
Write the first operand to one of the following register to perform the according operations: |
|
- CFU_MAC16_MPY : Operand A for unsigned multiplication (write-only) |
- CFU_MAC16_MPYS : Operand A for signed multiplication (write-only) |
- CFU_MAC16_MAC : Operand A for unsigned multiply-and-accumulate (write-only) |
- CFU_MAC16_MACS : Operand A for signed multiply-and-accumulate (write-only) |
|
The second operand is always written to the OP2 register, regardless of the actual operation: |
|
- CFU_MAC16_OP2 : Operand B for all operations (write-only) |
|
The final 32-bit wide result is split-up into two 16-bit registers: |
|
- CFU_MAC16_RESLO : Low word of the result (read-only) |
- CFU_MAC16_RESHI : high word of the result (read-only) |
|
The result can also be "read" as 32-bit value: |
|
- CFU_MAC16_RES_32bit : 32-bit wide result (read-only) |
|
|
To install the hardware of this unit, replace the original neo430_cfu.vhd in the rtl\core folder with the |
neo430_cfu.vhd from this folder. |
|
Include the header file from this folder to you application code to install the required software driver functions. |
|
The header file (cfu_mac16.h) provides the required definitions of the unit's interface registers |
as well as some rudimentary multiplication/multiply-and-accumulate operations implemented as inlined |
C functions. |
|
Include the cfu_mac16.h AFTER you have included the general NEO430 include file: |
#include ".../lib/neo430/neo430.h" |
#include ".../cfu_mac16.h" |
/rtl/cfu_templates/multiplier/cfu_mac16.h
0,0 → 1,179
// ################################################################################################# |
// # < neo430_cfu_mac16.h - MAC16 CFU Access Wrapper > # |
// # ********************************************************************************************* # |
// # This file is part of the NEO430 Processor project: https://github.com/stnolting/neo430 # |
// # Copyright by Stephan Nolting: stnolting@gmail.com # |
// # # |
// # This source file may be used and distributed without restriction provided that this copyright # |
// # statement is not removed from the file and that any derivative work contains the original # |
// # copyright notice and the associated disclaimer. # |
// # # |
// # This source file is free software; you can redistribute it and/or modify it under the terms # |
// # of the GNU Lesser General Public License as published by the Free Software Foundation, # |
// # either version 3 of the License, or (at your option) any later version. # |
// # # |
// # This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; # |
// # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # |
// # See the GNU Lesser General Public License for more details. # |
// # # |
// # You should have received a copy of the GNU Lesser General Public License along with this # |
// # source; if not, download it from https://www.gnu.org/licenses/lgpl-3.0.en.html # |
// # ********************************************************************************************* # |
// # Stephan Nolting, Hannover, Germany 19.07.2017 # |
// ################################################################################################# |
|
#ifndef neo430_cfu_mac16_h |
#define neo430_cfu_mac16_h |
|
// Interface register address definitions |
#define CFU_MAC16_MPY CFU_REG0 // -/w: operand one - multiply unsigned |
#define CFU_MAC16_MPYS CFU_REG1 // -/w: operand one - multiply signed |
#define CFU_MAC16_MAC CFU_REG2 // -/w: operand one - multiply-accumulate unsigned |
#define CFU_MAC16_MACS CFU_REG3 // -/w: operand one - multiply-accumulate signed |
#define CFU_MAC16_OP2 CFU_REG4 // -/w: operand two |
#define CFU_MAC16_RESLO CFU_REG5 // r/-: result low word |
#define CFU_MAC16_RESHI CFU_REG6 // r/-: result high word |
#define CFU_MAC16_RES_32bit (*(REG32 (&CFU_MAC16_RESLO))) // r/-: result word |
|
|
// Function prototypes |
inline uint16_t cfu_mul_u16_u16_u16(uint16_t a, uint16_t b); |
inline int16_t cfu_mul_s16_s16_s16(int16_t a, int16_t b); |
|
inline uint32_t cfu_mul_u16_u16_u32(uint16_t a, uint16_t b); |
inline int32_t cfu_mul_s16_s16_s32(int16_t a, int16_t b); |
|
inline void cfu_mac_clear_accu(void); |
|
inline uint16_t cfu_mac_u16_u16_u16(uint16_t a, uint16_t b); |
inline int16_t cfu_mac_s16_s16_s16(int16_t a, int16_t b); |
|
inline uint32_t cfu_mac_u16_u16_u32(uint16_t a, uint16_t b); |
inline int32_t cfu_mac_s16_s16_s32(int16_t a, int16_t b); |
|
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 16x16=16 multiplication |
* PARAM a unsigned 16-bit operand a |
* PARAM b unsigned 16-bit operand b |
* RETURN unsigned 16-bit result (lower result word) |
* ------------------------------------------------------------ */ |
inline uint16_t cfu_mul_u16_u16_u16(uint16_t a, uint16_t b) { |
|
CFU_MAC16_MPY = a; |
CFU_MAC16_OP2 = b; |
return CFU_MAC16_RESLO; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Signed 16x16=16 multiplication |
* PARAM a signed 16-bit operand a |
* PARAM b signed 16-bit operand b |
* RETURN signed 16-bit result (lower result word) |
* ------------------------------------------------------------ */ |
inline int16_t cfu_mul_s16_s16_s16(int16_t a, int16_t b) { |
|
CFU_MAC16_MPYS = (uint16_t)a; |
CFU_MAC16_OP2 = (uint16_t)b; |
return (int16_t)CFU_MAC16_RESLO; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 16x16=32 multiplication |
* PARAM a signed 16-bit operand a |
* PARAM b signed 16-bit operand b |
* RETURN signed 16-bit result |
* ------------------------------------------------------------ */ |
inline uint32_t cfu_mul_u16_u16_u32(uint16_t a, uint16_t b) { |
|
CFU_MAC16_MPY = a; |
CFU_MAC16_OP2 = b; |
return CFU_MAC16_RES_32bit; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Signed 16x16=32 multiplication |
* PARAM a signed 16-bit operand a |
* PARAM b signed 16-bit operand b |
* RETURN signed 32-bit result (lower result word) |
* ------------------------------------------------------------ */ |
inline int32_t cfu_mul_s16_s16_s32(int16_t a, int16_t b) { |
|
CFU_MAC16_MPYS = (uint16_t)a; |
CFU_MAC16_OP2 = (uint16_t)b; |
return (int32_t)CFU_MAC16_RES_32bit; |
} |
|
|
|
/* ------------------------------------------------------------ |
* INFO Clear accumulator |
* ------------------------------------------------------------ */ |
inline void cfu_mac_clear_accu(void) { |
|
CFU_MAC16_MPY = 0; |
CFU_MAC16_OP2 = 0; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 16x16=16 multiply-and-accumulate |
* PARAM a unsigned 16-bit operand a |
* PARAM b unsigned 16-bit operand b |
* RETURN unsigned 16-bit result (lower result word) |
* ------------------------------------------------------------ */ |
inline uint16_t cfu_mac_u16_u16_u16(uint16_t a, uint16_t b) { |
|
CFU_MAC16_MAC = a; |
CFU_MAC16_OP2 = b; |
return CFU_MAC16_RESLO; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Signed 16x16=16 multiply-and-accumulate |
* PARAM a signed 16-bit operand a |
* PARAM b signed 16-bit operand b |
* RETURN signed 16-bit result (lower result word) |
* ------------------------------------------------------------ */ |
inline int16_t cfu_mac_s16_s16_s16(int16_t a, int16_t b) { |
|
CFU_MAC16_MACS = (uint16_t)a; |
CFU_MAC16_OP2 = (uint16_t)b; |
return (int16_t)CFU_MAC16_RESLO; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 16x16=32 multiply-and-accumulate |
* PARAM a signed 16-bit operand a |
* PARAM b signed 16-bit operand b |
* RETURN signed 16-bit result |
* ------------------------------------------------------------ */ |
inline uint32_t cfu_mac_u16_u16_u32(uint16_t a, uint16_t b) { |
|
CFU_MAC16_MAC = a; |
CFU_MAC16_OP2 = b; |
return CFU_MAC16_RES_32bit; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Signed 16x16=32 multiply-and-accumulate |
* PARAM a signed 16-bit operand a |
* PARAM b signed 16-bit operand b |
* RETURN signed 32-bit result (lower result word) |
* ------------------------------------------------------------ */ |
inline int32_t cfu_mac_s16_s16_s32(int16_t a, int16_t b) { |
|
CFU_MAC16_MACS = (uint16_t)a; |
CFU_MAC16_OP2 = (uint16_t)b; |
return (int32_t)CFU_MAC16_RES_32bit; |
} |
|
|
#endif // neo430_cfu_mac16_h |
/rtl/cfu_templates/multiplier/neo430_cfu.vhd
0,0 → 1,173
-- ################################################################################################# |
-- # << NEO430 - 16x16=32-Bit Multiply/Acuumulate Unit >> # |
-- # ********************************************************************************************* # |
-- # NOTE: This unit is NOT fully compatible to the original TI MSP430 multiplier! # |
-- # ********************************************************************************************* # |
-- # This file is part of the NEO430 Processor project: http://opencores.org/project,neo430 # |
-- # Copyright 2015-2016, Stephan Nolting: stnolting@gmail.com # |
-- # # |
-- # This source file may be used and distributed without restriction provided that this copyright # |
-- # statement is not removed from the file and that any derivative work contains the original # |
-- # copyright notice and the associated disclaimer. # |
-- # # |
-- # This source file is free software; you can redistribute it and/or modify it under the terms # |
-- # of the GNU Lesser General Public License as published by the Free Software Foundation, # |
-- # either version 3 of the License, or (at your option) any later version. # |
-- # # |
-- # This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; # |
-- # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # |
-- # See the GNU Lesser General Public License for more details. # |
-- # # |
-- # You should have received a copy of the GNU Lesser General Public License along with this # |
-- # source; if not, download it from http://www.gnu.org/licenses/lgpl-3.0.en.html # |
-- # ********************************************************************************************* # |
-- # Stephan Nolting, Hannover, Germany 19.07.2016 # |
-- ################################################################################################# |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
library work; |
use work.neo430_package.all; |
|
entity neo430_cfu is |
port ( |
-- host access -- |
clk_i : in std_ulogic; -- global clock line |
rden_i : in std_ulogic; -- read enable |
wren_i : in std_ulogic_vector(01 downto 0); -- 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 |
); |
end neo430_cfu; |
|
architecture neo430_cfu_mac16_rtl of neo430_cfu is |
|
-- interface register addresses -- |
constant mac16_base_c : std_ulogic_vector(15 downto 0) := cfu_base_c; |
constant mac16_size_c : natural := cfu_size_c; |
|
constant mac16_mpy_addr_c : std_ulogic_vector(15 downto 0) := cfu_reg0_addr_c; -- -/w: operand A for unsigned multiplication |
constant mac16_mpys_addr_c : std_ulogic_vector(15 downto 0) := cfu_reg1_addr_c; -- -/w: operand A for signed multiplication |
constant mac16_mac_addr_c : std_ulogic_vector(15 downto 0) := cfu_reg2_addr_c; -- -/w: operand A for unsigned dmultiply-and-add |
constant mac16_macs_addr_c : std_ulogic_vector(15 downto 0) := cfu_reg3_addr_c; -- -/w: operand A for signed dmultiply-and-add |
constant mac16_op2_addr_c : std_ulogic_vector(15 downto 0) := cfu_reg4_addr_c; -- -/w: operand B (for all operations) |
constant mac16_reslo_addr_c : std_ulogic_vector(15 downto 0) := cfu_reg5_addr_c; -- r/-: low part of result |
constant mac16_reshi_addr_c : std_ulogic_vector(15 downto 0) := cfu_reg6_addr_c; -- r/-: high part of result |
|
-- IO space: module base address -- |
constant hi_abb_c : natural := index_size(io_size_c)-1; -- high address boundary bit |
constant lo_abb_c : natural := index_size(mac16_size_c); -- low address boundary bit |
|
-- access control -- |
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! |
|
-- accessible regs -- |
signal op_a, op_b : std_ulogic_vector(15 downto 0); |
signal mac_res : std_ulogic_vector(32 downto 0); |
|
-- control -- |
signal mode : std_ulogic_vector(01 downto 0); -- function select |
signal run : std_ulogic; |
signal run_s0 : std_ulogic; |
signal run_s1 : std_ulogic; |
|
-- mac core -- |
signal op_a_int, op_a_ff : std_ulogic_vector(16 downto 0); |
signal op_b_int, op_b_ff : std_ulogic_vector(16 downto 0); |
signal mul_res : std_ulogic_vector(33 downto 0); |
|
begin |
|
-- Access Control ----------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = mac16_base_c(hi_abb_c downto lo_abb_c)) else '0'; |
addr <= mac16_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(0) and wren_i(1); |
|
|
-- Write access ------------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
wr_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
run <= '0'; |
if (wr_en = '1') then -- only full word accesses! |
-- operands -- |
case addr is |
when mac16_mpy_addr_c | mac16_mpys_addr_c | mac16_mac_addr_c | mac16_macs_addr_c => -- operand A |
op_a <= data_i; |
when mac16_op2_addr_c => -- operand B |
run <= '1'; -- trigger operation |
op_b <= data_i; |
when others => |
NULL; |
end case; |
-- operation -- |
case (addr) is |
when mac16_mpy_addr_c => |
mode <= "00"; -- multiply unsigned |
when mac16_mpys_addr_c => |
mode <= "01"; -- multiply signed |
when mac16_mac_addr_c => |
mode <= "10"; -- multiply-accumulate unsigned |
when mac16_macs_addr_c => |
mode <= "11"; -- multiply-accumulate signed |
when others => |
NULL; |
end case; |
end if; |
end if; |
end process wr_access; |
|
-- signed/unsigned mode -- |
op_a_int <= (op_a(15) and mode(0)) & op_a(15 downto 0); -- final operand A (16-bit) |
op_b_int <= (op_b(15) and mode(0)) & op_b(15 downto 0); -- final operand B (16-bit) |
|
|
-- MAC core ----------------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
mac_core: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- stage 0 -- |
op_a_ff <= op_a_int; |
op_b_ff <= op_b_int; |
run_s0 <= run; |
-- stage 1 -- |
mul_res <= std_ulogic_vector(signed(op_a_ff) * signed(op_b_ff)); |
run_s1 <= run_s0; |
-- stage 2 -- |
if (run_s1 = '1') then |
if (mode(1) = '1') then -- accumulate |
mac_res <= std_ulogic_vector(unsigned('0' & mac_res(31 downto 0)) + unsigned('0' & mul_res(31 downto 0))); |
else -- simple multiplication |
mac_res <= '0' & mul_res(31 downto 0); |
end if; |
end if; |
end if; |
end process mac_core; |
|
|
-- Read access -------------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
rd_access: process(clk_i) |
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 = mac16_reslo_addr_c) then |
data_o <= mac_res(15 downto 00); |
else -- mac16_reshi_addr_c => |
data_o <= mac_res(31 downto 16); |
end if; |
end if; |
end if; |
end process rd_access; |
|
|
end neo430_cfu_mac16_rtl; |
/rtl/core/neo430_cfu.vhd
26,7 → 26,7
-- # You should have received a copy of the GNU Lesser General Public License along with this # |
-- # source; if not, download it from https://www.gnu.org/licenses/lgpl-3.0.en.html # |
-- # ********************************************************************************************* # |
-- # Stephan Nolting, Hannover, Germany 18.06.2017 # |
-- # Stephan Nolting, Hannover, Germany 19.06.2017 # |
-- ################################################################################################# |
|
library ieee; |
91,7 → 91,7
wr_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- write access to the low byte (bits 7..0) -- |
-- write access to the low bytes (bits 7..0) -- |
if (acc_en = '1') and (bwr_en(0) = '1') then -- valid write acces to LO byte |
case addr is |
when cfu_reg0_addr_c => user_reg0(7 downto 0) <= data_i(7 downto 0); |
105,7 → 105,7
when others => NULL; |
end case; |
end if; |
-- write access to the high byte (bits 15..8) -- |
-- write access to the high bytes (bits 15..8) -- |
if (acc_en = '1') and (bwr_en(1) = '1') then -- valid write access to HI byte |
case addr is |
when cfu_reg0_addr_c => user_reg0(15 downto 8) <= data_i(15 downto 8); |
/rtl/core/neo430_package.vhd
19,7 → 19,7
-- # You should have received a copy of the GNU Lesser General Public License along with this # |
-- # source; if not, download it from https://www.gnu.org/licenses/lgpl-3.0.en.html # |
-- # ********************************************************************************************* # |
-- # Stephan Nolting, Hannover, Germany 17.07.2017 # |
-- # Stephan Nolting, Hannover, Germany 19.07.2017 # |
-- ################################################################################################# |
|
library ieee; |
30,7 → 30,7
|
-- Processor Hardware Version ------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant hw_version_c : std_ulogic_vector(15 downto 0) := x"0120"; -- no touchy! |
constant hw_version_c : std_ulogic_vector(15 downto 0) := x"0121"; -- no touchy! |
|
-- Internal Functions --------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
86,7 → 86,7
constant wb32_wr_adr_hi_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(wb32_base_c) + x"0006"); |
constant wb32_data_lo_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(wb32_base_c) + x"0008"); |
constant wb32_data_hi_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(wb32_base_c) + x"000A"); |
--constant ... : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(wb32_base_c) + x"000C"); |
--constant reserved : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(wb32_base_c) + x"000C"); |
constant wb32_ctrl_addr_c : std_ulogic_vector(15 downto 0) := std_ulogic_vector(unsigned(wb32_base_c) + x"000E"); |
|
-- IO: USART -- |
/rtl/core/neo430_wb_interface.vhd
19,7 → 19,7
-- # You should have received a copy of the GNU Lesser General Public License along with this # |
-- # source; if not, download it from https://www.gnu.org/licenses/lgpl-3.0.en.html # |
-- # ********************************************************************************************* # |
-- # Stephan Nolting, Hannover, Germany 17.07.2017 # |
-- # Stephan Nolting, Hannover, Germany 19.07.2017 # |
-- ################################################################################################# |
|
library ieee; |
65,10 → 65,9
constant ctrl_pending_c : natural := 15; -- r/-: pending wb transfer |
|
-- access control -- |
signal acc_en : std_ulogic; -- module access enable |
signal addr : std_ulogic_vector(15 downto 0); -- access address |
signal wr_en : std_ulogic; -- word write enable |
signal bwr_en : std_ulogic_vector(01 downto 0); -- byte write enable |
signal acc_en : std_ulogic; -- module access enable |
signal addr : std_ulogic_vector(15 downto 0); -- access address |
signal wr_en : std_ulogic; |
|
-- accessible regs -- |
signal wb_addr : std_ulogic_vector(31 downto 0); |
85,11 → 84,9
|
-- Access control ----------------------------------------------------------- |
-- ----------------------------------------------------------------------------- |
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = wb32_base_c(hi_abb_c downto lo_abb_c)) else '0'; |
addr <= wb32_base_c(15 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 1) & '0'; -- word aligned |
bwr_en(0) <= acc_en and wren_i(0); |
bwr_en(1) <= acc_en and wren_i(1); |
wr_en <= acc_en and wren_i(1) and wren_i(0); |
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = wb32_base_c(hi_abb_c downto lo_abb_c)) else '0'; |
addr <= wb32_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(0) and wren_i(1); |
|
|
-- Write access ------------------------------------------------------------- |
97,26 → 94,27
wr_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
wb_we_o <= '0'; |
for i in 0 to 1 loop |
if (bwr_en(i) = '1') then |
if (acc_en = '1') and (wren_i(i) = '1') then -- valid byte write |
case addr is |
when wb32_rd_adr_lo_addr_c => |
wb_addr(i*8+7 downto i*8) <= data_i(i*8+7 downto i*8); |
wb_addr(7+i*8 downto 0+i*8) <= data_i(7+i*8 downto 0+i*8); |
wb_we_o <= '0'; |
when wb32_rd_adr_hi_addr_c => |
wb_addr(i*8+7+16 downto i*8+16) <= data_i(i*8+7 downto i*8); |
wb_addr(23+i*8 downto 16+i*8) <= data_i(7+i*8 downto 0+i*8); |
wb_we_o <= '0'; |
when wb32_wr_adr_lo_addr_c => |
wb_addr(i*8+7 downto i*8) <= data_i(i*8+7 downto i*8); |
wb_addr(7+i*8 downto 0+i*8) <= data_i(7+i*8 downto 0+i*8); |
wb_we_o <= '1'; |
when wb32_wr_adr_hi_addr_c => |
wb_addr(i*8+7+16 downto i*8+16) <= data_i(i*8+7 downto i*8); |
wb_addr(23+i*8 downto 16+i*8) <= data_i(7+i*8 downto 0+i*8); |
wb_we_o <= '1'; |
when wb32_data_lo_addr_c => |
wb_wdata(i*8+7 downto i*8) <= data_i(i*8+7 downto i*8); |
wb_wdata(7+i*8 downto 0+i*8) <= data_i(7+i*8 downto 0+i*8); |
when wb32_data_hi_addr_c => |
wb_wdata(i*8+7+16 downto i*8+16) <= data_i(i*8+7 downto i*8); |
wb_wdata(23+i*8 downto 16+i*8) <= data_i(7+i*8 downto 0+i*8); |
when wb32_ctrl_addr_c => |
if (i = 0) then -- low byte |
if (i = 0) then |
byte_en(0) <= data_i(ctrl_byte_en0_c); |
byte_en(1) <= data_i(ctrl_byte_en1_c); |
byte_en(2) <= data_i(ctrl_byte_en2_c); |
/sw/lib/neo430/neo430.h
23,7 → 23,7
// # You should have received a copy of the GNU Lesser General Public License along with this # |
// # source; if not, download it from https://www.gnu.org/licenses/lgpl-3.0.en.html # |
// # ********************************************************************************************* # |
// # Stephan Nolting, Hannover, Germany 17.07.2017 # |
// # Stephan Nolting, Hannover, Germany 19.07.2017 # |
// ################################################################################################# |
|
#ifndef neo430_h |
53,34 → 53,34
#define REG16 (volatile uint16_t*) |
#define REG32 (volatile uint32_t*) |
|
/* --- Custom Functions Unit --- */ |
#define CFU_REG0 (*(REG16 0xFF80)) // r/w: simple register |
#define CFU_REG0_LO (*(REG8 0xFF80)) // r/w: simple register |
#define CFU_REG0_HI (*(REG8 0xFF81)) // r/w: simple register |
#define CFU_REG1 (*(REG16 0xFF82)) // r/w: simple register |
#define CFU_REG1_LO (*(REG8 0xFF82)) // r/w: simple register |
#define CFU_REG1_HI (*(REG8 0xFF83)) // r/w: simple register |
#define CFU_REG2 (*(REG16 0xFF84)) // r/w: simple register |
#define CFU_REG2_LO (*(REG8 0xFF84)) // r/w: simple register |
#define CFU_REG2_HI (*(REG8 0xFF85)) // r/w: simple register |
#define CFU_REG3 (*(REG16 0xFF86)) // r/w: simple register |
#define CFU_REG3_LO (*(REG8 0xFF86)) // r/w: simple register |
#define CFU_REG3_HI (*(REG8 0xFF87)) // r/w: simple register |
#define CFU_REG4 (*(REG16 0xFF88)) // r/w: simple register |
#define CFU_REG4_LO (*(REG8 0xFF88)) // r/w: simple register |
#define CFU_REG4_HI (*(REG8 0xFF89)) // r/w: simple register |
#define CFU_REG5 (*(REG16 0xFF8A)) // r/w: simple register |
#define CFU_REG5_LO (*(REG8 0xFF8A)) // r/w: simple register |
#define CFU_REG5_HI (*(REG8 0xFF8B)) // r/w: simple register |
#define CFU_REG6 (*(REG16 0xFF8C)) // r/w: simple register |
#define CFU_REG6_LO (*(REG8 0xFF8C)) // r/w: simple register |
#define CFU_REG6_HI (*(REG8 0xFF8D)) // r/w: simple register |
#define CFU_REG7 (*(REG16 0xFF8E)) // r/w: simple register |
#define CFU_REG7_LO (*(REG8 0xFF8E)) // r/w: simple register |
#define CFU_REG7_HI (*(REG8 0xFF8F)) // r/w: simple register |
/* --- Custom Function Unit - CFU --- */ |
#define CFU_REG0 (*(REG16 0xFF80)) // r/w: simple register, customize it! |
#define CFU_REG0_LO (*(REG8 0xFF80)) // r/w: simple register, customize it! |
#define CFU_REG0_HI (*(REG8 0xFF81)) // r/w: simple register, customize it! |
#define CFU_REG1 (*(REG16 0xFF82)) // r/w: simple register, customize it! |
#define CFU_REG1_LO (*(REG8 0xFF82)) // r/w: simple register, customize it! |
#define CFU_REG1_HI (*(REG8 0xFF83)) // r/w: simple register, customize it! |
#define CFU_REG2 (*(REG16 0xFF84)) // r/w: simple register, customize it! |
#define CFU_REG2_LO (*(REG8 0xFF84)) // r/w: simple register, customize it! |
#define CFU_REG2_HI (*(REG8 0xFF85)) // r/w: simple register, customize it! |
#define CFU_REG3 (*(REG16 0xFF86)) // r/w: simple register, customize it! |
#define CFU_REG3_LO (*(REG8 0xFF86)) // r/w: simple register, customize it! |
#define CFU_REG3_HI (*(REG8 0xFF87)) // r/w: simple register, customize it! |
#define CFU_REG4 (*(REG16 0xFF88)) // r/w: simple register, customize it! |
#define CFU_REG4_LO (*(REG8 0xFF88)) // r/w: simple register, customize it! |
#define CFU_REG4_HI (*(REG8 0xFF89)) // r/w: simple register, customize it! |
#define CFU_REG5 (*(REG16 0xFF8A)) // r/w: simple register, customize it! |
#define CFU_REG5_LO (*(REG8 0xFF8A)) // r/w: simple register, customize it! |
#define CFU_REG5_HI (*(REG8 0xFF8B)) // r/w: simple register, customize it! |
#define CFU_REG6 (*(REG16 0xFF8C)) // r/w: simple register, customize it! |
#define CFU_REG6_LO (*(REG8 0xFF8C)) // r/w: simple register, customize it! |
#define CFU_REG6_HI (*(REG8 0xFF8D)) // r/w: simple register, customize it! |
#define CFU_REG7 (*(REG16 0xFF8E)) // r/w: simple register, customize it! |
#define CFU_REG7_LO (*(REG8 0xFF8E)) // r/w: simple register, customize it! |
#define CFU_REG7_HI (*(REG8 0xFF8F)) // r/w: simple register, customize it! |
|
|
/* --- WB32 --- */ |
/* --- Wishbone Bus Adapter - WB32 --- */ |
#define WB32_LRA (*(REG16 0xFF90)) // -/w: low address for read transfer |
#define WB32_HRA (*(REG16 0xFF92)) // -/w: high address for read transfer (+trigger) |
#define WB32_LWA (*(REG16 0xFF94)) // -/w: low address for write transfer |
91,9 → 91,10
#define WB32_CT (*(REG16 0xFF9E)) // r/w: control register |
|
// WB32 - 32-bit register access |
#define WB32_RA_32bit (*(REG32 0xFF90)) // -/w: address for read transfer (+trigger) |
#define WB32_WA_32bit (*(REG32 0xFF94)) // -/w: address for write transfer (+trigger) |
#define WB32_D_32bit (*(REG32 0xFF98)) // r/w: read/write data |
#define WB32_RA_32bit (*(REG32 (&WB32_LRA))) // -/w: address for read transfer (+trigger) |
#define WB32_WA_32bit (*(REG32 (&WB32_LWA))) // -/w: address for write transfer (+trigger) |
#define WB32_D_32bit (*(REG32 (&WB32_LD))) // r/w: read/write data (for 32-bit access) |
#define WB32_D_8bit (*(REG8 (&WB32_LD))) // r/w: read/write data (for 8-bit access) |
|
// WB32 control register |
#define WB32_CT_WBSEL0 0 // -/w: wishbone data byte enable bit 0 |
104,7 → 105,7
#define WB32_CT_PENDING 15 // r/-: pending transfer |
|
|
/* --- USART/USI --- */ |
/* --- Universal Serial Transceiver - USART/USI --- */ |
#define USI_SPIRTX (*(REG16 0xFFA0)) // r/w: spi receive/transmit register |
#define USI_UARTRTX (*(REG16 0xFFA2)) // r/w: uart receive/transmit register |
#define USI_BAUD (*(REG16 0xFFA4)) // r/w: uart baud rate generator value |
153,7 → 154,7
// 7: CLK/4096 |
|
|
/* --- GPIO --- */ |
/* --- Genearl Purpose Inputs/Outputs - GPIO --- */ |
#define GPIO_IN (*(REG16 0xFFB0)) // r/-: parallel input |
#define GPIO_OUT (*(REG16 0xFFB2)) // r/w: parallel output |
#define GPIO_CTRL (*(REG16 0xFFB4)) // -/w: control register |
167,7 → 168,7
// bit 2: General interrupt enable flag |
|
|
/* --- High-Precision Timer --- */ |
/* --- High-Precision Timer - TIMER --- */ |
#define TMR_CNT (*(REG16 0xFFC0)) // r/w: counter register |
#define TMR_THRES (*(REG16 0xFFC2)) // r/w: threshold register |
#define TMR_CT (*(REG16 0xFFC4)) // r/w: control register |
191,7 → 192,7
// 7: CLK/4096 |
|
|
/* --- Watchdog Timer --- */ |
/* --- Watchdog Timer - WTD --- */ |
#define WDT_CTRL (*(REG16 0xFFD0)) // r/w: Watchdog control register |
|
// Watchdog control register |
214,7 → 215,7
// 7: CLK/4096 |
|
|
/* --- SysConfig --- */ |
/* --- System Configuration - SYSCONFIG --- */ |
#define CPUID0 (*(REG16 0xFFE0)) // r/-: HW version |
#define CPUID1 (*(REG16 0xFFE2)) // r/-: system configuration |
#define CPUID2 (*(REG16 0xFFE4)) // r/-: CPU identifier |
223,10 → 224,6
#define CPUID5 (*(REG16 0xFFEA)) // r/-: DMEM/RAM size in bytes |
#define CPUID6 (*(REG16 0xFFEC)) // r/-: clock speed lo |
#define CPUID7 (*(REG16 0xFFEE)) // r/-: clock speed hi |
|
// SysConfig - 32-bit register access |
#define CLOCKSPEED_32bit (*(REG32 0xFFEC)) // r/-: clock speed (in Hz) |
|
// Aliases |
#define HW_VERSION CPUID0 // r/-: HW verison number |
#define SYS_FEATURES CPUID1 // r/-: synthesized system features |
237,6 → 234,9
#define CLOCKSPEED_LO CPUID6 // r/-: clock speed (in Hz) low part |
#define CLOCKSPEED_HI CPUID7 // r/-: clock speed (in Hz) high part |
|
// SysConfig - 32-bit register access |
#define CLOCKSPEED_32bit (*(REG32 (&CLOCKSPEED_LO))) // r/-: clock speed (in Hz) |
|
// SYS features |
#define SYS_CFU_EN 0 // CFU synthesized |
#define SYS_WB32_EN 1 // WB32 synthesized |
/sw/lib/neo430/neo430_wishbone.h
20,7 → 20,7
// # source; if not, download it from https://www.gnu.org/licenses/lgpl-3.0.en.html # |
// # ********************************************************************************************* # |
// # Thanks to Edward Sherriff! # |
// # Stephan Nolting, Hannover, Germany 17.07.2017 # |
// # Stephan Nolting, Hannover, Germany 19.07.2017 # |
// ################################################################################################# |
|
#ifndef neo430_wishbone_h |
147,7 → 147,7
uint8_t wishbone_read8(uint32_t a) { |
|
// 8-bit transfer, classic cycle |
WB32_CT = 1 << (a & 3); // corresponding byte enable |
WB32_CT = 1 << (((uint8_t)a) & 3); // corresponding byte enable |
|
// device address aligned to 8-bit + transfer trigger |
WB32_RA_32bit = a; |
156,7 → 156,7
while((WB32_CT & (1<<WB32_CT_PENDING)) != 0); |
|
// select correct byte to be written |
volatile uint8_t* in = (uint8_t*)(&WB32_LD + ((uint16_t)a & 3)); |
volatile uint8_t* in = (uint8_t*)(&WB32_D_8bit + ((uint8_t)a & 3)); |
return *in; |
} |
|
169,10 → 169,10
void wishbone_write8(uint32_t a, uint8_t d) { |
|
// 8-bit transfer, classic cycle |
WB32_CT = 1 << (a & 3); // corresponding byte enable |
WB32_CT = 1 << (((uint8_t)a) & 3); // corresponding byte enable |
|
// select correct byte to be written |
volatile uint8_t* out = (uint8_t*)(&WB32_LD + ((uint16_t)a & 3)); |
volatile uint8_t* out = (uint8_t*)(&WB32_D_8bit + ((uint8_t)a & 3)); |
*out = d; |
|
// device address aligned to 8-bit + transfer trigger |
287,7 → 287,7
uint8_t wishbone_read8_pipelined(uint32_t a) { |
|
// 8-bit transfer, pipelined cycle |
WB32_CT = (1 << (a & 3)) | 0x10; // corresponding byte enable |
WB32_CT = (1 << (((uint8_t)a) & 3)) | 0x10; // corresponding byte enable |
|
// device address aligned to 8-bit + transfer trigger |
WB32_RA_32bit = a; |
296,7 → 296,7
while((WB32_CT & (1<<WB32_CT_PENDING)) != 0); |
|
// select correct byte to be read |
volatile uint8_t* in = (uint8_t*)(&WB32_LD + ((uint16_t)a & 3)); |
volatile uint8_t* in = (uint8_t*)(&WB32_D_8bit + ((uint8_t)a & 3)); |
return *in; |
} |
|
309,10 → 309,10
void wishbone_write8_pipelined(uint32_t a, uint8_t d) { |
|
// 8-bit transfer, pipelined cycle |
WB32_CT = (1 << (a & 3)) | 0x10; // corresponding byte enable |
WB32_CT = (1 << (((uint8_t)a) & 3)) | 0x10; // corresponding byte enable |
|
// select correct byte to be written |
volatile uint8_t* out = (uint8_t*)(&WB32_LD + ((uint16_t)a & 3)); |
volatile uint8_t* out = (uint8_t*)(&WB32_D_8bit + ((uint8_t)a & 3)); |
*out = d; |
|
// device address aligned to 8-bit + transfer trigger |