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

Subversion Repositories neorv32

Compare Revisions

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

Rev 30 → Rev 31

/neorv32_cpu.vhd
329,7 → 329,7
ma_instr_o => ma_instr, -- misaligned instruction address
be_instr_o => be_instr, -- bus error on instruction access
-- cpu data access interface --
addr_i => alu_res, -- ALU result -> access address
addr_i => alu_res, -- ALU result -> access address
wdata_i => rs2, -- write data
rdata_o => rdata, -- read data
mar_o => mar, -- current memory address register
/neorv32_cpu_bus.vhd
340,7 → 340,7
be_instr_o <= i_arbiter.err_bus;
 
-- instruction bus (read-only) --
i_bus_addr_o <= fetch_pc_i;
i_bus_addr_o <= fetch_pc_i(data_width_c-1 downto 2) & "00"; -- instruction access is always 4-byte aligned (even for compressed instructions)
i_bus_wdata_o <= (others => '0');
i_bus_ben_o <= (others => '0');
i_bus_we_o <= '0';
/neorv32_cpu_control.vhd
1,9 → 1,10
-- #################################################################################################
-- # << NEORV32 - CPU Control >> #
-- # ********************************************************************************************* #
-- # CPU operation is split into a fetch engine (responsible for fetching an decompressing instr- #
-- # uctions), an execute engine (responsible for actually executing the instructions), an inter- #
-- # rupt and exception handling controller and the RISC-V status and control registers (CSRs). #
-- # CPU operation is split into a fetch engine (responsible for fetching instruction data), an #
-- # issue engine (for recoding compressed instructions and for constructing 32-bit instruction #
-- # words) and an execute engine (responsible for actually executing the instructions), a trap #
-- # handling controller and the RISC-V status and control register set (CSRs). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
105,49 → 106,68
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
 
-- instruction fetch enginge --
type fetch_engine_state_t is (IFETCH_RESET, IFETCH_0, IFETCH_1, IFETCH_2);
type fetch_engine_state_t is (IFETCH_RESET, IFETCH_REQUEST, IFETCH_ISSUE);
type fetch_engine_t is record
state : fetch_engine_state_t;
state_nxt : fetch_engine_state_t;
i_buf : std_ulogic_vector(33 downto 0);
i_buf_nxt : std_ulogic_vector(33 downto 0);
i_buf2 : std_ulogic_vector(33 downto 0);
i_buf2_nxt : std_ulogic_vector(33 downto 0);
ci_input : std_ulogic_vector(15 downto 0); -- input to compressed instr. decoder
i_buf_state : std_ulogic_vector(01 downto 0);
i_buf_state_nxt : std_ulogic_vector(01 downto 0);
pc : std_ulogic_vector(data_width_c-1 downto 0);
pc_add : std_ulogic_vector(data_width_c-1 downto 0);
reset : std_ulogic;
bus_err_ack : std_ulogic;
state : fetch_engine_state_t;
state_nxt : fetch_engine_state_t;
pc : std_ulogic_vector(data_width_c-1 downto 0);
pc_nxt : std_ulogic_vector(data_width_c-1 downto 0);
reset : std_ulogic;
bus_err_ack : std_ulogic;
end record;
signal fetch_engine : fetch_engine_t;
 
-- pre-decoder --
signal ci_instr32 : std_ulogic_vector(31 downto 0);
signal ci_illegal : std_ulogic;
 
-- instrucion prefetch buffer (IPB) --
type ipb_dbuf_t is array (0 to ipb_entries_c-1) of std_ulogic_vector(35 downto 0);
type ipb_data_fifo_t is array (0 to ipb_entries_c-1) of std_ulogic_vector(2+31 downto 0);
type ipb_t is record
wdata : std_ulogic_vector(35 downto 0); -- data (+ status) to be written
we : std_ulogic; -- trigger write
free : std_ulogic; -- free entry available?
wdata : std_ulogic_vector(2+31 downto 0); -- write status (bus_error, align_error) + 32-bit instruction data
we : std_ulogic; -- trigger write
free : std_ulogic; -- free entry available?
clear : std_ulogic; -- clear all entries
--
rdata : std_ulogic_vector(35 downto 0); -- read data (+ status)
re : std_ulogic; -- trigger read
avail : std_ulogic; -- data available?
rdata : std_ulogic_vector(2+31 downto 0); -- read data: status (bus_error, align_error) + 32-bit instruction data
re : std_ulogic; -- read enable
avail : std_ulogic; -- data available?
--
clear : std_ulogic; -- clear all entries
w_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- write pointer
r_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- read pointer
empty : std_ulogic;
full : std_ulogic;
--
data : ipb_dbuf_t; -- the data fifo
w_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- write pointer
r_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- read pointer
empty : std_ulogic;
full : std_ulogic;
data : ipb_data_fifo_t; -- fifo memory
end record;
signal ipb : ipb_t;
 
-- pre-decoder --
signal ci_instr16 : std_ulogic_vector(15 downto 0);
signal ci_instr32 : std_ulogic_vector(31 downto 0);
signal ci_illegal : std_ulogic;
 
-- instruction issue enginge --
type issue_engine_state_t is (ISSUE_ACTIVE, ISSUE_REALIGN);
type issue_engine_t is record
state : issue_engine_state_t;
state_nxt : issue_engine_state_t;
align : std_ulogic;
align_nxt : std_ulogic;
buf : std_ulogic_vector(2+15 downto 0);
buf_nxt : std_ulogic_vector(2+15 downto 0);
end record;
signal issue_engine : issue_engine_t;
 
-- instruction buffer --
type i_buf_t is record
wdata : std_ulogic_vector(35 downto 0); -- 4-bit status + 32-bit instruction
rdata : std_ulogic_vector(35 downto 0); -- 4-bit status + 32-bit instruction
status : std_ulogic;
clear : std_ulogic;
we : std_ulogic;
re : std_ulogic;
free : std_ulogic;
avail : std_ulogic;
end record;
signal i_buf : i_buf_t;
 
-- instruction execution engine --
type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, CSR_ACCESS);
type execute_engine_t is record
257,16 → 277,16
begin
 
-- ****************************************************************************************************************************
-- Instruction Fetch
-- Instruction Fetch (always fetches aligned 32-bit chunks of data)
-- ****************************************************************************************************************************
 
-- Fetch Engine FSM Sync ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- registers that require a specific reset state --
fetch_engine_fsm_sync_rst: process(rstn_i, clk_i)
fetch_engine_fsm_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
fetch_engine.state <= IFETCH_RESET;
fetch_engine.pc <= (others => '0');
elsif rising_edge(clk_i) then
if (fetch_engine.reset = '1') then
fetch_engine.state <= IFETCH_RESET;
273,114 → 293,55
else
fetch_engine.state <= fetch_engine.state_nxt;
end if;
fetch_engine.pc <= fetch_engine.pc_nxt;
end if;
end process fetch_engine_fsm_sync_rst;
 
 
-- registers that DO NOT require a specific reset state --
fetch_engine_fsm_sync: process(clk_i)
begin
if rising_edge(clk_i) then
if (fetch_engine.state = IFETCH_RESET) then
fetch_engine.pc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
else
fetch_engine.pc <= std_ulogic_vector(unsigned(fetch_engine.pc(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_add(data_width_c-1 downto 1) & '0'));
end if;
--
fetch_engine.i_buf <= fetch_engine.i_buf_nxt;
fetch_engine.i_buf2 <= fetch_engine.i_buf2_nxt;
fetch_engine.i_buf_state <= fetch_engine.i_buf_state_nxt;
end if;
end process fetch_engine_fsm_sync;
 
-- PC output --
fetch_pc_o <= fetch_engine.pc(data_width_c-1 downto 1) & '0';
fetch_pc_o <= fetch_engine.pc(data_width_c-1 downto 1) & '0'; -- half-word aligned
 
 
-- Fetch Engine FSM Comb ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fetch_engine_fsm_comb: process(fetch_engine, csr, ipb, instr_i, bus_i_wait_i, ci_instr32, ci_illegal, be_instr_i, ma_instr_i)
fetch_engine_fsm_comb: process(fetch_engine, execute_engine, ipb, instr_i, bus_i_wait_i, be_instr_i, ma_instr_i)
begin
-- arbiter defaults --
bus_fast_ir <= '0';
fetch_engine.state_nxt <= fetch_engine.state;
fetch_engine.pc_add <= (others => '0');
fetch_engine.i_buf_nxt <= fetch_engine.i_buf;
fetch_engine.i_buf2_nxt <= fetch_engine.i_buf2;
fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state;
fetch_engine.ci_input <= fetch_engine.i_buf2(15 downto 00);
fetch_engine.bus_err_ack <= '0';
bus_fast_ir <= '0';
fetch_engine.state_nxt <= fetch_engine.state;
fetch_engine.pc_nxt <= fetch_engine.pc;
fetch_engine.bus_err_ack <= '0';
 
-- instruction prefetch buffer interface --
ipb.we <= '0';
ipb.wdata <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store exception info and instruction word
ipb.clear <= '0';
ipb.wdata <= (others => '0');
 
-- state machine --
case fetch_engine.state is
 
when IFETCH_RESET => -- reset engine, prefetch buffer, get appilcation PC
when IFETCH_RESET => -- reset engine and prefetch buffer, get appilcation PC
-- ------------------------------------------------------------
fetch_engine.i_buf_state_nxt <= (others => '0');
ipb.clear <= '1'; -- clear instruction prefetch buffer
fetch_engine.state_nxt <= IFETCH_0;
fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
fetch_engine.pc_nxt <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
ipb.clear <= '1'; -- clear prefetch buffer
fetch_engine.state_nxt <= IFETCH_REQUEST;
 
when IFETCH_0 => -- output current PC to bus system, request 32-bit word
when IFETCH_REQUEST => -- output current PC to bus system and request 32-bit (aligned!) instruction data
-- ------------------------------------------------------------
bus_fast_ir <= '1'; -- fast instruction fetch request
fetch_engine.state_nxt <= IFETCH_1;
if (ipb.free = '1') then -- free entry in buffer?
bus_fast_ir <= '1'; -- fast instruction fetch request
fetch_engine.state_nxt <= IFETCH_ISSUE;
end if;
 
when IFETCH_1 => -- store data from memory to buffer(s)
when IFETCH_ISSUE => -- store instruction data to prefetch buffer
-- ------------------------------------------------------------
if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
fetch_engine.i_buf_nxt <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store data word and exception info
fetch_engine.i_buf2_nxt <= fetch_engine.i_buf;
fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state(0) & '1';
if (fetch_engine.i_buf_state(0) = '1') then -- buffer filled?
fetch_engine.state_nxt <= IFETCH_2;
else
fetch_engine.pc_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.state_nxt <= IFETCH_0; -- get another instruction word
end if;
fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
fetch_engine.pc_nxt <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
ipb.we <= '1';
fetch_engine.state_nxt <= IFETCH_REQUEST;
end if;
 
when IFETCH_2 => -- construct instruction word and issue
-- ------------------------------------------------------------
fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
if (fetch_engine.pc(1) = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
fetch_engine.ci_input <= fetch_engine.i_buf2(15 downto 00);
 
if (ipb.free = '1') then -- free entry in buffer?
ipb.we <= '1';
if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed
ipb.wdata <= '0' & fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
fetch_engine.pc_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.state_nxt <= IFETCH_0;
else -- compressed
ipb.wdata <= ci_illegal & fetch_engine.i_buf2(33 downto 32) & '1' & ci_instr32;
fetch_engine.pc_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
fetch_engine.state_nxt <= IFETCH_2; -- try to get another 16-bit instruction word in next round
end if;
end if;
 
else -- 16-bit aligned
fetch_engine.ci_input <= fetch_engine.i_buf2(31 downto 16);
 
if (ipb.free = '1') then -- free entry in buffer?
ipb.we <= '1';
if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed and "unaligned"
ipb.wdata <= '0' & fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
fetch_engine.pc_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.state_nxt <= IFETCH_0;
else -- compressed
ipb.wdata <= ci_illegal & fetch_engine.i_buf(33 downto 32) & '1' & ci_instr32;
fetch_engine.pc_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
fetch_engine.state_nxt <= IFETCH_0;
end if;
end if;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
fetch_engine.state_nxt <= IFETCH_RESET;
389,27 → 350,6
end process fetch_engine_fsm_comb;
 
 
-- Compressed Instructions Recoding -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_decompressor_inst_true:
if (CPU_EXTENSION_RISCV_C = true) generate
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
port map (
-- instruction input --
ci_instr16_i => fetch_engine.ci_input, -- compressed instruction input
-- instruction output --
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction
);
end generate;
 
neorv32_cpu_decompressor_inst_false:
if (CPU_EXTENSION_RISCV_C = false) generate
ci_instr32 <= (others => '0');
ci_illegal <= '0';
end generate;
 
 
-- ****************************************************************************************************************************
-- Instruction Prefetch Buffer
-- ****************************************************************************************************************************
429,7 → 369,7
elsif (ipb.we = '1') then
ipb.w_pnt <= std_ulogic_vector(unsigned(ipb.w_pnt) + 1);
end if;
-- read port --
-- read ports --
if (ipb.clear = '1') then
ipb.r_pnt <= (others => '0');
elsif (ipb.re = '1') then
448,17 → 388,182
end process instr_prefetch_buffer_data;
 
-- async read --
ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.w_pnt'left-1 downto 0))));
ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0))));
 
-- status --
ipb.full <= '1' when (ipb.r_pnt(ipb.r_pnt'left) /= ipb.w_pnt(ipb.w_pnt'left)) and (ipb.r_pnt(ipb.r_pnt'left-1 downto 0) = ipb.w_pnt(ipb.w_pnt'left-1 downto 0)) else '0';
ipb.empty <= '1' when (ipb.r_pnt(ipb.r_pnt'left) = ipb.w_pnt(ipb.w_pnt'left)) and (ipb.r_pnt(ipb.r_pnt'left-1 downto 0) = ipb.w_pnt(ipb.w_pnt'left-1 downto 0)) else '0';
 
ipb.free <= not ipb.full;
ipb.avail <= not ipb.empty;
 
 
-- ****************************************************************************************************************************
-- Instruction Issue (recoding of compressed instructions and 32-bit instruction word construction)
-- ****************************************************************************************************************************
 
 
-- Issue Engine FSM Sync ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
issue_engine_fsm_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
issue_engine.state <= ISSUE_ACTIVE;
issue_engine.align <= CPU_BOOT_ADDR(1);
issue_engine.buf <= (others => '0');
elsif rising_edge(clk_i) then
if (ipb.clear = '1') then
if (CPU_EXTENSION_RISCV_C = true) then
if (execute_engine.pc(1) = '1') then -- branch to unaligned address?
issue_engine.state <= ISSUE_REALIGN;
issue_engine.align <= '1'; -- aligned on 16-bit boundary
else
issue_engine.state <= issue_engine.state_nxt;
issue_engine.align <= '0'; -- aligned on 32-bit boundary
end if;
else
issue_engine.state <= issue_engine.state_nxt;
issue_engine.align <= '0'; -- always aligned on 32-bit boundaries
end if;
else
issue_engine.state <= issue_engine.state_nxt;
issue_engine.align <= issue_engine.align_nxt;
end if;
issue_engine.buf <= issue_engine.buf_nxt;
end if;
end process issue_engine_fsm_sync;
 
 
-- Issue Engine FSM Comb ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
issue_engine_fsm_comb: process(issue_engine, ipb, i_buf, execute_engine, ci_illegal, ci_instr32)
begin
-- arbiter defaults --
issue_engine.state_nxt <= issue_engine.state;
issue_engine.align_nxt <= issue_engine.align;
issue_engine.buf_nxt <= issue_engine.buf;
 
-- instruction prefetch buffer interface defaults --
ipb.re <= '0';
 
-- instruction buffer interface defaults --
i_buf.we <= '0';
i_buf.wdata <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
 
-- state machine --
case issue_engine.state is
 
when ISSUE_ACTIVE => -- issue instruction if available
-- ------------------------------------------------------------
if (ipb.avail = '1') then -- instructions available?
 
if (issue_engine.align = '0') or (CPU_EXTENSION_RISCV_C = false) then -- begin check in LOW instruction half-word
if (i_buf.free = '1') then
issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
if (ipb.rdata(1 downto 0) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed and "aligned"
ipb.re <= '1';
i_buf.wdata <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
i_buf.we <= '1';
else -- compressed
ipb.re <= '1';
i_buf.wdata <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
i_buf.we <= '1';
issue_engine.align_nxt <= '1';
end if;
end if;
 
else -- begin check in HIGH instruction half-word
if (i_buf.free = '1') then
issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
if (issue_engine.buf(1 downto 0) = "11") then -- uncompressed and "unaligned"
ipb.re <= '1';
i_buf.wdata <= '0' & issue_engine.buf(17 downto 16) & '0' & (ipb.rdata(15 downto 0) & issue_engine.buf(15 downto 0));
i_buf.we <= '1';
else -- compressed
--ipb.re <= '1';
i_buf.wdata <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
i_buf.we <= '1';
issue_engine.align_nxt <= '0';
end if;
end if;
end if;
end if;
 
when ISSUE_REALIGN => -- re-align input fifos after a branch to an unaligned address
-- ------------------------------------------------------------
issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16);
if (ipb.avail = '1') then -- instructions available?
ipb.re <= '1';
issue_engine.state_nxt <= ISSUE_ACTIVE;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
issue_engine.state_nxt <= ISSUE_ACTIVE;
 
end case;
end process issue_engine_fsm_comb;
 
-- 16-bit instruction: half-word select --
ci_instr16 <= ipb.rdata(15 downto 0) when (issue_engine.align = '0') else issue_engine.buf(15 downto 0);
 
 
-- Compressed Instructions Recoding -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_decompressor_inst_true:
if (CPU_EXTENSION_RISCV_C = true) generate
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
port map (
-- instruction input --
ci_instr16_i => ci_instr16, -- compressed instruction input
-- instruction output --
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction
);
end generate;
 
neorv32_cpu_decompressor_inst_false:
if (CPU_EXTENSION_RISCV_C = false) generate
ci_instr32 <= (others => '0');
ci_illegal <= '0';
end generate;
 
 
-- Instruction Buffer ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
instruction_buffer_ctrl: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
i_buf.status <= '0';
elsif rising_edge(clk_i) then
if (i_buf.clear = '1') then
i_buf.status <= '0';
elsif (i_buf.we = '1') then
i_buf.status <= '1';
elsif (i_buf.re = '1') then
i_buf.status <= '0';
end if;
end if;
end process instruction_buffer_ctrl;
 
instruction_buffer_data: process(clk_i)
begin
if rising_edge(clk_i) then
if (i_buf.we = '1') and (ipb.clear = '0') then
i_buf.rdata <= i_buf.wdata;
end if;
end if;
end process instruction_buffer_data;
 
-- status --
i_buf.free <= not i_buf.status;
i_buf.avail <= i_buf.status;
 
-- clear i_buf when clearing ipb --
i_buf.clear <= ipb.clear;
 
 
-- ****************************************************************************************************************************
-- Instruction Execution
-- ****************************************************************************************************************************
 
584,7 → 689,7
 
-- Execute Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl, csr_acc_valid,
execute_engine_fsm_comb: process(execute_engine, fetch_engine, i_buf, trap_ctrl, csr, ctrl, csr_acc_valid,
alu_res_i, alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
variable alu_immediate_v : std_ulogic;
variable rs1_is_r0_v : std_ulogic;
602,7 → 707,7
 
-- instruction dispatch --
fetch_engine.reset <= '0';
ipb.re <= '0';
i_buf.re <= '0';
 
-- trap environment control --
trap_ctrl.env_start_ack <= '0';
658,28 → 763,28
--
execute_engine.state_nxt <= DISPATCH;
 
when DISPATCH => -- Get new command from instruction prefetch buffer (IPB)
when DISPATCH => -- Get new command from instruction buffer (I_BUF)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= ipb.rdata(instr_rd_msb_c downto instr_rd_lsb_c); -- rd addr
ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= ipb.rdata(instr_rs1_msb_c downto instr_rs1_lsb_c); -- rs1 addr
ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= ipb.rdata(instr_rs2_msb_c downto instr_rs2_lsb_c); -- rs2 addr
ctrl_nxt(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= i_buf.rdata(instr_rd_msb_c downto instr_rd_lsb_c); -- rd addr
ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= i_buf.rdata(instr_rs1_msb_c downto instr_rs1_lsb_c); -- rs1 addr
ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= i_buf.rdata(instr_rs2_msb_c downto instr_rs2_lsb_c); -- rs2 addr
--
if (ipb.avail = '1') then -- instruction available?
ipb.re <= '1';
if (i_buf.avail = '1') then -- instruction available?
i_buf.re <= '1';
--
execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a de-compressed instruction beeing executed
execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0);
execute_engine.is_ci_nxt <= i_buf.rdata(32); -- flag to indicate this is a de-compressed instruction beeing executed
execute_engine.i_reg_nxt <= i_buf.rdata(31 downto 0);
execute_engine.if_rst_nxt <= '0';
--
trap_ctrl.instr_ma <= ipb.rdata(33); -- misaligned instruction fetch address
trap_ctrl.instr_be <= ipb.rdata(34); -- bus access fault during instrucion fetch
illegal_compressed <= ipb.rdata(35); -- invalid decompressed instruction
trap_ctrl.instr_ma <= i_buf.rdata(33); -- misaligned instruction fetch address
trap_ctrl.instr_be <= i_buf.rdata(34); -- bus access fault during instrucion fetch
illegal_compressed <= i_buf.rdata(35); -- invalid decompressed instruction
--
if (execute_engine.if_rst = '0') then -- if there was NO non-linear PC modification
execute_engine.pc_nxt <= execute_engine.next_pc;
end if;
--
if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or ((ipb.rdata(33) or ipb.rdata(34)) = '1') then
if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or ((i_buf.rdata(33) or i_buf.rdata(34)) = '1') then
execute_engine.state_nxt <= TRAP;
else
execute_engine.state_nxt <= EXECUTE;
/neorv32_package.vhd
41,7 → 41,7
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- data width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040405"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040408"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED!
 
-- Architecture Configuration -------------------------------------------------------------
49,6 → 49,7
constant ispace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"00000000"; -- default instruction memory address space base address
constant dspace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"80000000"; -- default data memory address space base address
constant bus_timeout_c : natural := 127; -- cycles after which a valid bus access will timeout and triggers an access exception
constant wb_pipe_mode_c : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode (better timing)
constant ipb_entries_c : natural := 2; -- entries in instruction prefetch buffer, must be a power of 2, default=2
constant rf_r0_is_reg_c : boolean := true; -- reg_file.r0 is a physical register that has to be initialized to zero
 
1057,6 → 1058,7
component neorv32_wishbone
generic (
INTERFACE_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2)
WB_PIPELINED_MODE : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode
-- Internal instruction memory --
MEM_INT_IMEM_USE : boolean := true; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 8*1024; -- size of processor-internal instruction memory in bytes
/neorv32_top.vhd
511,6 → 511,7
neorv32_wishbone_inst: neorv32_wishbone
generic map (
INTERFACE_REG_STAGES => MEM_EXT_REG_STAGES, -- number of interface register stages (0,1,2)
WB_PIPELINED_MODE => wb_pipe_mode_c, -- false: classic/standard wishbone mode, true: pipelined wishbone mode
-- Internal instruction memory --
MEM_INT_IMEM_USE => MEM_INT_IMEM_USE, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
/neorv32_wishbone.vhd
3,7 → 3,9
-- # ********************************************************************************************* #
-- # The interface is either unregistered (INTERFACE_REG_STAGES = 0), only outgoing signals are #
-- # registered (INTERFACE_REG_STAGES = 1) or incoming and outgoing signals are registered #
-- # (INTERFACE_REG_STAGES = 2). #
-- # (INTERFACE_REG_STAGES = 2). This interface supports classic/standard Wishbone transactions #
-- # (WB_PIPELINED_MODE = false) and also pipelined transactions for improved timing #
-- # (WB_PIPELINED_MODE = true). #
-- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
-- # All bus accesses from the CPU, which do not target the internal IO region, the internal boot- #
-- # loader or the internal instruction or data memories (if implemented), are delegated via this #
50,6 → 52,7
entity neorv32_wishbone is
generic (
INTERFACE_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2)
WB_PIPELINED_MODE : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode
-- Internal instruction memory --
MEM_INT_IMEM_USE : boolean := true; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 8*1024; -- size of processor-internal instruction memory in bytes
95,6 → 98,7
signal rb_en : std_ulogic;
 
-- bus arbiter --
signal wb_we_ff : std_ulogic;
signal wb_stb_ff0 : std_ulogic;
signal wb_stb_ff1 : std_ulogic;
signal wb_cyc_ff : std_ulogic;
101,6 → 105,10
signal wb_ack_ff : std_ulogic;
signal wb_err_ff : std_ulogic;
 
-- wishbone mode: standard / pipelined --
signal stb_int_std : std_ulogic;
signal stb_int_pipe : std_ulogic;
 
-- data read-back --
signal wb_rdata : std_ulogic_vector(31 downto 0);
 
115,11 → 123,14
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- access to internal IMEM or DMEM? --
int_imem_acc <= '1' when (addr_i >= imem_base_c) and (addr_i < std_ulogic_vector(unsigned(imem_base_c) + MEM_INT_IMEM_SIZE)) else '0';
int_dmem_acc <= '1' when (addr_i >= dmem_base_c) and (addr_i < std_ulogic_vector(unsigned(dmem_base_c) + MEM_INT_DMEM_SIZE)) else '0';
int_imem_acc <= '1' when (addr_i(31 downto index_size_f(MEM_INT_IMEM_SIZE)) = imem_base_c(31 downto index_size_f(MEM_INT_IMEM_SIZE))) else '0';
int_dmem_acc <= '1' when (addr_i(31 downto index_size_f(MEM_INT_DMEM_SIZE)) = dmem_base_c(31 downto index_size_f(MEM_INT_DMEM_SIZE))) else '0';
int_imem_acc_real <= int_imem_acc when (MEM_INT_IMEM_USE = true) else '0';
int_dmem_acc_real <= int_dmem_acc when (MEM_INT_DMEM_USE = true) else '0';
 
-- access to internal BOOTROM or IO devices? --
int_boot_acc <= '1' when (addr_i >= boot_rom_base_c) else '0'; -- this also covers access to the IO space
--int_boot_acc <= '1' when (addr_i(31 downto index_size_f(2*boot_rom_max_size_c)) = boot_rom_base_c(31 downto index_size_f(2*boot_rom_max_size_c))) else '0'; -- this also covers access to the IO space
--int_io_acc <= '1' when (addr_i >= io_base_c) else '0';
 
-- actual external bus access? --
131,6 → 142,7
bus_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
wb_we_ff <= '0';
wb_cyc_ff <= '0';
wb_stb_ff1 <= '0';
wb_stb_ff0 <= '0';
139,6 → 151,8
wb_access_ff <= '0';
wb_access_ff_ff <= '0';
elsif rising_edge(clk_i) then
-- read/write --
wb_we_ff <= (wb_we_ff or wren_i) and wb_access and (not wb_ack_i) and (not wb_err_i) and (not cancel_i);
-- bus cycle --
if (INTERFACE_REG_STAGES = 0) then
wb_cyc_ff <= '0'; -- unused
162,11 → 176,14
end if;
end process bus_arbiter;
 
-- bus cycle --
-- valid bus cycle --
wb_cyc_o <= wb_access when (INTERFACE_REG_STAGES = 0) else wb_cyc_ff;
 
-- bus_strobe: rising edge detector --
wb_stb_o <= (wb_access and (not wb_stb_ff0)) when (INTERFACE_REG_STAGES = 0) else (wb_stb_ff0 and (not wb_stb_ff1));
-- bus strobe --
stb_int_std <= wb_access when (INTERFACE_REG_STAGES = 0) else wb_cyc_ff; -- same as wb_cyc
stb_int_pipe <= (wb_access and (not wb_stb_ff0)) when (INTERFACE_REG_STAGES = 0) else (wb_stb_ff0 and (not wb_stb_ff1)); -- wb_access rising edge detector
--
wb_stb_o <= stb_int_std when (WB_PIPELINED_MODE = false) else stb_int_pipe; -- standard or pipelined mode
 
-- cpu ack --
ack_o <= wb_ack_ff when (INTERFACE_REG_STAGES = 2) else wb_ack_i;
187,7 → 204,7
wb_adr_o <= addr_i;
wb_dat_o <= data_i;
wb_sel_o <= ben_i;
wb_we_o <= wren_i;
wb_we_o <= wren_i or wb_we_ff;
end generate;
 
interface_reg_level_one:
199,7 → 216,7
wb_adr_o <= addr_i;
wb_dat_o <= data_i;
wb_sel_o <= ben_i;
wb_we_o <= wren_i;
wb_we_o <= wren_i or wb_we_ff;
end if;
end if;
end process buffer_stages_one;
215,7 → 232,7
wb_adr_o <= addr_i;
wb_dat_o <= data_i;
wb_sel_o <= ben_i;
wb_we_o <= wren_i;
wb_we_o <= wren_i or wb_we_ff;
end if;
if (wb_ack_i = '1') then
wb_rdata <= wb_dat_i;

powered by: WebSVN 2.1.0

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