OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk/rtl/core
    from Rev 51 to Rev 52
    Reverse comparison

Rev 51 → Rev 52

/neorv32_cfs.vhd
45,7 → 45,9
 
entity neorv32_cfs is
generic (
CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000" -- custom CFS configuration conduit generic
CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic
CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
CFS_OUT_SIZE : positive := 32 -- size of CFS output conduit in bits
);
port (
-- host access --
66,8 → 68,8
irq_o : out std_ulogic; -- interrupt request
irq_ack_i : in std_ulogic; -- interrupt acknowledge
-- custom io (conduits) --
cfs_in_i : in std_ulogic_vector(31 downto 0); -- custom inputs
cfs_out_o : out std_ulogic_vector(31 downto 0) -- custom outputs
cfs_in_i : in std_ulogic_vector(CFS_IN_SIZE-1 downto 0); -- custom inputs
cfs_out_o : out std_ulogic_vector(CFS_OUT_SIZE-1 downto 0) -- custom outputs
);
end neorv32_cfs;
 
100,10 → 102,12
rden <= acc_en and rden_i; -- the read access is always a full 32-bit word wide; if required, the byte/half-word select/masking is done in the CPU
 
 
-- CFS Generic ----------------------------------------------------------------------------
-- CFS Generics ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- In its default version, the CFS provides a single generic: CFS_CONFIG. This generic can be set using the processor top's IO_CFS_CONFIG generic.
-- It is intended as a "conduit" to propagate custom implementation option from the top down to this entiy.
-- In its default version, the CFS provides the configuration generics. single generic:
-- CFS_IN_SIZE configures the size (in bits) of the CFS input conduit cfs_in_i
-- CFS_OUT_SIZE configures the size (in bits) of the CFS output conduit cfs_out_o
-- CFS_CONFIG is a blank 32-bit generic. It is intended as a "generic conduit" to propagate custom configuration flags from the top entity down to this entiy.
 
 
-- CFS IOs --------------------------------------------------------------------------------
206,7 → 210,7
-- ack_o <= ... -- or define the ACK by yourself (example: some registers are read-only, some others can only be written, ...)
 
-- write access --
for i in 0 to 3 loop -- iterate over all 4 bytes in a word
for i in 0 to 3 loop
if (wren = '1') then -- word-wide write-access only!
case addr is -- make sure to use the internal 'addr' signal for the read/write interface
when cfs_reg0_addr_c => cfs_reg_wr(0) <= data_i; -- for example: control register
/neorv32_cpu.vhd
5,7 → 5,9
-- # * neorv32_cpu.vhd - CPU top entity #
-- # * neorv32_cpu_alu.vhd - Arithmetic/logic unit #
-- # * neorv32_cpu_bus.vhd - Instruction and data bus interface unit #
-- # * neorv32_cpu_cp_muldiv.vhd - MULDIV co-processor #
-- # * neorv32_cpu_cp_bitmanip.vhd - Bit-manipulation co-processor ('B') #
-- # * neorv32_cpu_cp_fpu.vhd - Single-precision FPU co-processor ('F') #
-- # * neorv32_cpu_cp_muldiv.vhd - Integer multiplier/divider co-processor ('M') #
-- # * neorv32_cpu_ctrl.vhd - CPU control and CSR system #
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder #
-- # * neorv32_cpu_regfile.vhd - Data register file #
62,10 → 64,11
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
121,27 → 124,31
architecture neorv32_cpu_rtl of neorv32_cpu is
 
-- local signals --
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
signal comparator : std_ulogic_vector(1 downto 0); -- comparator result
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result
signal rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
signal alu_wait : std_ulogic; -- alu is busy due to iterative unit
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch
signal bus_d_wait : std_ulogic; -- wait for current bus data access
signal csr_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
signal mar : std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
signal ma_instr : std_ulogic; -- misaligned instruction address
signal ma_load : std_ulogic; -- misaligned load data address
signal ma_store : std_ulogic; -- misaligned store data address
signal be_instr : std_ulogic; -- bus error on instruction access
signal be_load : std_ulogic; -- bus error on load data access
signal be_store : std_ulogic; -- bus error on store data access
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction)
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
signal comparator : std_ulogic_vector(1 downto 0); -- comparator result
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result
signal mem_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
signal mem_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data
signal alu_wait : std_ulogic; -- alu is busy due to iterative unit
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch
signal bus_d_wait : std_ulogic; -- wait for current bus data access
signal csr_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
signal mar : std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
signal ma_instr : std_ulogic; -- misaligned instruction address
signal ma_load : std_ulogic; -- misaligned load data address
signal ma_store : std_ulogic; -- misaligned store data address
signal be_instr : std_ulogic; -- bus error on instruction access
signal be_load : std_ulogic; -- bus error on load data access
signal be_store : std_ulogic; -- bus error on store data access
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction)
signal fpu_mem_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data form FPU
signal fpu_rm : std_ulogic_vector(2 downto 0); -- FPU rounding mode
signal fpu_flags : std_ulogic_vector(4 downto 0); -- FPU exception flags
 
-- co-processor interface --
signal cp_start : std_ulogic_vector(7 downto 0); -- trigger co-processor i
174,9 → 181,12
-- A extension - only lr.w and sc.w are supported yet --
assert not (CPU_EXTENSION_RISCV_A = true) report "NEORV32 CPU CONFIG WARNING! Atomic operations extension (A) only supports <lr.w> and <sc.w> instructions." severity warning;
 
-- Bit manipulation notifier --
assert not (CPU_EXTENSION_RISCV_B = true) report "NEORV32 CPU CONFIG WARNING! Bit manipulation extension (B) is still highly experimental (not ratified yet)." severity warning;
-- FIXME: Bit manipulation warning --
assert not (CPU_EXTENSION_RISCV_B = true) report "NEORV32 CPU CONFIG WARNING! Bit manipulation extension (B) is still HIGHLY EXPERIMENTAL (and spec. is not ratified yet)." severity warning;
 
-- FIXME: Floating-point extension warning --
assert not (CPU_EXTENSION_RISCV_F = true) report "NEORV32 CPU CONFIG WARNING! 32-bit floating-point extension (F) is WORK-IN-PROGRESS and NOT OPERATIONAL yet." severity warning;
 
-- PMP regions check --
assert not (PMP_NUM_REGIONS > 64) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out of valid range (0..64)." severity error;
-- PMP granulartiy --
205,6 → 215,7
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit manipulation extensions?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_F => CPU_EXTENSION_RISCV_F, -- implement 32-bit floating-point extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
234,6 → 245,9
fetch_pc_o => fetch_pc, -- PC for instruction fetch
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction)
csr_rdata_o => csr_rdata, -- CSR read data
-- FPU interface --
fpu_rm_o => fpu_rm, -- rounding mode
fpu_flags_i => fpu_flags, -- exception flags
-- interrupts (risc-v compliant) --
msw_irq_i => msw_irq_i, -- machine software interrupt
mext_irq_i => mext_irq_i, -- machine external interrupt
271,7 → 285,7
clk_i => clk_i, -- global clock, rising edge
ctrl_i => ctrl, -- main control bus
-- data input --
mem_i => rdata, -- memory read data
mem_i => mem_rdata, -- memory read data
alu_i => alu_res, -- ALU result
-- data output --
rs1_o => rs1, -- operand 1
396,11 → 410,40
cp_valid(3) <= cp_start(3); -- always assigned even if Zicsr extension is disabled to make sure CPU does not get stalled if there is an accidental access
 
 
-- Co-Processor 4..7: Not Implemented Yet -------------------------------------------------
-- Co-Processor 4: Single-Precision Floating-Point Unit ('F' Extension) -------------------
-- -------------------------------------------------------------------------------------------
cp_result(4) <= (others => '0');
cp_valid(4) <= '0';
--
neorv32_cpu_cp_fpu_inst_true:
if (CPU_EXTENSION_RISCV_F = true) generate
neorv32_cpu_cp_fpu_inst: neorv32_cpu_cp_fpu
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl, -- main control bus
start_i => cp_start(4), -- trigger operation
-- data input --
frm_i => fpu_rm, -- rounding mode
reg_i => rs1, -- rf source
mem_i => mem_rdata, -- memory read-data
-- result and status --
fflags_o => fpu_flags, -- exception flags
mem_o => fpu_mem_wdata, -- memory write-data
res_o => cp_result(4), -- operation result
valid_o => cp_valid(4) -- data output valid
);
end generate;
 
neorv32_cpu_cp_fpu_inst_false:
if (CPU_EXTENSION_RISCV_F = false) generate
fpu_flags <= (others => '0');
fpu_mem_wdata <= (others => '0');
cp_result(4) <= (others => '0');
cp_valid(4) <= cp_start(4); -- to make sure CPU does not get stalled if there is an accidental access
end generate;
 
 
-- Co-Processor 5..7: Not Implemented Yet -------------------------------------------------
-- -------------------------------------------------------------------------------------------
cp_result(5) <= (others => '0');
cp_valid(5) <= '0';
--
436,8 → 479,8
be_instr_o => be_instr, -- bus error on instruction access
-- cpu data access interface --
addr_i => alu_add, -- ALU.add result -> access address
wdata_i => rs2, -- write data
rdata_o => rdata, -- read data
wdata_i => mem_wdata, -- write data
rdata_o => mem_rdata, -- read data
mar_o => mar, -- current memory address register
d_wait_o => bus_d_wait, -- wait for access to complete
--
474,6 → 517,9
d_bus_lock_o => d_bus_lock_o -- locked/exclusive access
);
 
-- memory write data --
mem_wdata <= fpu_mem_wdata when ((CPU_EXTENSION_RISCV_F = true) and (ctrl(ctrl_bus_wd_sel_c) = '1')) else rs2;
 
-- current privilege level --
i_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c);
d_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c);
/neorv32_cpu_control.vhd
55,6 → 55,7
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
84,6 → 85,9
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
-- FPU interface --
fpu_rm_o : out std_ulogic_vector(02 downto 0); -- rounding mode
fpu_flags_i : in std_ulogic_vector(04 downto 0); -- exception flags
-- interrupts (risc-v compliant) --
msw_irq_i : in std_ulogic; -- machine software interrupt
mext_irq_i : in std_ulogic; -- machine external interrupt
176,6 → 180,8
is_atomic_sc : std_ulogic;
is_bitmanip_imm : std_ulogic;
is_bitmanip_reg : std_ulogic;
is_float_f_reg : std_ulogic;
is_float_i_reg : std_ulogic;
sys_env_cmd : std_ulogic_vector(11 downto 0);
end record;
signal decode_aux : decode_aux_t;
196,6 → 202,8
is_ci_nxt : std_ulogic;
is_cp_op : std_ulogic; -- current instruction is a co-processor operation
is_cp_op_nxt : std_ulogic;
is_fp : std_ulogic; -- floating-point operation - do not access to integer register file
is_fp_nxt : std_ulogic;
--
branch_taken : std_ulogic; -- branch condition fullfilled
pc : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
322,6 → 330,9
pmpcfg_rd : pmp_ctrl_rd_t; -- physical memory protection - actual read data
pmpaddr : pmp_addr_t; -- physical memory protection - address registers
pmpaddr_rd : pmp_addr_rd_t; -- physical memory protection - actual read data
--
frm : std_ulogic_vector(02 downto 0); -- frm (R/W): FPU rounding mode
fflags : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags
end record;
signal csr : csr_t;
 
606,7 → 617,7
imm_o <= execute_engine.next_pc;
else -- "normal" immediate from instruction word
case opcode_v is -- save some bits here, the two LSBs are always "11" for rv32
when opcode_store_c => -- S-immediate
when opcode_store_c | opcode_fsw_c => -- S-immediate
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
695,6 → 706,7
execute_engine.i_reg <= execute_engine.i_reg_nxt;
execute_engine.is_ci <= execute_engine.is_ci_nxt;
execute_engine.is_cp_op <= execute_engine.is_cp_op_nxt;
execute_engine.is_fp <= execute_engine.is_fp_nxt;
-- PC & IR of "last executed" instruction --
if (execute_engine.state = EXECUTE) then
execute_engine.last_pc <= execute_engine.pc;
768,6 → 780,8
decode_aux.is_atomic_sc <= '0';
decode_aux.is_bitmanip_imm <= '0';
decode_aux.is_bitmanip_reg <= '0';
decode_aux.is_float_f_reg <= '0';
decode_aux.is_float_i_reg <= '0';
 
-- is immediate ALU operation? --
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
776,7 → 790,7
decode_aux.rs1_is_r0 <= not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
 
-- is atomic load-reservate/store-conditional? --
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') then -- valid atomic sub-opcode
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c);
end if;
820,6 → 834,26
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) then -- SBSEXT
decode_aux.is_bitmanip_reg <= '1';
end if;
 
-- floating-point FLOAT_register operations --
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11110")) or -- FMV.W.X
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00000")) or -- FADD.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00001")) or -- FSUB.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00011")) or -- FDIV.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01011") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00000")) or -- FSQRT.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMIN.S / FMAX.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.S.W*
decode_aux.is_float_f_reg <= '1';
end if;
-- floating-point INTEGER_register operations --
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMV.X.W / FCLASS.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "10100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FEQ.S / FLT.S / FLE.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11000") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.W*.S
decode_aux.is_float_i_reg <= '1';
end if;
 
-- system/environment instructions --
sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c; -- sum-up set bits
decode_aux.sys_env_cmd(11 downto 0) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unsued bits to always-zero
837,6 → 871,7
execute_engine.i_reg_nxt <= execute_engine.i_reg;
execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
execute_engine.is_ci_nxt <= execute_engine.is_ci;
execute_engine.is_fp_nxt <= execute_engine.is_fp;
execute_engine.sleep_nxt <= execute_engine.sleep;
execute_engine.branched_nxt <= execute_engine.branched;
--
897,6 → 932,9
 
when DISPATCH => -- Get new command from instruction issue engine
-- ------------------------------------------------------------
-- housekeeping --
execute_engine.is_cp_op_nxt <= '0'; -- init
execute_engine.is_fp_nxt <= '0'; -- init
-- PC update --
execute_engine.pc_mux_sel <= '0'; -- linear next PC
-- IR update --
1026,13 → 1064,19
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.state_nxt <= DISPATCH;
 
when opcode_load_c | opcode_store_c | opcode_atomic_c => -- load/store / atomic memory access
when opcode_load_c | opcode_store_c | opcode_atomic_c | opcode_flw_c | opcode_fsw_c => -- load/store / atomic memory access / floating-point load/store
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_bus_mo_we_c) <= '1'; -- write to MAR and MDO (MDO only relevant for store)
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "01") then -- floating-point load/store
execute_engine.is_fp_nxt <= decode_aux.is_float_f_reg; -- no integer register file write back for FPU internal operations
ctrl_nxt(ctrl_bus_wd_sel_c) <= '1'; -- use memory-write-data from FPU co-processor (only relevant for float STORE)
end if;
--
if (CPU_EXTENSION_RISCV_A = false) or (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') then -- atomic (A) extension disabled or normal load/store
if (CPU_EXTENSION_RISCV_A = false) or -- atomic extension disabled
(execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "00") or -- normal integerload/store
((CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "01")) then -- floating-point load/store
execute_engine.state_nxt <= LOADSTORE_0;
else -- atomic operation
atomic_ctrl.env_start <= not execute_engine.i_reg(instr_funct5_lsb_c); -- LR: start LOCKED memory access environment
1074,6 → 1118,17
execute_engine.state_nxt <= SYS_WAIT;
end if;
 
when opcode_fop_c => -- floating-point operations (1 or 2 operands)
-- ------------------------------------------------------------
execute_engine.state_nxt <= SYS_WAIT;
if (CPU_EXTENSION_RISCV_F = true) then
execute_engine.is_fp_nxt <= decode_aux.is_float_f_reg; -- no integer register file write back for FPU internal operations
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- use FPU CP
execute_engine.is_cp_op_nxt <= '1'; -- this is a CP operation
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
execute_engine.state_nxt <= ALU_WAIT;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
execute_engine.state_nxt <= SYS_WAIT;
1114,7 → 1169,11
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
-- ------------------------------------------------------------
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back)
if (CPU_EXTENSION_RISCV_F = false) then
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back)
else
ctrl_nxt(ctrl_rf_wb_en_c) <= not execute_engine.is_fp; -- allow write back if NOT <FPU-internal operation>
end if;
-- cp access or alu.shift? --
if (execute_engine.is_cp_op = '1') then
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
1204,8 → 1263,11
execute_engine.state_nxt <= DISPATCH;
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') or (decode_aux.is_atomic_sc = '1') then -- load / load-reservate / store conditional
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
ctrl_nxt(ctrl_rf_wb_en_c) <= not execute_engine.is_fp; -- allow write back if NOT <FPU-internal operation>
end if;
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) = opcode_flw_c(6 downto 2)) then -- floating-point LOAD.word
ctrl_nxt(ctrl_cp_fpu_mem_we_c) <= '1'; -- co-processor register file write-back
end if;
atomic_ctrl.env_end <= not decode_aux.is_atomic_lr; -- normal end of LOCKED (atomic) memory access environment - if we are not starting it via LR instruction
execute_engine.state_nxt <= DISPATCH;
end if;
1243,13 → 1305,17
 
-- low privilege level access to hpm counters? --
csr_mcounteren_hpm_v := (others => '0');
if (CPU_EXTENSION_RISCV_U = true) then -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented
if (CPU_EXTENSION_RISCV_U = true) then
csr_mcounteren_hpm_v(HPM_NUM_CNTS-1 downto 0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0);
else -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented
csr_mcounteren_hpm_v := (others => '0');
end if;
 
-- check CSR access --
case csr.addr is
-- standard read/write CSRs --
when csr_fflags_c | csr_frm_c | csr_fcsr_c => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_F); -- full access for everyone if F extension is enabled
--
when csr_mstatus_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
when csr_mstatush_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
when csr_misa_c => csr_acc_valid <= csr.priv_m_mode;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
1410,6 → 1476,7
case opcode_v is
 
-- check sufficient LUI, UIPC, JAL (only check actual OPCODE) --
-- ------------------------------------------------------------
when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
illegal_instruction <= '0';
-- illegal E-CPU register? --
1418,6 → 1485,7
end if;
 
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
illegal_instruction <= '1';
1441,6 → 1509,7
end if;
 
when opcode_alui_c => -- check ALUI.funct7
-- ------------------------------------------------------------
if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
illegal_instruction <= '1';
1460,6 → 1529,7
end if;
 
when opcode_load_c => -- check LOAD.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
1475,6 → 1545,7
end if;
 
when opcode_store_c => -- check STORE.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
1488,6 → 1559,7
end if;
 
when opcode_branch_c => -- check BRANCH.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
1504,6 → 1576,7
end if;
 
when opcode_jalr_c => -- check JALR.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
illegal_instruction <= '0';
else
1514,7 → 1587,8
illegal_register <= '1';
end if;
 
when opcode_fence_c => -- fence instructions --
when opcode_fence_c => -- fence instructions
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
illegal_instruction <= '0';
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
1523,7 → 1597,8
illegal_instruction <= '1';
end if;
 
when opcode_syscsr_c => -- check system instructions --
when opcode_syscsr_c => -- check system instructions
-- ------------------------------------------------------------
-- CSR access --
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
1561,7 → 1636,8
illegal_instruction <= '1';
end if;
 
when opcode_atomic_c => -- atomic instructions --
when opcode_atomic_c => -- atomic instructions
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_A = true) and -- atomic memory operations (A extension) enabled
((execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) or -- LR
(execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c)) then -- SC
1570,7 → 1646,27
illegal_instruction <= '1';
end if;
 
when opcode_fop_c => -- floating point operations (dual-operand)
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_F = true) and -- F extension enabled
(execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations
((decode_aux.is_float_f_reg = '1') or (decode_aux.is_float_i_reg = '1')) then -- float_reg or int_reg operations
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
 
when opcode_flw_c | opcode_fsw_c => -- floating point load/store word
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_F = true) and -- F extension enabled
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then -- 32-bit transfer size
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
 
when others => -- undefined instruction -> illegal!
-- ------------------------------------------------------------
illegal_instruction <= '1';
 
end case;
1870,10 → 1966,9
end process csr_write_data;
 
 
-- Control and Status Registers Write Access ----------------------------------------------
-- Control and Status Registers - Write Access --------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_write_access: process(rstn_i, clk_i)
variable pmpaddr_v : std_ulogic_vector(6 downto 0);
begin
if (rstn_i = '0') then
csr.we <= '0';
1890,23 → 1985,25
csr.mscratch <= x"19880704"; -- :)
csr.mepc <= (others => '0');
csr.mcause <= trap_reset_c; -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt")
--
csr.mtval <= (others => '0');
csr.mip_clear <= (others => '0');
--
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => '1'));
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => '1'));
--
csr.mhpmevent <= (others => (others => '0'));
csr.mhpmevent <= (others => (others => '0'));
--
csr.mcounteren_cy <= '0';
csr.mcounteren_tm <= '0';
csr.mcounteren_ir <= '0';
csr.mcounteren_hpm <= (others => '0');
csr.mcounteren_cy <= '0';
csr.mcounteren_tm <= '0';
csr.mcounteren_ir <= '0';
csr.mcounteren_hpm <= (others => '0');
--
csr.mcountinhibit_cy <= '0';
csr.mcountinhibit_ir <= '0';
csr.mcountinhibit_hpm <= (others => '0');
--
csr.fflags <= (others => '0');
csr.frm <= (others => '0');
 
elsif rising_edge(clk_i) then
-- write access? --
1920,11 → 2017,30
-- CSR access by application software
-- --------------------------------------------------------------------------------
if (csr.we = '1') then -- manual update
case csr.addr is
-- machine trap setup --
-- --------------------------------------------------------------------
when csr_mstatus_c => -- R/W: mstatus - machine status register
 
-- user floating-point CSRs --
-- --------------------------------------------------------------------
if (csr.addr(11 downto 4) = csr_class_float_c) then -- floating point CSR class
-- R/W: fflags - floating-point (FPU) exception flags --
if (csr.addr(3 downto 0) = csr_fflags_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then
csr.fflags <= csr.wdata(4 downto 0);
end if;
-- R/W: frm - floating-point (FPU) rounding mode --
if (csr.addr(3 downto 0) = csr_frm_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then
csr.frm <= csr.wdata(2 downto 0);
end if;
-- R/W: fflags - floating-point (FPU) control/status (frm + fflags) --
if (csr.addr(3 downto 0) = csr_fcsr_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then
csr.frm <= csr.wdata(7 downto 5);
csr.fflags <= csr.wdata(4 downto 0);
end if;
end if;
 
-- machine trap setup --
-- --------------------------------------------------------------------
if (csr.addr(11 downto 4) = csr_setup_c) then -- ftrap setup CSR class
-- R/W: mstatus - machine status register --
if (csr.addr(3 downto 0) = csr_mstatus_c(3 downto 0)) then
csr.mstatus_mie <= csr.wdata(03);
csr.mstatus_mpie <= csr.wdata(07);
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
1933,7 → 2049,9
else -- only machine mode is available
csr.mstatus_mpp <= priv_mode_m_c;
end if;
when csr_mie_c => -- R/W: mie - machine interrupt enable register
end if;
-- R/W: mie - machine interrupt enable register --
if (csr.addr(3 downto 0) = csr_mie_c(3 downto 0)) then
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
1940,30 → 2058,44
for i in 0 to 15 loop -- fast interrupt channels 0..15
csr.mie_firqe(i) <= csr.wdata(16+i);
end loop; -- i
when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
end if;
-- R/W: mtvec - machine trap-handler base address (for ALL exceptions) --
if (csr.addr(3 downto 0) = csr_mtvec_c(3 downto 0)) then
csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
when csr_mcounteren_c => -- R/W: machine counter enable register
end if;
-- R/W: machine counter enable register --
if (csr.addr(3 downto 0) = csr_mcounteren_c(3 downto 0)) then
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented
csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h]
csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h]
csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h]
csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to hpmcounterx[h]
else
NULL;
end if;
end if;
end if;
 
-- machine trap handling --
-- --------------------------------------------------------------------
when csr_mscratch_c => -- R/W: mscratch - machine scratch register
-- machine trap handling --
-- --------------------------------------------------------------------
if (csr.addr(11 downto 4) = csr_class_trap_c) then -- machine trap handling CSR class
-- R/W: mscratch - machine scratch register --
if (csr.addr(3 downto 0) = csr_mscratch_c(3 downto 0)) then
csr.mscratch <= csr.wdata;
when csr_mepc_c => -- R/W: mepc - machine exception program counter
end if;
-- R/W: mepc - machine exception program counter --
if (csr.addr(3 downto 0) = csr_mepc_c(3 downto 0)) then
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
when csr_mcause_c => -- R/W: mcause - machine trap cause
end if;
-- R/W: mcause - machine trap cause --
if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
when csr_mtval_c => -- R/W: mtval - machine bad address/instruction
end if;
-- R/W: mtval - machine bad address/instruction --
if (csr.addr(3 downto 0) = csr_mtval_c(3 downto 0)) then
csr.mtval <= csr.wdata;
when csr_mip_c => -- R/W: mip - machine interrupt pending
end if;
-- R/W: mip - machine interrupt pending --
if (csr.addr(3 downto 0) = csr_mip_c(3 downto 0)) then
csr.mip_clear(interrupt_msw_irq_c) <= not csr.wdata(03);
csr.mip_clear(interrupt_mtime_irq_c) <= not csr.wdata(07);
csr.mip_clear(interrupt_mext_irq_c) <= not csr.wdata(11);
1970,89 → 2102,78
for i in 0 to 15 loop -- fast interrupt channels 0..15
csr.mip_clear(interrupt_firq_0_c+i) <= not csr.wdata(16+i);
end loop; -- i
end if;
end if;
 
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
-- --------------------------------------------------------------------
when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c |
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
if (PMP_NUM_REGIONS > 0) then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write)
csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X (rights.execute)
csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_L
csr.pmpcfg(i)(4) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(i)(5) <= '0'; -- reserved
csr.pmpcfg(i)(6) <= '0'; -- reserved
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
end if;
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
-- --------------------------------------------------------------------
if (csr.addr(11 downto 4) = csr_class_pmpcfg_c) then -- pmp configuration CSR class
if (PMP_NUM_REGIONS > 0) then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write)
csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X (rights.execute)
csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_L
csr.pmpcfg(i)(4) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(i)(5) <= '0'; -- reserved
csr.pmpcfg(i)(6) <= '0'; -- reserved
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
end if;
end loop; -- i (PMP regions)
else
NULL;
end if;
end if;
end loop; -- i (PMP regions)
end if;
end if;
 
-- physical memory protection: R/W: pmpaddr* - PMP address registers --
-- --------------------------------------------------------------------
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c |
csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c =>
if (PMP_NUM_REGIONS > 0) then
for i in 0 to PMP_NUM_REGIONS-1 loop
pmpaddr_v := std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i); -- adapt to *non-aligned* base address (csr_pmpaddr0_c)
if (csr.addr(6 downto 0) = pmpaddr_v) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr.wdata;
csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
end if;
end loop; -- i (PMP regions)
else
NULL;
end if;
-- physical memory protection: R/W: pmpaddr* - PMP address registers --
-- --------------------------------------------------------------------
if (csr.addr(11 downto 4) = csr_pmpaddr0_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr16_c(11 downto 4)) or
(csr.addr(11 downto 4) = csr_pmpaddr32_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr48_c(11 downto 4)) then
if (PMP_NUM_REGIONS > 0) then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(6 downto 0) = std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i)) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr.wdata;
csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
end if;
end loop; -- i (PMP regions)
end if;
end if;
 
-- machine counter setup --
-- --------------------------------------------------------------------
when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
-- machine counter setup --
-- --------------------------------------------------------------------
-- R/W: mcountinhibit - machine counter-inhibit register --
if (csr.addr = csr_mcountinhibit_c) then
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
end if;
 
-- machine performance-monitoring event selector --
-- --------------------------------------------------------------------
when csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c |
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector
if (HPM_NUM_CNTS > 0) then
for i in 0 to HPM_NUM_CNTS-1 loop
if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME"
end if;
end loop; -- i (CSRs)
else
NULL;
end if;
-- machine performance-monitoring event selector --
-- --------------------------------------------------------------------
if (unsigned(csr.addr) >= unsigned(csr_mhpmevent3_c)) and (unsigned(csr.addr) <= unsigned(csr_mhpmevent31_c)) then
if (HPM_NUM_CNTS > 0) then
for i in 0 to HPM_NUM_CNTS-1 loop
if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME"
end if;
end loop; -- i (CSRs)
end if;
end if;
 
-- undefined --
-- --------------------------------------------------------------------
when others =>
NULL;
 
end case;
 
-- --------------------------------------------------------------------------------
-- CSR access by hardware
-- --------------------------------------------------------------------------------
else
 
-- floating-point (FPU) exception flags --
-- --------------------------------------------------------------------
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.state = ALU_WAIT) then -- FIXME?
csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags")
end if;
 
-- mcause, mepc, mtval: machine trap cause, PC and value register --
-- --------------------------------------------------------------------
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
2103,9 → 2224,42
csr.mstatus_mpp <= priv_mode_m_c;
end if;
 
end if; -- hardware csr access
end if; -- /hardware csr access
end if;
 
-- --------------------------------------------------------------------------------
-- override write access for disabled functions
-- --------------------------------------------------------------------------------
 
-- user mode disabled --
if (CPU_EXTENSION_RISCV_U = false) then
csr.privilege <= priv_mode_m_c;
csr.mstatus_mpp <= priv_mode_m_c;
csr.mcounteren_cy <= '0';
csr.mcounteren_tm <= '0';
csr.mcounteren_ir <= '0';
csr.mcounteren_hpm <= (others => '0');
end if;
 
-- pmp disabled --
if (PMP_NUM_REGIONS = 0) then
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => '1'));
end if;
 
-- hpms disabled --
if (HPM_NUM_CNTS = 0) then
csr.mhpmevent <= (others => (others => '0'));
csr.mcounteren_hpm <= (others => '0');
csr.mcountinhibit_hpm <= (others => '0');
end if;
 
-- floating-point extension disabled --
if (CPU_EXTENSION_RISCV_F = false) then
csr.fflags <= (others => '0');
csr.frm <= (others => '0');
end if;
 
end if;
end process csr_write_access;
 
2139,7 → 2293,10
end loop; -- i
end process pmp_rd_dummy;
 
-- FPU rounding mode --
fpu_rm_o <= csr.frm;
 
 
-- Control and Status Registers - Counters ------------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_counters: process(clk_i)
2254,7 → 2411,7
cnt_event_nxt(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
 
 
-- Control and Status Registers Read Access -----------------------------------------------
-- Control and Status Registers - Read Access ---------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_read_access: process(clk_i)
begin
2264,6 → 2421,25
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
case csr.addr is
 
-- user floating-point CSRs --
-- --------------------------------------------------------------------
when csr_fflags_c => -- R/W: fflags - floating-point (FPU) exception flags
csr.rdata <= (others => '0');
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
csr.rdata(4 downto 0) <= csr.fflags;
end if;
when csr_frm_c => -- R/W: frm - floating-point (FPU) rounding mode
csr.rdata <= (others => '0');
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
csr.rdata(2 downto 0) <= csr.frm;
end if;
when csr_fcsr_c => -- R/W: fflags - floating-point (FPU) control/status (frm + fflags)
csr.rdata <= (others => '0');
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
csr.rdata(7 downto 5) <= csr.frm;
csr.rdata(4 downto 0) <= csr.fflags;
end if;
 
-- machine trap setup --
when csr_mstatus_c => -- R/W: mstatus - machine status register
csr.rdata(03) <= csr.mstatus_mie; -- MIE
2278,6 → 2454,7
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr.rdata(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_F); -- F CPU extension
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
/neorv32_cpu_cp_fpu.vhd
0,0 → 1,83
-- #################################################################################################
-- # << NEORV32 - CPU Co-Processor: Single-Precision Floating Point Unit (RISC-V "F" Extension) >> #
-- # ********************************************************************************************* #
-- # #
-- # !!! WORK-IN-PROGRESS !!! #
-- # !!! THIS UNIT IS NOT FUNCTIONAL YET !!! #
-- # #
-- # ********************************************************************************************* #
-- # !!! Enabling the F extension does not has an effect on the CPU. If F is enabled, there !!! #
-- # !!! will be no traps when trying to execute floating-point instructions, since the main !!! #
-- # !!! CPU control unit allready provides all necessary F-extension infrastructure. !!! #
-- # !!! However, all F instructions will always return zero. !!! #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
-- #################################################################################################
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library neorv32;
use neorv32.neorv32_package.all;
 
entity neorv32_cpu_cp_fpu is
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
start_i : in std_ulogic; -- trigger operation
-- data input --
frm_i : in std_ulogic_vector(2 downto 0); -- rounding mode
reg_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source (rs1)
mem_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory read-data
-- result and status --
fflags_o : out std_ulogic_vector(4 downto 0); -- exception flags
mem_o : out std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result
valid_o : out std_ulogic -- data output valid
);
end neorv32_cpu_cp_fpu;
 
architecture neorv32_cpu_cp_fpu_rtl of neorv32_cpu_cp_fpu is
 
begin
 
-- There is nothing to see here yet -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fflags_o <= (others => '0');
mem_o <= (others => '0');
res_o <= (others => '0');
valid_o <= start_i;
 
 
end neorv32_cpu_cp_fpu_rtl;
/neorv32_cpu_decompressor.vhd
137,9 → 137,13
ci_instr32_o(instr_imm12_lsb_c + 9) <= ci_instr16_i(10);
end if;
 
when "010" => -- C.LW
when "010" | "011" => -- C.LW / C.FLW
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.LW
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
else -- C.FLW
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_flw_c;
end if;
ci_instr32_o(21 downto 20) <= "00";
ci_instr32_o(22) <= ci_instr16_i(6);
ci_instr32_o(23) <= ci_instr16_i(10);
151,9 → 155,13
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c); -- x8 - x15
 
when "110" => -- C.SW
when "110" | "111" => -- C.SW / C.FSW
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.SW
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
else -- C.FSW
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_fsw_c;
end if;
ci_instr32_o(08 downto 07) <= "00";
ci_instr32_o(09) <= ci_instr16_i(6);
ci_instr32_o(10) <= ci_instr16_i(10);
362,9 → 370,13
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_illegal_o <= ci_instr16_i(12);
 
when "010" => -- C.LWSP
when "010" | "011" => -- C.LWSP / C.FLWSP
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.LWSP
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
else -- C.FLWSP
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_flw_c;
end if;
ci_instr32_o(21 downto 20) <= "00";
ci_instr32_o(22) <= ci_instr16_i(4);
ci_instr32_o(23) <= ci_instr16_i(5);
377,9 → 389,13
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
 
when "110" => -- C.SWSP
when "110" | "111" => -- C.SWSP / C.FSWSP
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.SWSP
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
else -- C.FSWSP
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_fsw_c;
end if;
ci_instr32_o(08 downto 07) <= "00";
ci_instr32_o(09) <= ci_instr16_i(9);
ci_instr32_o(10) <= ci_instr16_i(10);
/neorv32_neoled.vhd
0,0 → 1,394
-- #################################################################################################
-- # << NEORV32 - Smart LED (WS2811/WS2812) Interface (NEOLED) >> #
-- # ********************************************************************************************* #
-- # Hardware interface for direct control of "smart LEDs" using an asynchronouse serial data #
-- # line. Compatible with the WS2811 and WS2812 LEDs. #
-- # #
-- # NeoPixel-compatible, RGB (24-bit) and RGBW (32-bit) #
-- # (c) "NeoPixel" is a trademark of Adafruit Industries. #
-- # #
-- # The interface uses a programmable carries frequency (800 KHz for the WS2812 LEDs) #
-- # configurable via the control register's clock prescaler bits (ctrl_clksel*_c) and the period #
-- # length configuration bits (ctrl_t_tot_*_c). "high-times" for sending a ZERO or a ONE bit are #
-- # configured using the ctrl_t_0h_*_c and ctrl_t_1h_*_c bits, respectively. 32-bit transfers #
-- # (for RGBW modules) and 24-bit transfers (for RGB modules) are supported via ctrl_mode__c. #
-- # #
-- # The device features a TX buffer with <tx_buffer_entries_c> entries. The devices busy flag and #
-- # IRQ generator can be programmed to either clear the busy flag / send an IRQ when AT LEAST ONE #
-- # FREE BUFFER ENTRY is available (ctrl_bscon_c = 0) or when the WHOLE BUFFER IS EMPTY #
-- # (ctrl_bscon_c = 1). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
-- #################################################################################################
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library neorv32;
use neorv32.neorv32_package.all;
 
entity neorv32_neoled is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- interrupt --
irq_o : out std_ulogic; -- interrupt request
-- NEOLED output --
neoled_o : out std_ulogic -- serial async data line
);
end neorv32_neoled;
 
architecture neorv32_neoled_rtl of neorv32_neoled is
 
-- TX buffer size configuration --
constant tx_buffer_entries_c : natural := 4; -- number of entries in TX buffer, has to be a power of two, min=0
 
-- 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(neoled_size_c); -- low address boundary bit
 
-- access control --
signal acc_en : std_ulogic; -- module access enable
signal addr : std_ulogic_vector(31 downto 0); -- access address
signal wren : std_ulogic; -- word write enable
signal rden : std_ulogic; -- read enable
 
-- Control register bits --
constant ctrl_enable_c : natural := 0; -- r/w: module enable
constant ctrl_mode_c : natural := 1; -- r/w: 0 = 24-bit RGB mode, 1 = 32-bit RGBW mode
constant ctrl_bscon_c : natural := 2; -- r/w: buffer status configuration -> busy_flag/IRQ config
constant ctrl_clksel0_c : natural := 3; -- r/w: prescaler select bit 0
constant ctrl_clksel1_c : natural := 4; -- r/w: prescaler select bit 1
constant ctrl_clksel2_c : natural := 5; -- r/w: prescaler select bit 2
--
constant ctrl_bufs_0_c : natural := 6; -- r/-: log2(tx_buffer_entries_c) bit 0
constant ctrl_bufs_1_c : natural := 7; -- r/-: log2(tx_buffer_entries_c) bit 1
constant ctrl_bufs_2_c : natural := 8; -- r/-: log2(tx_buffer_entries_c) bit 2
constant ctrl_bufs_3_c : natural := 9; -- r/-: log2(tx_buffer_entries_c) bit 3
--
constant ctrl_t_tot_0_c : natural := 10; -- r/w: pulse-clock ticks per total period bit 0
constant ctrl_t_tot_1_c : natural := 11; -- r/w: pulse-clock ticks per total period bit 1
constant ctrl_t_tot_2_c : natural := 12; -- r/w: pulse-clock ticks per total period bit 2
constant ctrl_t_tot_3_c : natural := 13; -- r/w: pulse-clock ticks per total period bit 3
constant ctrl_t_tot_4_c : natural := 14; -- r/w: pulse-clock ticks per total period bit 4
--
constant ctrl_t_0h_0_c : natural := 15; -- r/w: pulse-clock ticks per ZERO high-time bit 0
constant ctrl_t_0h_1_c : natural := 16; -- r/w: pulse-clock ticks per ZERO high-time bit 1
constant ctrl_t_0h_2_c : natural := 17; -- r/w: pulse-clock ticks per ZERO high-time bit 2
constant ctrl_t_0h_3_c : natural := 18; -- r/w: pulse-clock ticks per ZERO high-time bit 3
constant ctrl_t_0h_4_c : natural := 19; -- r/w: pulse-clock ticks per ZERO high-time bit 4
--
constant ctrl_t_1h_0_c : natural := 20; -- r/w: pulse-clock ticks per ONE high-time bit 0
constant ctrl_t_1h_1_c : natural := 21; -- r/w: pulse-clock ticks per ONE high-time bit 1
constant ctrl_t_1h_2_c : natural := 22; -- r/w: pulse-clock ticks per ONE high-time bit 2
constant ctrl_t_1h_3_c : natural := 23; -- r/w: pulse-clock ticks per ONE high-time bit 3
constant ctrl_t_1h_4_c : natural := 24; -- r/w: pulse-clock ticks per ONE high-time bit 4
--
constant ctrl_tx_status_c : natural := 30; -- r/-: serial TX engine busy when set
constant ctrl_busy_c : natural := 31; -- r/-: busy / buffer status flag (configured via ctrl_bscon_c)
 
-- control register --
type ctrl_t is record
enable : std_ulogic;
bscon : std_ulogic; -- buffer/busy status flag configuration
mode : std_ulogic;
clk_prsc : std_ulogic_vector(2 downto 0);
ready : std_ulogic; -- buffer ready to accept new data
-- pulse config --
t_total : std_ulogic_vector(4 downto 0);
t0_high : std_ulogic_vector(4 downto 0);
t1_high : std_ulogic_vector(4 downto 0);
end record;
signal ctrl : ctrl_t;
 
-- transmission buffer --
type tx_fifo_t is array (0 to tx_buffer_entries_c-1) of std_ulogic_vector(31+1 downto 0);
type tx_buffer_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
wdata : std_ulogic_vector(31 downto 0); -- write data (excluding excluding)
rdata : std_ulogic_vector(31+1 downto 0); -- read data (including mode)
--
w_pnt : std_ulogic_vector(index_size_f(tx_buffer_entries_c) downto 0); -- write pointer
r_pnt : std_ulogic_vector(index_size_f(tx_buffer_entries_c) downto 0); -- read pointer
match : std_ulogic;
empty : std_ulogic;
empty_ff : std_ulogic;
full : std_ulogic;
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
free_ff : std_ulogic;
--
data : tx_fifo_t; -- fifo memory
end record;
signal tx_buffer : tx_buffer_t;
 
-- serial transmission engine --
type serial_state_t is (S_IDLE, S_INIT, S_GETBIT, S_PULSE);
type serial_t is record
-- state control --
state : serial_state_t;
mode : std_ulogic;
busy : std_ulogic;
bit_cnt : std_ulogic_vector(5 downto 0);
-- shift register --
sreg : std_ulogic_vector(31 downto 0);
next_bit : std_ulogic; -- next bit to send
-- pulse generator --
pulse_clk : std_ulogic; -- pulse cycle "clock"
pulse_cnt : std_ulogic_vector(4 downto 0);
t_high : std_ulogic_vector(4 downto 0);
output : std_ulogic;
end record;
signal serial : serial_t;
 
begin
 
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not ((is_power_of_two_f(tx_buffer_entries_c) = false) or (tx_buffer_entries_c > 32768)) report "NEORV32 PROCESSOR CONFIG ERROR! Invalid <IO.NEOPIX> buffer size configuration!" severity error;
 
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = neoled_base_c(hi_abb_c downto lo_abb_c)) else '0';
addr <= neoled_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
 
 
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- access acknowledge --
ack_o <= wren or rden;
 
-- write access --
tx_buffer.we <= '0';
if (wren = '1') then
-- control register --
if (addr = neoled_ctrl_addr_c) then
ctrl.enable <= data_i(ctrl_enable_c);
ctrl.mode <= data_i(ctrl_mode_c);
ctrl.bscon <= data_i(ctrl_bscon_c);
ctrl.clk_prsc <= data_i(ctrl_clksel2_c downto ctrl_clksel0_c);
ctrl.t_total <= data_i(ctrl_t_tot_4_c downto ctrl_t_tot_0_c);
ctrl.t0_high <= data_i(ctrl_t_0h_4_c downto ctrl_t_0h_0_c);
ctrl.t1_high <= data_i(ctrl_t_1h_4_c downto ctrl_t_1h_0_c);
end if;
-- tx data register (FIFO) --
if (addr = neoled_data_addr_c) then
tx_buffer.wdata <= data_i;
tx_buffer.we <= tx_buffer.free; -- only write new data if there is at least one free entry left
end if;
end if;
 
-- read access: control register --
data_o <= (others => '0');
if (rden = '1') and (addr = neoled_ctrl_addr_c) then
data_o(ctrl_enable_c) <= ctrl.enable;
data_o(ctrl_mode_c) <= ctrl.mode;
data_o(ctrl_bscon_c) <= ctrl.bscon;
data_o(ctrl_clksel2_c downto ctrl_clksel0_c) <= ctrl.clk_prsc;
data_o(ctrl_bufs_3_c downto ctrl_bufs_0_c) <= std_ulogic_vector(to_unsigned(index_size_f(tx_buffer_entries_c), 4));
data_o(ctrl_t_tot_4_c downto ctrl_t_tot_0_c) <= ctrl.t_total;
data_o(ctrl_t_0h_4_c downto ctrl_t_0h_0_c) <= ctrl.t0_high;
data_o(ctrl_t_1h_4_c downto ctrl_t_1h_0_c) <= ctrl.t1_high;
data_o(ctrl_tx_status_c) <= serial.busy;
data_o(ctrl_busy_c) <= not ctrl.ready;
end if;
end if;
end process rw_access;
 
-- enable external clock generator --
clkgen_en_o <= ctrl.enable;
 
 
-- TX Buffer (FIFO) -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
instr_prefetch_buffer: process(clk_i)
begin
if rising_edge(clk_i) then
-- write port --
if (ctrl.enable = '0') then
tx_buffer.w_pnt <= (others => '0');
elsif (tx_buffer.we = '1') then
tx_buffer.w_pnt <= std_ulogic_vector(unsigned(tx_buffer.w_pnt) + 1);
end if;
if (tx_buffer.we = '1') then -- write data
tx_buffer.data(to_integer(unsigned(tx_buffer.w_pnt(tx_buffer.w_pnt'left-1 downto 0)))) <= ctrl.mode & tx_buffer.wdata;
end if;
-- read port --
if (ctrl.enable = '0') then
tx_buffer.r_pnt <= (others => '0');
elsif (tx_buffer.re = '1') then
tx_buffer.r_pnt <= std_ulogic_vector(unsigned(tx_buffer.r_pnt) + 1);
end if;
tx_buffer.rdata <= tx_buffer.data(to_integer(unsigned(tx_buffer.r_pnt(tx_buffer.r_pnt'left-1 downto 0)))); -- sync read
-- status buffer --
tx_buffer.empty_ff <= tx_buffer.empty;
tx_buffer.free_ff <= tx_buffer.free;
end if;
end process instr_prefetch_buffer;
 
-- status --
tx_buffer.match <= '1' when (tx_buffer.r_pnt(tx_buffer.r_pnt'left-1 downto 0) = tx_buffer.w_pnt(tx_buffer.w_pnt'left-1 downto 0)) else '0';
tx_buffer.full <= '1' when (tx_buffer.r_pnt(tx_buffer.r_pnt'left) /= tx_buffer.w_pnt(tx_buffer.w_pnt'left)) and (tx_buffer.match = '1') else '0';
tx_buffer.empty <= '1' when (tx_buffer.r_pnt(tx_buffer.r_pnt'left) = tx_buffer.w_pnt(tx_buffer.w_pnt'left)) and (tx_buffer.match = '1') else '0';
tx_buffer.free <= not tx_buffer.full;
tx_buffer.avail <= not tx_buffer.empty;
 
 
-- Buffer Status Flag and IRQ Generator ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- ctrl.bscon = 0: clear buffer/busy status flag and send IRQ if -> there is at least one free entry in buffer
-- ctrl.bscon = 1: clear buffer/busy status flag and send IRQ if -> the complete buffer is empty
irq_generator: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl.enable = '1') then
if (ctrl.bscon = '0') then -- one entry is becoming free
irq_o <= (not tx_buffer.free_ff) and tx_buffer.free;
else -- buffer is becoming empty
irq_o <= (not tx_buffer.empty_ff) and tx_buffer.empty;
end if;
else
irq_o <= '0';
end if;
end if;
end process irq_generator;
 
-- ready flag --
ctrl.ready <= tx_buffer.free when (ctrl.bscon = '0') else tx_buffer.empty;
 
 
-- Serial TX Engine -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
serial_engine: process(clk_i)
begin
if rising_edge(clk_i) then
-- defaults --
serial.pulse_clk <= clkgen_i(to_integer(unsigned(ctrl.clk_prsc)));
 
-- disabled --
if (ctrl.enable = '0') then -- disabled
serial.output <= '0';
serial.state <= S_IDLE;
else
case serial.state is
 
when S_IDLE => -- waiting for new TX data
-- ------------------------------------------------------------
serial.output <= '0';
serial.pulse_cnt <= (others => '0');
if (tx_buffer.avail = '1') then
serial.state <= S_INIT;
end if;
 
when S_INIT => -- initialize TX shift engine
-- ------------------------------------------------------------
if (tx_buffer.rdata(32) = '0') then -- mode = "RGB"
serial.mode <= '0';
serial.bit_cnt <= "011000"; -- total number of bits to send: 3x8=24
else -- mode = "RGBW"
serial.mode <= '1';
serial.bit_cnt <= "100000"; -- total number of bits to send: 4x8=32
end if;
serial.sreg <= tx_buffer.rdata(31 downto 00);
serial.state <= S_GETBIT;
 
when S_GETBIT => -- get next TX bit
-- ------------------------------------------------------------
serial.sreg <= serial.sreg(serial.sreg'left-1 downto 0) & '0'; -- shift left by one position (MSB-first)
serial.bit_cnt <= std_ulogic_vector(unsigned(serial.bit_cnt) - 1);
serial.pulse_cnt <= (others => '0');
if (serial.bit_cnt = "000000") then -- all done?
serial.state <= S_IDLE;
else -- check current data MSB
if (serial.next_bit = '0') then -- send zero-bit
serial.t_high <= ctrl.t0_high;
else -- send one-bit
serial.t_high <= ctrl.t1_high;
end if;
serial.state <= S_PULSE; -- transmit single pulse
serial.output <= '1';
end if;
 
when S_PULSE => -- send pulse with specific duty cycle
-- ------------------------------------------------------------
-- total pulse length = ctrl.t_total
-- pulse high time = serial.t_high
if (serial.pulse_clk = '1') then
serial.pulse_cnt <= std_ulogic_vector(unsigned(serial.pulse_cnt) + 1);
-- T_high reached? --
if (serial.pulse_cnt = serial.t_high) then
serial.output <= '0';
end if;
-- T_total reached? --
if (serial.pulse_cnt = ctrl.t_total) then
serial.state <= S_GETBIT; -- get next bit to send
end if;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
serial.state <= S_IDLE;
 
end case;
end if;
-- serial data output --
neoled_o <= serial.output; -- IOB.FF
end if;
end process serial_engine;
 
-- SREG's TX data: bit 23 for RGB mode (24-bit), bit 31 for RGBW mode (32-bit) --
serial.next_bit <= serial.sreg(23) when (serial.mode = '0') else serial.sreg(31);
 
-- get new TX data --
tx_buffer.re <= '1' when (serial.state = S_IDLE) and (tx_buffer.avail = '1') else '0';
 
-- TX engine status --
serial.busy <= '0' when (serial.state = S_IDLE) or (ctrl.enable = '0') else '1';
 
 
end neorv32_neoled_rtl;
/neorv32_package.vhd
60,7 → 60,7
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- native data path width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050200"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050204"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!
constant rf_r0_is_reg_c : boolean := true; -- reg_file.r0 is a *physical register* that has to be initialized to zero by the CPU HW
203,9 → 203,11
constant uart1_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD0";
constant uart1_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD4";
 
-- reserved --
--constant reserved_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8"; -- base address
--constant reserved_size_c : natural := 2*4; -- module's address space in bytes
-- Smart LED (WS2811/WS2812) Interface (NEOLED) --
constant neoled_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8"; -- base address
constant neoled_size_c : natural := 2*4; -- module's address space in bytes
constant neoled_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8";
constant neoled_data_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFDC";
 
-- System Information Memory (SYSINFO) --
constant sysinfo_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFE0"; -- base address
252,46 → 254,48
constant ctrl_bus_if_c : natural := 33; -- instruction fetch request
constant ctrl_bus_mo_we_c : natural := 34; -- memory address and data output register write enable
constant ctrl_bus_mi_we_c : natural := 35; -- memory data input register write enable
constant ctrl_bus_unsigned_c : natural := 36; -- is unsigned load
constant ctrl_bus_ierr_ack_c : natural := 37; -- acknowledge instruction fetch bus exceptions
constant ctrl_bus_derr_ack_c : natural := 38; -- acknowledge data access bus exceptions
constant ctrl_bus_fence_c : natural := 39; -- executed fence operation
constant ctrl_bus_fencei_c : natural := 40; -- executed fencei operation
constant ctrl_bus_lock_c : natural := 41; -- locked/exclusive bus access
constant ctrl_bus_wd_sel_c : natural := 36; -- memory write-data source select (0=reg_file, 1=co-proc.)
constant ctrl_bus_unsigned_c : natural := 37; -- is unsigned load
constant ctrl_bus_ierr_ack_c : natural := 38; -- acknowledge instruction fetch bus exceptions
constant ctrl_bus_derr_ack_c : natural := 39; -- acknowledge data access bus exceptions
constant ctrl_bus_fence_c : natural := 40; -- executed fence operation
constant ctrl_bus_fencei_c : natural := 41; -- executed fencei operation
constant ctrl_bus_lock_c : natural := 42; -- locked/exclusive bus access
-- co-processors --
constant ctrl_cp_id_lsb_c : natural := 42; -- cp select ID lsb
constant ctrl_cp_id_hsb_c : natural := 43; -- cp select ID hsb
constant ctrl_cp_id_msb_c : natural := 44; -- cp select ID msb
constant ctrl_cp_id_lsb_c : natural := 43; -- cp select ID lsb
constant ctrl_cp_id_hsb_c : natural := 44; -- cp select ID hsb
constant ctrl_cp_id_msb_c : natural := 45; -- cp select ID msb
constant ctrl_cp_fpu_mem_we_c : natural := 46; -- fpu-cp memory-data write enable
-- current privilege level --
constant ctrl_priv_lvl_lsb_c : natural := 45; -- privilege level lsb
constant ctrl_priv_lvl_msb_c : natural := 46; -- privilege level msb
constant ctrl_priv_lvl_lsb_c : natural := 47; -- privilege level lsb
constant ctrl_priv_lvl_msb_c : natural := 48; -- privilege level msb
-- instruction's control blocks (used by cpu co-processors) --
constant ctrl_ir_funct3_0_c : natural := 47; -- funct3 bit 0
constant ctrl_ir_funct3_1_c : natural := 48; -- funct3 bit 1
constant ctrl_ir_funct3_2_c : natural := 49; -- funct3 bit 2
constant ctrl_ir_funct12_0_c : natural := 50; -- funct12 bit 0
constant ctrl_ir_funct12_1_c : natural := 51; -- funct12 bit 1
constant ctrl_ir_funct12_2_c : natural := 52; -- funct12 bit 2
constant ctrl_ir_funct12_3_c : natural := 53; -- funct12 bit 3
constant ctrl_ir_funct12_4_c : natural := 54; -- funct12 bit 4
constant ctrl_ir_funct12_5_c : natural := 55; -- funct12 bit 5
constant ctrl_ir_funct12_6_c : natural := 56; -- funct12 bit 6
constant ctrl_ir_funct12_7_c : natural := 57; -- funct12 bit 7
constant ctrl_ir_funct12_8_c : natural := 58; -- funct12 bit 8
constant ctrl_ir_funct12_9_c : natural := 59; -- funct12 bit 9
constant ctrl_ir_funct12_10_c : natural := 60; -- funct12 bit 10
constant ctrl_ir_funct12_11_c : natural := 61; -- funct12 bit 11
constant ctrl_ir_opcode7_0_c : natural := 62; -- opcode7 bit 0
constant ctrl_ir_opcode7_1_c : natural := 63; -- opcode7 bit 1
constant ctrl_ir_opcode7_2_c : natural := 64; -- opcode7 bit 2
constant ctrl_ir_opcode7_3_c : natural := 65; -- opcode7 bit 3
constant ctrl_ir_opcode7_4_c : natural := 66; -- opcode7 bit 4
constant ctrl_ir_opcode7_5_c : natural := 67; -- opcode7 bit 5
constant ctrl_ir_opcode7_6_c : natural := 68; -- opcode7 bit 6
constant ctrl_ir_funct3_0_c : natural := 49; -- funct3 bit 0
constant ctrl_ir_funct3_1_c : natural := 50; -- funct3 bit 1
constant ctrl_ir_funct3_2_c : natural := 51; -- funct3 bit 2
constant ctrl_ir_funct12_0_c : natural := 52; -- funct12 bit 0
constant ctrl_ir_funct12_1_c : natural := 53; -- funct12 bit 1
constant ctrl_ir_funct12_2_c : natural := 54; -- funct12 bit 2
constant ctrl_ir_funct12_3_c : natural := 55; -- funct12 bit 3
constant ctrl_ir_funct12_4_c : natural := 56; -- funct12 bit 4
constant ctrl_ir_funct12_5_c : natural := 57; -- funct12 bit 5
constant ctrl_ir_funct12_6_c : natural := 58; -- funct12 bit 6
constant ctrl_ir_funct12_7_c : natural := 59; -- funct12 bit 7
constant ctrl_ir_funct12_8_c : natural := 60; -- funct12 bit 8
constant ctrl_ir_funct12_9_c : natural := 61; -- funct12 bit 9
constant ctrl_ir_funct12_10_c : natural := 62; -- funct12 bit 10
constant ctrl_ir_funct12_11_c : natural := 63; -- funct12 bit 11
constant ctrl_ir_opcode7_0_c : natural := 64; -- opcode7 bit 0
constant ctrl_ir_opcode7_1_c : natural := 65; -- opcode7 bit 1
constant ctrl_ir_opcode7_2_c : natural := 66; -- opcode7 bit 2
constant ctrl_ir_opcode7_3_c : natural := 67; -- opcode7 bit 3
constant ctrl_ir_opcode7_4_c : natural := 68; -- opcode7 bit 4
constant ctrl_ir_opcode7_5_c : natural := 69; -- opcode7 bit 5
constant ctrl_ir_opcode7_6_c : natural := 70; -- opcode7 bit 6
-- CPU status --
constant ctrl_sleep_c : natural := 69; -- set when CPU is in sleep mode
constant ctrl_sleep_c : natural := 71; -- set when CPU is in sleep mode
-- control bus size --
constant ctrl_width_c : natural := 70; -- control bus size
constant ctrl_width_c : natural := 72; -- control bus size
 
-- Comparator Bus -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
340,8 → 344,13
-- system/csr --
constant opcode_fence_c : std_ulogic_vector(6 downto 0) := "0001111"; -- fence / fence.i
constant opcode_syscsr_c : std_ulogic_vector(6 downto 0) := "1110011"; -- system/csr access (type via funct3)
-- atomic operations (A) --
-- atomic memory access (A) --
constant opcode_atomic_c : std_ulogic_vector(6 downto 0) := "0101111"; -- atomic operations (A extension)
-- floating point operations (F/D/H/Q) --
constant opcode_flw_c : std_ulogic_vector(6 downto 0) := "0000111"; -- load word
constant opcode_fsw_c : std_ulogic_vector(6 downto 0) := "0100111"; -- store word
constant opcode_fop_c : std_ulogic_vector(6 downto 0) := "1010011"; -- dual/single opearand operation
constant opcode_fmac_c : std_ulogic_vector(6 downto 0) := "100--11"; -- fused multiply-add (three operands)
 
-- RISC-V Funct3 --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
396,14 → 405,28
constant funct5_a_lr_c : std_ulogic_vector(4 downto 0) := "00010"; -- LR
constant funct5_a_sc_c : std_ulogic_vector(4 downto 0) := "00011"; -- SC
 
-- RISC-V Floating-Point Formats ----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant float_single_c : std_ulogic_vector(1 downto 0) := "00"; -- single-precisions (32-bit)
constant float_double_c : std_ulogic_vector(1 downto 0) := "01"; -- double-precisions (64-bit)
constant float_half_c : std_ulogic_vector(1 downto 0) := "10"; -- half-precisions (16-bit)
constant float_quad_c : std_ulogic_vector(1 downto 0) := "11"; -- quad-precisions (64-bit)
 
-- RISC-V CSR Addresses -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- read/write CSRs --
constant csr_class_float_c : std_ulogic_vector(07 downto 0) := x"00"; -- floating point
constant csr_fflags_c : std_ulogic_vector(11 downto 0) := x"001";
constant csr_frm_c : std_ulogic_vector(11 downto 0) := x"002";
constant csr_fcsr_c : std_ulogic_vector(11 downto 0) := x"003";
--
constant csr_setup_c : std_ulogic_vector(07 downto 0) := x"30"; -- trap setup
constant csr_mstatus_c : std_ulogic_vector(11 downto 0) := x"300";
constant csr_misa_c : std_ulogic_vector(11 downto 0) := x"301";
constant csr_mie_c : std_ulogic_vector(11 downto 0) := x"304";
constant csr_mtvec_c : std_ulogic_vector(11 downto 0) := x"305";
constant csr_mcounteren_c : std_ulogic_vector(11 downto 0) := x"306";
--
constant csr_mstatush_c : std_ulogic_vector(11 downto 0) := x"310";
--
constant csr_mcountinhibit_c : std_ulogic_vector(11 downto 0) := x"320";
438,6 → 461,7
constant csr_mhpmevent30_c : std_ulogic_vector(11 downto 0) := x"33e";
constant csr_mhpmevent31_c : std_ulogic_vector(11 downto 0) := x"33f";
--
constant csr_class_trap_c : std_ulogic_vector(07 downto 0) := x"34"; -- machine trap handling
constant csr_mscratch_c : std_ulogic_vector(11 downto 0) := x"340";
constant csr_mepc_c : std_ulogic_vector(11 downto 0) := x"341";
constant csr_mcause_c : std_ulogic_vector(11 downto 0) := x"342";
444,6 → 468,7
constant csr_mtval_c : std_ulogic_vector(11 downto 0) := x"343";
constant csr_mip_c : std_ulogic_vector(11 downto 0) := x"344";
--
constant csr_class_pmpcfg_c : std_ulogic_vector(07 downto 0) := x"3a"; -- pmp configuration
constant csr_pmpcfg0_c : std_ulogic_vector(11 downto 0) := x"3a0";
constant csr_pmpcfg1_c : std_ulogic_vector(11 downto 0) := x"3a1";
constant csr_pmpcfg2_c : std_ulogic_vector(11 downto 0) := x"3a2";
675,10 → 700,10
constant cp_sel_atomic_c : std_ulogic_vector(2 downto 0) := "001"; -- atomic operations; success/failure evaluation ('A' extension)
constant cp_sel_bitmanip_c : std_ulogic_vector(2 downto 0) := "010"; -- bit manipulation ('B' extension)
constant cp_sel_csr_rd_c : std_ulogic_vector(2 downto 0) := "011"; -- CSR read access ('Zicsr' extension)
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "100"; -- reserved
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "101"; -- reserved
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "110"; -- reserved
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "111"; -- reserved
constant cp_sel_fpu_c : std_ulogic_vector(2 downto 0) := "100"; -- loating-point unit ('F' extension)
--constant cp_sel_reserved_c : std_ulogic_vector(2 downto 0) := "101"; -- reserved
--constant cp_sel_reserved_c : std_ulogic_vector(2 downto 0) := "110"; -- reserved
--constant cp_sel_reserved_c : std_ulogic_vector(2 downto 0) := "111"; -- reserved
 
-- ALU Function Codes ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
857,8 → 882,11
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)?
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)?
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)?
);
port (
-- Global control --
903,10 → 931,12
-- PWM (available if IO_PWM_EN = true) --
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels
-- Custom Functions Subsystem IO --
cfs_in_i : in std_ulogic_vector(31 downto 0) := (others => '0'); -- custom CSF inputs
cfs_out_o : out std_ulogic_vector(31 downto 0); -- custom CSF outputs
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom CFS inputs conduit
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit
-- NCO output (available if IO_NCO_EN = true) --
nco_o : out std_ulogic_vector(02 downto 0); -- numerically-controlled oscillator channels
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o : out std_ulogic; -- async serial data line
-- system time input from external MTIME (available if IO_MTIME_EN = false) --
mtime_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time
-- Interrupts --
930,6 → 960,7
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
938,7 → 969,7
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29)
998,12 → 1029,13
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29)
1021,12 → 1053,15
instr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- instruction
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU address result
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
-- data output --
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
-- FPU interface --
fpu_rm_o : out std_ulogic_vector(02 downto 0); -- rounding mode
fpu_flags_i : in std_ulogic_vector(04 downto 0); -- exception flags
-- interrupts (risc-v compliant) --
msw_irq_i : in std_ulogic; -- machine software interrupt
mext_irq_i : in std_ulogic; -- machine external interrupt
1139,6 → 1174,27
);
end component;
 
-- Component: CPU Co-Processor 32-bit FPU ('F' extension) ---------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_cp_fpu
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
start_i : in std_ulogic; -- trigger operation
-- data input --
frm_i : in std_ulogic_vector(2 downto 0); -- rounding mode
reg_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source
mem_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory read-data
-- result and status --
fflags_o : out std_ulogic_vector(4 downto 0); -- exception flags
mem_o : out std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result
valid_o : out std_ulogic -- data output valid
);
end component;
 
-- Component: CPU Bus Interface -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_bus
1580,7 → 1636,9
-- -------------------------------------------------------------------------------------------
component neorv32_cfs
generic (
CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000" -- custom CFS configuration generic
CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic
CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
CFS_OUT_SIZE : positive := 32 -- size of CFS output conduit in bits
);
port (
-- host access --
1601,8 → 1659,8
irq_o : out std_ulogic; -- interrupt request
irq_ack_i : in std_ulogic; -- interrupt acknowledge
-- custom io (conduit) --
cfs_in_i : in std_ulogic_vector(31 downto 0); -- custom inputs
cfs_out_o : out std_ulogic_vector(31 downto 0) -- custom outputs
cfs_in_i : in std_ulogic_vector(CFS_IN_SIZE-1 downto 0); -- custom inputs
cfs_out_o : out std_ulogic_vector(CFS_OUT_SIZE-1 downto 0) -- custom outputs
);
end component;
 
1626,6 → 1684,28
);
end component;
 
-- Component: Smart LED (WS2811/WS2812) Interface (NEOLED) --------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_neoled
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- interrupt --
irq_o : out std_ulogic; -- interrupt request
-- NEOLED output --
neoled_o : out std_ulogic -- serial async data line
);
end component;
 
-- Component: System Configuration Information Memory (SYSINFO) ---------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_sysinfo
1659,7 → 1739,8
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean := true; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean := true; -- implement custom functions subsystem (CFS)?
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)?
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)?
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)?
);
port (
-- host access --
/neorv32_sysinfo.vhd
73,7 → 73,8
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean := true; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean := true; -- implement custom functions subsystem (CFS)?
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)?
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)?
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)?
);
port (
-- host access --
132,19 → 133,20
--
sysinfo_mem(2)(15 downto 07) <= (others => '0'); -- reserved
-- IO --
sysinfo_mem(2)(16) <= bool_to_ulogic_f(IO_GPIO_EN); -- general purpose input/output port unit (GPIO) implemented?
sysinfo_mem(2)(17) <= bool_to_ulogic_f(IO_MTIME_EN); -- machine system timer (MTIME) implemented?
sysinfo_mem(2)(18) <= bool_to_ulogic_f(IO_UART0_EN); -- primary universal asynchronous receiver/transmitter (UART0) implemented?
sysinfo_mem(2)(19) <= bool_to_ulogic_f(IO_SPI_EN); -- serial peripheral interface (SPI) implemented?
sysinfo_mem(2)(20) <= bool_to_ulogic_f(IO_TWI_EN); -- two-wire interface (TWI) implemented?
sysinfo_mem(2)(21) <= bool_to_ulogic_f(IO_PWM_EN); -- pulse-width modulation unit (PWM) implemented?
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_EN); -- watch dog timer (WDT) implemented?
sysinfo_mem(2)(23) <= bool_to_ulogic_f(IO_CFS_EN); -- custom functions subsystem (CFS) implemented?
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_EN); -- true random number generator (TRNG) implemented?
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_NCO_EN); -- numerically-controlled oscillator (NCO) implemented?
sysinfo_mem(2)(26) <= bool_to_ulogic_f(IO_UART1_EN); -- secondary universal asynchronous receiver/transmitter (UART1) implemented?
sysinfo_mem(2)(16) <= bool_to_ulogic_f(IO_GPIO_EN); -- general purpose input/output port unit (GPIO) implemented?
sysinfo_mem(2)(17) <= bool_to_ulogic_f(IO_MTIME_EN); -- machine system timer (MTIME) implemented?
sysinfo_mem(2)(18) <= bool_to_ulogic_f(IO_UART0_EN); -- primary universal asynchronous receiver/transmitter (UART0) implemented?
sysinfo_mem(2)(19) <= bool_to_ulogic_f(IO_SPI_EN); -- serial peripheral interface (SPI) implemented?
sysinfo_mem(2)(20) <= bool_to_ulogic_f(IO_TWI_EN); -- two-wire interface (TWI) implemented?
sysinfo_mem(2)(21) <= bool_to_ulogic_f(IO_PWM_EN); -- pulse-width modulation unit (PWM) implemented?
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_EN); -- watch dog timer (WDT) implemented?
sysinfo_mem(2)(23) <= bool_to_ulogic_f(IO_CFS_EN); -- custom functions subsystem (CFS) implemented?
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_EN); -- true random number generator (TRNG) implemented?
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_NCO_EN); -- numerically-controlled oscillator (NCO) implemented?
sysinfo_mem(2)(26) <= bool_to_ulogic_f(IO_UART1_EN); -- secondary universal asynchronous receiver/transmitter (UART1) implemented?
sysinfo_mem(2)(27) <= bool_to_ulogic_f(IO_NEOLED_EN); -- NeoPixel-compatible smart LED interface (NEOLED) implemented?
--
sysinfo_mem(2)(31 downto 27) <= (others => '0'); -- reserved
sysinfo_mem(2)(31 downto 28) <= (others => '0'); -- reserved
 
-- SYSINFO(3): Cache configuration --
sysinfo_mem(3)(03 downto 00) <= std_ulogic_vector(to_unsigned(index_size_f(ICACHE_BLOCK_SIZE), 4)) when (ICACHE_EN = true) else (others => '0'); -- i-cache: log2(block_size_in_bytes)
/neorv32_top.vhd
103,8 → 103,11
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)?
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)?
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)?
);
port (
-- Global control --
158,12 → 161,15
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels
 
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
cfs_in_i : in std_ulogic_vector(31 downto 0) := (others => '0'); -- custom CFS inputs conduit
cfs_out_o : out std_ulogic_vector(31 downto 0); -- custom CFS outputs conduit
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom CFS inputs conduit
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit
 
-- NCO output (available if IO_NCO_EN = true) --
nco_o : out std_ulogic_vector(02 downto 0); -- numerically-controlled oscillator channels
 
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o : out std_ulogic; -- async serial data line
 
-- system time input from external MTIME (available if IO_MTIME_EN = false) --
mtime_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time
 
201,16 → 207,17
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 clk_gen_en : std_ulogic_vector(07 downto 0);
signal clk_gen_en : std_ulogic_vector(08 downto 0);
--
signal wdt_cg_en : std_ulogic;
signal uart0_cg_en : std_ulogic;
signal uart1_cg_en : std_ulogic;
signal spi_cg_en : std_ulogic;
signal twi_cg_en : std_ulogic;
signal pwm_cg_en : std_ulogic;
signal cfs_cg_en : std_ulogic;
signal nco_cg_en : std_ulogic;
signal wdt_cg_en : std_ulogic;
signal uart0_cg_en : std_ulogic;
signal uart1_cg_en : std_ulogic;
signal spi_cg_en : std_ulogic;
signal twi_cg_en : std_ulogic;
signal pwm_cg_en : std_ulogic;
signal cfs_cg_en : std_ulogic;
signal nco_cg_en : std_ulogic;
signal neoled_cg_en : std_ulogic;
 
-- bus interface --
type bus_interface_t is record
267,6 → 274,8
signal cfs_ack : std_ulogic;
signal nco_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal nco_ack : std_ulogic;
signal neoled_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal neoled_ack : std_ulogic;
signal sysinfo_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal sysinfo_ack : std_ulogic;
 
286,6 → 295,7
signal twi_irq : std_ulogic;
signal cfs_irq : std_ulogic;
signal cfs_irq_ack : std_ulogic;
signal neoled_irq : std_ulogic;
 
-- misc --
signal mtime_time : std_ulogic_vector(63 downto 0); -- current system time from MTIME
364,6 → 374,7
clk_gen_en(5) <= pwm_cg_en;
clk_gen_en(6) <= cfs_cg_en;
clk_gen_en(7) <= nco_cg_en;
clk_gen_en(8) <= neoled_cg_en;
if (or_all_f(clk_gen_en) = '1') then
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1);
end if;
400,6 → 411,7
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit manipulation extensions?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_F => false, -- implement 32-bit floating-point extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
473,7 → 485,7
fast_irq(06) <= spi_irq; -- SPI transmission done
fast_irq(07) <= twi_irq; -- TWI transmission done
fast_irq(08) <= gpio_irq; -- GPIO pin-change
fast_irq(09) <= '0'; -- reserved
fast_irq(09) <= neoled_irq; -- NEOLED buffer free
 
-- fast interrupts - platform level (for custom use) --
fast_irq(10) <= soc_firq_i(0);
591,11 → 603,11
 
-- processor bus: CPU transfer data input --
p_bus.rdata <= (imem_rdata or dmem_rdata or bootrom_rdata) or wishbone_rdata or (gpio_rdata or mtime_rdata or uart0_rdata or uart1_rdata or
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or cfs_rdata or nco_rdata or sysinfo_rdata);
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or cfs_rdata or nco_rdata or neoled_rdata or sysinfo_rdata);
 
-- processor bus: CPU transfer ACK input --
p_bus.ack <= (imem_ack or dmem_ack or bootrom_ack) or wishbone_ack or (gpio_ack or mtime_ack or uart0_ack or uart1_ack or
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or cfs_ack or nco_ack or sysinfo_ack);
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or cfs_ack or nco_ack or neoled_ack or sysinfo_ack);
 
-- processor bus: CPU transfer data bus error input --
p_bus.err <= wishbone_err;
764,7 → 776,9
if (IO_CFS_EN = true) generate
neorv32_cfs_inst: neorv32_cfs
generic map (
CFS_CONFIG => IO_CFS_CONFIG -- custom CFS configuration generic
CFS_CONFIG => IO_CFS_CONFIG, -- custom CFS configuration generic
CFS_IN_SIZE => IO_CFS_IN_SIZE, -- size of CFS input conduit in bits
CFS_OUT_SIZE => IO_CFS_OUT_SIZE -- size of CFS output conduit in bits
)
port map (
-- host access --
1145,6 → 1159,40
end generate;
 
 
-- Smart LED (WS2811/WS2812) Interface (NEOLED) -------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_neoled_inst_true:
if (IO_NEOLED_EN = true) generate
neorv32_neoled_inst: neorv32_neoled
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => p_bus.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
data_i => p_bus.wdata, -- data in
data_o => neoled_rdata, -- data out
ack_o => neoled_ack, -- transfer acknowledge
-- clock generator --
clkgen_en_o => neoled_cg_en, -- enable clock generator
clkgen_i => clk_gen,
-- interrupt --
irq_o => neoled_irq, -- interrupt request
-- NEOLED output --
neoled_o => neoled_o -- serial async data line
);
end generate;
 
neorv32_neoled_inst_false:
if (IO_NEOLED_EN = false) generate
neoled_rdata <= (others => '0');
neoled_ack <= '0';
neoled_cg_en <= '0';
neoled_irq <= '0';
neoled_o <= '0';
end generate;
 
 
-- System Configuration Information Memory (SYSINFO) --------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_sysinfo_inst: neorv32_sysinfo
1178,7 → 1226,8
IO_WDT_EN => IO_WDT_EN, -- implement watch dog timer (WDT)?
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)?
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)?
IO_NCO_EN => IO_NCO_EN -- implement numerically-controlled oscillator (NCO)?
IO_NCO_EN => IO_NCO_EN, -- implement numerically-controlled oscillator (NCO)?
IO_NEOLED_EN => IO_NEOLED_EN -- implement NeoPixel-compatible smart LED interface (NEOLED)?
)
port map (
-- host access --

powered by: WebSVN 2.1.0

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