misa CSR is read-only! mtval and mcause CSRs can now also be written by user; fixed error in bus unit - controller can now force bus unit reset and bus transaction termination

This commit is contained in:
stnolting 2020-07-09 14:21:13 +02:00
parent 338bde36d8
commit 227516009b
10 changed files with 316 additions and 335 deletions

View file

@ -88,20 +88,21 @@ entity neorv32_cpu is
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
-- bus interface --
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic; -- bus transfer error
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_cancel_o : out std_ulogic; -- cancel current bus transaction
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic; -- bus transfer error
-- external interrupts --
clic_irq_i : in std_ulogic; -- CLIC interrupt request
mtime_irq_i : in std_ulogic -- machine timer interrupt
clic_irq_i : in std_ulogic; -- CLIC interrupt request
mtime_irq_i : in std_ulogic -- machine timer interrupt
);
end neorv32_cpu;
@ -126,7 +127,6 @@ architecture neorv32_cpu_rtl of neorv32_cpu is
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 bus_exc_ack : std_ulogic; -- bus exception error acknowledge
signal bus_busy : std_ulogic; -- bus unit is busy
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)
@ -209,7 +209,6 @@ begin
be_instr_i => be_instr, -- bus error on instruction access
be_load_i => be_load, -- bus error on load data access
be_store_i => be_store, -- bus error on store data access
bus_exc_ack_o => bus_exc_ack, -- bus exception error acknowledge
bus_busy_i => bus_busy -- bus unit is busy
);
@ -238,6 +237,9 @@ begin
-- ALU ------------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_alu_inst: neorv32_cpu_alu
generic map (
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M -- implement muld/div extension?
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
@ -299,40 +301,41 @@ begin
-- -------------------------------------------------------------------------------------------
neorv32_cpu_bus_inst: neorv32_cpu_bus
generic map (
MEM_EXT_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
MEM_EXT_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout
)
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
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl, -- main control bus
-- data input --
wdata_i => rs2, -- write data
pc_i => fetch_pc, -- current PC for instruction fetch
alu_i => alu_res, -- ALU result
wdata_i => rs2, -- write data
pc_i => fetch_pc, -- current PC for instruction fetch
alu_i => alu_res, -- ALU result
-- data output --
instr_o => instr, -- instruction
rdata_o => rdata, -- read data
instr_o => instr, -- instruction
rdata_o => rdata, -- read data
-- status --
mar_o => mar, -- current memory address register
ma_instr_o => ma_instr, -- misaligned instruction address
ma_load_o => ma_load, -- misaligned load data address
ma_store_o => ma_store, -- misaligned store data address
be_instr_o => be_instr, -- bus error on instruction access
be_load_o => be_load, -- bus error on load data access
be_store_o => be_store, -- bus error on store data access
bus_wait_o => bus_wait, -- wait for bus operation to finish
bus_busy_o => bus_busy, -- bus unit is busy
exc_ack_i => bus_exc_ack, -- exception controller ACK
mar_o => mar, -- current memory address register
ma_instr_o => ma_instr, -- misaligned instruction address
ma_load_o => ma_load, -- misaligned load data address
ma_store_o => ma_store, -- misaligned store data address
be_instr_o => be_instr, -- bus error on instruction access
be_load_o => be_load, -- bus error on load data access
be_store_o => be_store, -- bus error on store data access
bus_wait_o => bus_wait, -- wait for bus operation to finish
bus_busy_o => bus_busy, -- bus unit is busy
-- bus system --
bus_addr_o => bus_addr_o, -- bus access address
bus_rdata_i => bus_rdata_i, -- bus read data
bus_wdata_o => bus_wdata_o, -- bus write data
bus_ben_o => bus_ben_o, -- byte enable
bus_we_o => bus_we_o, -- write enable
bus_re_o => bus_re_o, -- read enable
bus_ack_i => bus_ack_i, -- bus transfer acknowledge
bus_err_i => bus_err_i -- bus transfer error
bus_addr_o => bus_addr_o, -- bus access address
bus_rdata_i => bus_rdata_i, -- bus read data
bus_wdata_o => bus_wdata_o, -- bus write data
bus_ben_o => bus_ben_o, -- byte enable
bus_we_o => bus_we_o, -- write enable
bus_re_o => bus_re_o, -- read enable
bus_cancel_o => bus_cancel_o, -- cancel current bus transaction
bus_ack_i => bus_ack_i, -- bus transfer acknowledge
bus_err_i => bus_err_i -- bus transfer error
);

View file

@ -42,6 +42,9 @@ library neorv32;
use neorv32.neorv32_package.all;
entity neorv32_cpu_alu is
generic (
CPU_EXTENSION_RISCV_M : boolean := true -- implement muld/div extension?
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
@ -200,7 +203,7 @@ begin
cp_rb_ff0 <= '0';
cp_rb_ff1 <= '0';
elsif rising_edge(clk_i) then
if (ctrl_i(ctrl_sys_m_ext_en_c) = '1') then -- FIXME add second cp (floating point stuff?)
if (CPU_EXTENSION_RISCV_M = true) then -- FIXME add second cp (floating point stuff?)
cp_cmd_ff <= ctrl_i(ctrl_cp_use_c);
cp_rb_ff0 <= '0';
cp_rb_ff1 <= cp_rb_ff0;

View file

@ -43,40 +43,41 @@ use neorv32.neorv32_package.all;
entity neorv32_cpu_bus is
generic (
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
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
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
-- data input --
wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- write data
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- write data
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
-- data output --
instr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- instruction
rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- read data
instr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- instruction
rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- read data
-- status --
mar_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
ma_instr_o : out std_ulogic; -- misaligned instruction address
ma_load_o : out std_ulogic; -- misaligned load data address
ma_store_o : out std_ulogic; -- misaligned store data address
be_instr_o : out std_ulogic; -- bus error on instruction access
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data access
bus_wait_o : out std_ulogic; -- wait for bus operation to finish
bus_busy_o : out std_ulogic; -- bus unit is busy
exc_ack_i : in std_ulogic; -- exception controller ACK
mar_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
ma_instr_o : out std_ulogic; -- misaligned instruction address
ma_load_o : out std_ulogic; -- misaligned load data address
ma_store_o : out std_ulogic; -- misaligned store data address
be_instr_o : out std_ulogic; -- bus error on instruction access
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data access
bus_wait_o : out std_ulogic; -- wait for bus operation to finish
bus_busy_o : out std_ulogic; -- bus unit is busy
-- bus system --
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic -- bus transfer error
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_cancel_o : out std_ulogic; -- cancel current bus transaction
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic -- bus transfer error
);
end neorv32_cpu_bus;
@ -103,9 +104,7 @@ begin
-- -------------------------------------------------------------------------------------------
mem_adr_reg: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
mar <= (others => '0');
elsif rising_edge(clk_i) then
if rising_edge(clk_i) then
if (ctrl_i(ctrl_bus_mar_we_c) = '1') then
mar <= alu_i;
end if;
@ -113,14 +112,14 @@ begin
end process mem_adr_reg;
-- address output --
bus_addr_o <= pc_i when ((bus_if_req or ctrl_i(ctrl_bus_if_c)) = '1') else mar; -- is instruction fetch?
bus_addr_o <= pc_i when ((bus_if_req or ctrl_i(ctrl_bus_if_c)) = '1') else mar; -- is instruction fetch? keep output at PC as long as IF request is active
mar_o <= mar;
-- write request output --
bus_we_o <= ctrl_i(ctrl_bus_wr_c) and (not misaligned_data);
-- read request output (also used for instruction fetch) --
bus_re_o <= (ctrl_i(ctrl_bus_rd_c) and (not misaligned_data)) or ((bus_if_req or ctrl_i(ctrl_bus_if_c)) and (not misaligned_instr));
bus_re_o <= (ctrl_i(ctrl_bus_rd_c) and (not misaligned_data)) or (ctrl_i(ctrl_bus_if_c) and (not misaligned_instr)); -- FIXME i_reg and misaligned
-- Write Data -----------------------------------------------------------------------------
@ -223,7 +222,7 @@ begin
align_err <= '0';
bus_timeout <= (others => '0');
elsif rising_edge(clk_i) then
if (bus_busy = '0') then -- wait for new request
if (bus_busy = '0') or (ctrl_i(ctrl_bus_reset_c) = '1') then -- wait for new request or reset
bus_busy <= ctrl_i(ctrl_bus_if_c) or ctrl_i(ctrl_bus_rd_c) or ctrl_i(ctrl_bus_wr_c); -- any request at all?
bus_if_req <= ctrl_i(ctrl_bus_if_c); -- instruction fetch
bus_rd_req <= ctrl_i(ctrl_bus_rd_c); -- store access
@ -233,10 +232,10 @@ begin
align_err <= '0';
else -- bus transfer in progress
bus_timeout <= std_ulogic_vector(unsigned(bus_timeout) - 1);
align_err <= (align_err or misaligned_data or misaligned_instr) and (not exc_ack_i);
access_err <= (access_err or (not or_all_f(bus_timeout)) or bus_err_i) and (not exc_ack_i);
align_err <= (align_err or misaligned_data or misaligned_instr) and (not ctrl_i(ctrl_bus_exc_ack_c));
access_err <= (access_err or (not or_all_f(bus_timeout)) or bus_err_i) and (not ctrl_i(ctrl_bus_exc_ack_c));
if (align_err = '1') or (access_err = '1') then
if (exc_ack_i = '1') then -- wait for controller to ack exception
if (ctrl_i(ctrl_bus_exc_ack_c) = '1') then -- wait for controller to ack exception
bus_if_req <= '0';
bus_rd_req <= '0';
bus_wr_req <= '0';
@ -262,6 +261,9 @@ begin
ma_load_o <= bus_rd_req and align_err;
ma_store_o <= bus_wr_req and align_err;
-- terminate bus access --
bus_cancel_o <= (bus_busy and (align_err or access_err)) or ctrl_i(ctrl_bus_reset_c);
-- wait for bus --
bus_busy_o <= bus_busy;
bus_wait_o <= bus_busy and (not bus_ack_i); -- FIXME: 'async' ack
@ -291,10 +293,10 @@ begin
begin
-- check instruction access --
misaligned_instr <= '0'; -- default
if (ctrl_i(ctrl_sys_c_ext_en_c) = '1') then -- 16-bit and 32-bit instruction accesses
if (CPU_EXTENSION_RISCV_C = true) then -- 16-bit and 32-bit instruction accesses
misaligned_instr <= '0';
else -- 32-bit instruction accesses only
if (pc_i(1 downto 0) /= "00") then
if (pc_i(1) = '1') then -- PC(0) is always zero
misaligned_instr <= '1';
end if;
end if;

View file

@ -112,7 +112,6 @@ entity neorv32_cpu_control is
be_instr_i : in std_ulogic; -- bus error on instruction access
be_load_i : in std_ulogic; -- bus error on load data access
be_store_i : in std_ulogic; -- bus error on store data access
bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge
bus_busy_i : in std_ulogic -- bus unit is busy
);
end neorv32_cpu_control;
@ -140,6 +139,7 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
ci_return_nxt : std_ulogic;
reset : std_ulogic;
bus_err_ack : std_ulogic;
bus_reset : std_ulogic;
end record;
signal fetch_engine : fetch_engine_t;
@ -212,8 +212,6 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
-- fast bus access --
signal bus_fast_ir : std_ulogic;
signal bus_fast_rd : std_ulogic;
signal bus_fast_wr : std_ulogic;
-- RISC-V control and status registers (CSRs) --
type csr_t is record
@ -228,16 +226,14 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
mepc : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
mcause : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/-)
mcause : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/W)
mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-)
mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/W)
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
cycle : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-), plus carry bit
instret : std_ulogic_vector(32 downto 0); -- instret (R/-), plus carry bit
cycleh : std_ulogic_vector(31 downto 0); -- cycleh, mtimeh (R/-)
instreth : std_ulogic_vector(31 downto 0); -- instreth (R/-)
misa_c_en : std_ulogic; -- misa: C extension enable bit (R/W)
misa_m_en : std_ulogic; -- misa: M extension enable bit (R/W)
end record;
signal csr : csr_t;
@ -330,6 +326,7 @@ begin
fetch_engine.ci_reg_nxt <= fetch_engine.ci_reg;
fetch_engine.ci_return_nxt <= fetch_engine.ci_return;
fetch_engine.bus_err_ack <= '0';
fetch_engine.bus_reset <= '0';
-- instruction prefetch buffer interface --
ipb.we <= '0';
@ -344,8 +341,8 @@ begin
-- ------------------------------------------------------------
fetch_engine.i_buf_state_nxt <= (others => '0');
fetch_engine.ci_return_nxt <= '0';
fetch_engine.bus_reset <= '1'; -- reset bus unit
ipb.clear <= '1'; -- clear instruction prefetch buffer
fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them
fetch_engine.state_nxt <= IFETCH_0;
when IFETCH_0 => -- output current PC to bus system, request 32-bit word
@ -364,7 +361,7 @@ begin
fetch_engine.i_buf_state_nxt(1) <= fetch_engine.i_buf_state(0);
fetch_engine.state_nxt <= IFETCH_2;
end if;
fetch_engine.i_buf_state_nxt(0) <= '1';
if (be_instr_i = '1') or (ma_instr_i = '1') then -- any fetch exception?
fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them
@ -373,11 +370,11 @@ begin
when IFETCH_2 => -- construct instruction and issue
-- ------------------------------------------------------------
if (fetch_engine.i_buf_state(1) = '1') then
if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- 32-bit aligned
if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00);
ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- uncompressed
if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed
if (ipb.free = '1') then -- free entry in buffer?
ipb.we <= '1';
fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
@ -582,7 +579,7 @@ begin
-- CPU Control Bus Output -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_output: process(ctrl, execute_engine, csr, bus_fast_ir, bus_fast_rd, bus_fast_wr)
ctrl_output: process(ctrl, execute_engine, fetch_engine, trap_ctrl, csr, bus_fast_ir)
begin
ctrl_o <= ctrl;
-- direct output of register addresses --
@ -591,11 +588,9 @@ begin
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
-- bus access requests --
ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir;
ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) or bus_fast_rd;
ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) or bus_fast_wr;
-- cpu extension control --
ctrl_o(ctrl_sys_c_ext_en_c) <= csr.misa_c_en; -- C extension enabled
ctrl_o(ctrl_sys_m_ext_en_c) <= csr.misa_m_en; -- M extension enabled
-- bus control --
ctrl_o(ctrl_bus_exc_ack_c) <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack;
ctrl_o(ctrl_bus_reset_c) <=fetch_engine.bus_reset;
end process ctrl_output;
@ -623,10 +618,6 @@ begin
trap_ctrl.env_start_ack <= '0';
trap_ctrl.env_end <= '0';
-- bus access (fast) --
bus_fast_rd <= '0';
bus_fast_wr <= '0';
-- exception trigger --
trap_ctrl.instr_be <= '0';
trap_ctrl.instr_ma <= '0';
@ -712,12 +703,12 @@ begin
end if;
end if;
when TRAP => -- Start trap environment (also used as sleep state)
when TRAP => -- Start trap environment (also used as cpu sleep state)
-- ------------------------------------------------------------
fetch_engine.reset <= '1';
if (trap_ctrl.env_start = '1') then
trap_ctrl.env_start_ack <= '1';
execute_engine.pc_nxt <= csr.mtvec(data_width_c-1 downto 1) & '0';
fetch_engine.reset <= '1';
execute_engine.state_nxt <= SYS_WAIT;
end if;
@ -732,17 +723,22 @@ begin
ctrl_nxt(ctrl_alu_opc_mux_c) <= not alu_immediate_v;
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP
execute_engine.state_nxt <= ALU_WAIT;
elsif (alu_operation_v = alu_cmd_shift_c) then -- multi-cycle shift operation?
-- multi cycle alu operation? --
if (alu_operation_v = alu_cmd_shift_c) or -- shift operation
((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001")) then -- MULDIV?
execute_engine.state_nxt <= ALU_WAIT;
else
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.state_nxt <= DISPATCH;
end if;
-- cp access? --
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP
end if;
when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
-- ------------------------------------------------------------
@ -828,7 +824,7 @@ begin
execute_engine.pc_nxt <= csr.mepc(data_width_c-1 downto 1) & '0';
fetch_engine.reset <= '1';
execute_engine.state_nxt <= SYS_WAIT;
when x"105" => -- WFI
when x"105" => -- WFI = "CPU sleep"
execute_engine.state_nxt <= TRAP;
when others => -- undefined
NULL;
@ -913,12 +909,12 @@ begin
when LOAD => -- trigger memory read request
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_rd_c) <= '1';--bus_fast_rd <= '1'; -- fast read request
ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- fast read request
execute_engine.state_nxt <= LOADSTORE_0;
when STORE => -- trigger memory write request
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_wr_c) <= '1';--bus_fast_wr <= '1'; -- fast write request
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- fast write request
execute_engine.state_nxt <= LOADSTORE_0;
when LOADSTORE_0 => -- memory latency
@ -951,6 +947,8 @@ begin
-- -------------------------------------------------------------------------------------------
illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal)
begin
-- illegal instructions are checked in the EXECUTE stage
-- the execute engine will only commit valid instructions
if (execute_engine.state = EXECUTE) then
-- defaults --
illegal_instruction <= '0';
@ -1023,7 +1021,7 @@ begin
when opcode_alu_c => -- check ALU funct3 & funct7
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
if (CPU_EXTENSION_RISCV_M = false) or (csr.misa_m_en = '0') then -- not implemented or disabled
if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
illegal_instruction <= '1';
end if;
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
@ -1108,7 +1106,7 @@ begin
if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
illegal_instruction <= '1';
else -- compressed instruction: illegal or disabled / not implemented
illegal_compressed <= ci_illegal or (not csr.misa_c_en);
illegal_compressed <= ci_illegal;
end if;
end case;
@ -1184,12 +1182,6 @@ begin
trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked
trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled
-- exception acknowledge for bus unit --
bus_exc_ack_o <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack;
-- exception/interrupt/status ID visible for program --
csr.mcause <= trap_ctrl.cause;
-- Trap Priority Detector -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
@ -1309,45 +1301,64 @@ begin
csr.mtval <= (others => '0');
csr.mepc <= (others => '0');
csr.mip_msip <= '0';
csr.misa_c_en <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.misa_m_en <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
-- defaults --
csr.mip_msip <= '0';
-- register that can be modified by user --
if (csr.we = '1') then -- manual update
-- machine trap setup --
if (execute_engine.i_reg(31 downto 24) = x"30") then
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
csr.mstatus_mie <= csr_wdata_i(03);
csr.mstatus_mpie <= csr_wdata_i(07);
-- Machine CSRs: Standard read/write
if (execute_engine.i_reg(31 downto 28) = x"3") then
-- machine trap setup --
if (execute_engine.i_reg(27 downto 24) = x"0") then
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
csr.mstatus_mie <= csr_wdata_i(03);
csr.mstatus_mpie <= csr_wdata_i(07);
end if;
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
end if;
if (execute_engine.i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
csr.mtvec <= csr_wdata_i;
end if;
end if;
if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: misa - machine instruction set extensions
csr.misa_c_en <= csr_wdata_i(02); -- C extension enable/disable during runtime
csr.misa_m_en <= csr_wdata_i(12); -- M extension enable/disable during runtime
end if;
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
end if;
if (execute_engine.i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
csr.mtvec <= csr_wdata_i;
end if;
end if;
-- machine trap handling --
if (execute_engine.i_reg(31 downto 24) = x"34") then
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register
csr.mscratch <= csr_wdata_i;
end if;
if (execute_engine.i_reg(23 downto 20) = x"1") then-- R/W: mepc - machine exception program counter
csr.mepc <= csr_wdata_i;
end if;
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending
csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
-- machine trap handling --
if (execute_engine.i_reg(27 downto 24) = x"4") then
case execute_engine.i_reg(23 downto 20) is
when x"0" => -- R/W: mscratch - machine scratch register
csr.mscratch <= csr_wdata_i;
when x"1" => -- R/W: mepc - machine exception program counter
csr.mepc <= csr_wdata_i;
when x"2" => -- R/W: mcause - machine trap cause
csr.mcause <= csr_wdata_i;
when x"3" => -- R/W: mtval - machine bad address or instruction
csr.mtval <= csr_wdata_i;
when x"4" => -- R/W: mip - machine interrupt pending
csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
when others =>
NULL;
end case;
-- FIXME remove code below
--if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register
-- csr.mscratch <= csr_wdata_i;
--end if;
--if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: mepc - machine exception program counter
-- csr.mepc <= csr_wdata_i;
--end if;
--if (execute_engine.i_reg(23 downto 20) = x"2") then -- R/W: mcause - machine trap cause
-- csr.mcause <= csr_wdata_i;
--end if;
--if (execute_engine.i_reg(23 downto 20) = x"3") then -- R/W: mtval - machine bad address or instruction
-- csr.mtval <= csr_wdata_i;
--end if;
--if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending
-- csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
--end if;
end if;
end if;
@ -1355,9 +1366,10 @@ begin
-- machine exception PC & exception value register --
if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only (mtval not defined for interrupts)
csr.mcause <= trap_ctrl.cause;
if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
csr.mtval <= (others => '0');
csr.mtval <= (others => '0'); -- mtval not defined for interrupts
else -- for EXCEPTIONS (according to their priority)
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
@ -1402,10 +1414,10 @@ begin
csr_rdata_o(11) <= '1'; -- MPP low
csr_rdata_o(12) <= '1'; -- MPP high
when x"301" => -- R/W: misa - ISA and extensions
csr_rdata_o(02) <= csr.misa_c_en; -- C CPU extension
csr_rdata_o(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
csr_rdata_o(12) <= csr.misa_m_en; -- M CPU extension
csr_rdata_o(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Z CPU extension
csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo)
csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi)
@ -1420,9 +1432,9 @@ begin
csr_rdata_o <= csr.mscratch;
when x"341" => -- R/W: mepc - machine exception program counter
csr_rdata_o <= csr.mepc;
when x"342" => -- R/-: mcause - machine trap cause
when x"342" => -- R/W: mcause - machine trap cause
csr_rdata_o <= csr.mcause;
when x"343" => -- R/-: mtval - machine bad address or instruction
when x"343" => -- R/W: mtval - machine bad address or instruction
csr_rdata_o <= csr.mtval;
when x"344" => -- R/W: mip - machine interrupt pending
csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
@ -1473,7 +1485,7 @@ begin
csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_DSPACE_SIZE, 32));
-- undefined/unavailable --
when others =>
csr_rdata_o <= (others => '0'); -- not implemented (yet)
csr_rdata_o <= (others => '0'); -- not implemented
end case;
end if;
end if;

View file

@ -41,7 +41,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- data width - FIXED!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01000100"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01000500"; -- no touchy!
-- Internal Functions ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
@ -178,16 +178,15 @@ package neorv32_package is
constant ctrl_bus_mdo_we_c : natural := 37; -- memory data out register write enable
constant ctrl_bus_mdi_we_c : natural := 38; -- memory data in register write enable
constant ctrl_bus_unsigned_c : natural := 39; -- is unsigned load
constant ctrl_bus_exc_ack_c : natural := 40; -- acknowledge bus exception
constant ctrl_bus_reset_c : natural := 41; -- reset bus unit, terminate all actions
-- co-processor --
constant ctrl_cp_use_c : natural := 40; -- is cp operation
constant ctrl_cp_id_lsb_c : natural := 41; -- cp select lsb
constant ctrl_cp_id_msb_c : natural := 42; -- cp select msb
constant ctrl_cp_cmd0_c : natural := 43; -- cp command bit 0
constant ctrl_cp_cmd1_c : natural := 44; -- cp command bit 1
constant ctrl_cp_cmd2_c : natural := 45; -- cp command bit 2
-- system --
constant ctrl_sys_c_ext_en_c : natural := 46; -- CPU C extension enabled
constant ctrl_sys_m_ext_en_c : natural := 47; -- CPU M extension enabled
constant ctrl_cp_use_c : natural := 42; -- is cp operation
constant ctrl_cp_id_lsb_c : natural := 43; -- cp select lsb
constant ctrl_cp_id_msb_c : natural := 44; -- cp select msb
constant ctrl_cp_cmd0_c : natural := 45; -- cp command bit 0
constant ctrl_cp_cmd1_c : natural := 46; -- cp command bit 1
constant ctrl_cp_cmd2_c : natural := 47; -- cp command bit 2
-- control bus size --
constant ctrl_width_c : natural := 48; -- control bus size
@ -453,20 +452,21 @@ package neorv32_package is
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
-- bus interface --
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic; -- bus transfer error
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_cancel_o : out std_ulogic; -- cancel current bus transaction
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic; -- bus transfer error
-- external interrupts --
clic_irq_i : in std_ulogic; -- CLIC interrupt request
mtime_irq_i : in std_ulogic -- machine timer interrupt
clic_irq_i : in std_ulogic; -- CLIC interrupt request
mtime_irq_i : in std_ulogic -- machine timer interrupt
);
end component;
@ -541,7 +541,6 @@ package neorv32_package is
be_instr_i : in std_ulogic; -- bus error on instruction access
be_load_i : in std_ulogic; -- bus error on load data access
be_store_i : in std_ulogic; -- bus error on store data access
bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge
bus_busy_i : in std_ulogic -- bus unit is busy
);
end component;
@ -570,6 +569,9 @@ package neorv32_package is
-- Component: CPU ALU ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_alu
generic (
CPU_EXTENSION_RISCV_M : boolean := true -- implement muld/div extension?
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
@ -616,40 +618,41 @@ package neorv32_package is
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_bus
generic (
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
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
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
-- data input --
wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- write data
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- write data
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
-- data output --
instr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- instruction
rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- read data
instr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- instruction
rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- read data
-- status --
mar_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
ma_instr_o : out std_ulogic; -- misaligned instruction address
ma_load_o : out std_ulogic; -- misaligned load data address
ma_store_o : out std_ulogic; -- misaligned store data address
be_instr_o : out std_ulogic; -- bus error on instruction access
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data
bus_wait_o : out std_ulogic; -- wait for bus operation to finish
bus_busy_o : out std_ulogic; -- bus unit is busy
exc_ack_i : in std_ulogic; -- exception controller ACK
mar_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
ma_instr_o : out std_ulogic; -- misaligned instruction address
ma_load_o : out std_ulogic; -- misaligned load data address
ma_store_o : out std_ulogic; -- misaligned store data address
be_instr_o : out std_ulogic; -- bus error on instruction access
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data
bus_wait_o : out std_ulogic; -- wait for bus operation to finish
bus_busy_o : out std_ulogic; -- bus unit is busy
-- bus system --
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic -- bus transfer error
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_cancel_o : out std_ulogic; -- cancel current bus transaction
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic -- bus transfer error
);
end component;
@ -940,6 +943,7 @@ package neorv32_package is
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
cancel_i : in std_ulogic; -- cancel current bus transaction
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
-- wishbone interface --

View file

@ -52,9 +52,9 @@ entity neorv32_top is
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := true; -- implement muld/div extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Memory configuration: Instruction memory --
@ -142,14 +142,18 @@ architecture neorv32_top_rtl of neorv32_top is
signal pwm_cg_en : std_ulogic;
-- cpu bus --
signal cpu_addr : std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
signal cpu_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
signal cpu_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
signal cpu_ben : std_ulogic_vector(03 downto 0); -- byte enable
signal cpu_we : std_ulogic; -- write enable
signal cpu_re : std_ulogic; -- read enable
signal cpu_ack : std_ulogic; -- bus transfer acknowledge
signal cpu_err : std_ulogic; -- bus transfer error
type cpu_bus_t is record
addr : std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
wdata : std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
ben : std_ulogic_vector(03 downto 0); -- byte enable
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
cancel : std_ulogic; -- cancel current transfer
ack : std_ulogic; -- bus transfer acknowledge
err : std_ulogic; -- bus transfer error
end record;
signal cpu : cpu_bus_t;
-- io space access --
signal io_acc : std_ulogic;
@ -352,32 +356,33 @@ begin
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => sys_rstn, -- global reset, low-active, async
clk_i => clk_i, -- global clock, rising edge
rstn_i => sys_rstn, -- global reset, low-active, async
-- bus interface --
bus_addr_o => cpu_addr, -- bus access address
bus_rdata_i => cpu_rdata, -- bus read data
bus_wdata_o => cpu_wdata, -- bus write data
bus_ben_o => cpu_ben, -- byte enable
bus_we_o => cpu_we, -- write enable
bus_re_o => cpu_re, -- read enable
bus_ack_i => cpu_ack, -- bus transfer acknowledge
bus_err_i => cpu_err, -- bus transfer error
bus_addr_o => cpu.addr, -- bus access address
bus_rdata_i => cpu.rdata, -- bus read data
bus_wdata_o => cpu.wdata, -- bus write data
bus_ben_o => cpu.ben, -- byte enable
bus_we_o => cpu.we, -- write enable
bus_re_o => cpu.re, -- read enable
bus_cancel_o => cpu.cancel, -- cancel current bus transaction
bus_ack_i => cpu.ack, -- bus transfer acknowledge
bus_err_i => cpu.err, -- bus transfer error
-- external interrupts --
clic_irq_i => clic_irq, -- CLIC interrupt request
mtime_irq_i => mtime_irq -- machine timer interrupt
clic_irq_i => clic_irq, -- CLIC interrupt request
mtime_irq_i => mtime_irq -- machine timer interrupt
);
-- CPU data input --
cpu_rdata <= (imem_rdata or dmem_rdata or bootrom_rdata) or wishbone_rdata or (gpio_rdata or mtime_rdata or
cpu.rdata <= (imem_rdata or dmem_rdata or bootrom_rdata) or wishbone_rdata or (gpio_rdata or mtime_rdata or
uart_rdata or spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or clic_rdata or trng_rdata or devnull_rdata);
-- CPU ACK input --
cpu_ack <= (imem_ack or dmem_ack or bootrom_ack) or wishbone_ack or (gpio_ack or mtime_ack or
cpu.ack <= (imem_ack or dmem_ack or bootrom_ack) or wishbone_ack or (gpio_ack or mtime_ack or
uart_ack or spi_ack or twi_ack or pwm_ack or wdt_ack or clic_ack or trng_ack or devnull_ack);
-- CPU bus error input --
cpu_err <= wishbone_err;
cpu.err <= wishbone_err;
-- Processor-Internal Instruction Memory (IMEM) -------------------------------------------
@ -393,12 +398,12 @@ begin
)
port map (
clk_i => clk_i, -- global clock line
rden_i => cpu_re, -- read enable
wren_i => cpu_we, -- write enable
ben_i => cpu_ben, -- byte write enable
rden_i => cpu.re, -- read enable
wren_i => cpu.we, -- write enable
ben_i => cpu.ben, -- byte write enable
upen_i => '1', -- update enable
addr_i => cpu_addr, -- address
data_i => cpu_wdata, -- data in
addr_i => cpu.addr, -- address
data_i => cpu.wdata, -- data in
data_o => imem_rdata, -- data out
ack_o => imem_ack -- transfer acknowledge
);
@ -422,11 +427,11 @@ begin
)
port map (
clk_i => clk_i, -- global clock line
rden_i => cpu_re, -- read enable
wren_i => cpu_we, -- write enable
ben_i => cpu_ben, -- byte write enable
addr_i => cpu_addr, -- address
data_i => cpu_wdata, -- data in
rden_i => cpu.re, -- read enable
wren_i => cpu.we, -- write enable
ben_i => cpu.ben, -- byte write enable
addr_i => cpu.addr, -- address
data_i => cpu.wdata, -- data in
data_o => dmem_rdata, -- data out
ack_o => dmem_ack -- transfer acknowledge
);
@ -446,8 +451,8 @@ begin
neorv32_boot_rom_inst: neorv32_boot_rom
port map (
clk_i => clk_i, -- global clock line
rden_i => cpu_re, -- read enable
addr_i => cpu_addr, -- address
rden_i => cpu.re, -- read enable
addr_i => cpu.addr, -- address
data_o => bootrom_rdata, -- data out
ack_o => bootrom_ack -- transfer acknowledge
);
@ -483,12 +488,13 @@ begin
clk_i => clk_i, -- global clock line
rstn_i => sys_rstn, -- global reset line, low-active
-- host access --
addr_i => cpu_addr, -- address
rden_i => cpu_re, -- read enable
wren_i => cpu_we, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
addr_i => cpu.addr, -- address
rden_i => cpu.re, -- read enable
wren_i => cpu.we, -- write enable
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => wishbone_rdata, -- data out
cancel_i => cpu.cancel, -- cancel current transaction
ack_o => wishbone_ack, -- transfer acknowledge
err_o => wishbone_err, -- transfer error
-- wishbone interface --
@ -521,9 +527,9 @@ begin
-- IO Access? -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
io_acc <= '1' when (cpu_addr(data_width_c-1 downto index_size_f(io_size_c)) = io_base_c(data_width_c-1 downto index_size_f(io_size_c))) else '0';
io_rden <= io_acc and cpu_re;
io_wren <= io_acc and cpu_we;
io_acc <= '1' when (cpu.addr(data_width_c-1 downto index_size_f(io_size_c)) = io_base_c(data_width_c-1 downto index_size_f(io_size_c))) else '0';
io_rden <= io_acc and cpu.re;
io_wren <= io_acc and cpu.we;
-- General Purpose Input/Output Port (GPIO) -----------------------------------------------
@ -534,11 +540,11 @@ begin
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => gpio_rdata, -- data out
ack_o => gpio_ack, -- transfer acknowledge
-- parallel io --
@ -568,9 +574,9 @@ begin
clk_i => clk_i, -- global clock line
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
addr_i => cpu_addr, -- address
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
addr_i => cpu.addr, -- address
data_i => cpu.wdata, -- data in
data_o => clic_rdata, -- data out
ack_o => clic_ack, -- transfer acknowledge
-- cpu interrupt --
@ -615,9 +621,9 @@ begin
rstn_i => ext_rstn, -- global reset line, low-active
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
addr_i => cpu_addr, -- address
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
addr_i => cpu.addr, -- address
data_i => cpu.wdata, -- data in
data_o => wdt_rdata, -- data out
ack_o => wdt_ack, -- transfer acknowledge
-- clock generator --
@ -648,11 +654,11 @@ begin
-- host access --
clk_i => clk_i, -- global clock line
rstn_i => sys_rstn, -- global reset, low-active, async
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => mtime_rdata, -- data out
ack_o => mtime_ack, -- transfer acknowledge
-- interrupt --
@ -676,11 +682,11 @@ begin
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => uart_rdata, -- data out
ack_o => uart_ack, -- transfer acknowledge
-- clock generator --
@ -712,11 +718,11 @@ begin
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => spi_rdata, -- data out
ack_o => spi_ack, -- transfer acknowledge
-- clock generator --
@ -752,11 +758,11 @@ begin
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => twi_rdata, -- data out
ack_o => twi_ack, -- transfer acknowledge
-- clock generator --
@ -789,11 +795,11 @@ begin
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => pwm_rdata, -- data out
ack_o => pwm_ack, -- transfer acknowledge
-- clock generator --
@ -821,11 +827,11 @@ begin
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => trng_rdata, -- data out
ack_o => trng_ack -- transfer acknowledge
);
@ -846,11 +852,11 @@ begin
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
addr_i => cpu.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
ben_i => cpu.ben, -- byte write enable
data_i => cpu.wdata, -- data in
data_o => devnull_rdata, -- data out
ack_o => devnull_ack -- transfer acknowledge
);

View file

@ -244,7 +244,7 @@ int main() {
#endif
}
else {
neorv32_uart_printf("skipped (no EXC I_ALIGN possible in C-mode)\n");
neorv32_uart_printf("skipped (not possible when C-EXT enabled)\n");
}

View file

@ -129,10 +129,10 @@ enum NEORV32_CPU_MIP_enum {
* CPU <b>misa</b> CSR (r/w): Machine instruction set extensions (RISC-V spec.)
**************************************************************************/
enum NEORV32_CPU_MISA_enum {
CPU_MISA_C_EXT = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/w), can be switched on/off */
CPU_MISA_C_EXT = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/-), can be switched on/off */
CPU_MISA_E_EXT = 4, /**< CPU misa CSR (3): E: Embedded CPU extension available (r/-) */
CPU_MISA_I_EXT = 8, /**< CPU misa CSR (8): I: Base integer ISA CPU extension available (r/-) */
CPU_MISA_M_EXT = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/w), can be switched on/off */
CPU_MISA_M_EXT = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/-), can be switched on/off */
CPU_MISA_X_EXT = 23, /**< CPU misa CSR (23): X: Non-standard CPU extension available (r/-) */
CPU_MISA_Z_EXT = 25, /**< CPU misa CSR (25): Z: Privileged architecture CPU extension(s) available (r/-) */
CPU_MISA_MXL_LO_EXT = 30, /**< CPU misa CSR (30): MXL.lo: CPU data width (r/-) */

View file

@ -43,7 +43,6 @@
#define neorv32_cpu_h
// prototypes
int neorv32_cpu_switch_extension(int sel, int state);
int neorv32_cpu_irq_enable(uint8_t irq_sel);
int neorv32_cpu_irq_disable(uint8_t irq_sel);
void neorv32_cpu_delay_ms(uint32_t time_ms);

View file

@ -43,54 +43,6 @@
#include "neorv32_cpu.h"
/**********************************************************************//**
* Enable/disable CPU extension during runtime via the 'misa' CSR.
*
* @warning This is still highly experimental! This function requires the Zicsr + Zifencei CPU extensions.
*
* @param[in] sel Bit to be set in misa CSR / extension to be enabled. See #NEORV32_CPU_MISA_enum.
* @param[in] state Set 1 to enable the selected extension, set 0 to disable it;
* return 0 if success, 1 if error (invalid sel or extension cannot be enabled).
**************************************************************************/
int neorv32_cpu_switch_extension(int sel, int state) {
// get current misa setting
uint32_t misa_curr = neorv32_cpu_csr_read(CSR_MISA);
uint32_t misa_prev = misa_curr;
// abort if misa.z is cleared
if ((misa_curr & (1 << CPU_MISA_Z_EXT)) == 0) {
return 1;
}
// out of range?
if (sel > 25) {
return 1;
}
// enable/disable selected extension
if (state & 1) {
misa_curr |= (1 << sel);
}
else {
misa_curr &= ~(1 << sel);
}
// try updating misa
neorv32_cpu_csr_write(CSR_MISA, misa_curr);
asm volatile("fence.i"); // required to flush prefetch buffers
asm volatile("nop");
// dit it work?
if (neorv32_cpu_csr_read(CSR_MISA) == misa_prev) {
return 1; // nope
}
else {
return 0; // fine
}
}
/**********************************************************************//**
* Enable specific CPU interrupt.
*