mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-23 21:57:33 -04:00
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:
parent
338bde36d8
commit
227516009b
10 changed files with 316 additions and 335 deletions
|
@ -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
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 --
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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/-) */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue