Line 129... |
Line 129... |
re : std_ulogic; -- read enable
|
re : std_ulogic; -- read enable
|
avail : std_ulogic; -- data available?
|
avail : std_ulogic; -- data available?
|
--
|
--
|
w_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- write pointer
|
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
|
r_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- read pointer
|
|
match : std_ulogic;
|
empty : std_ulogic;
|
empty : std_ulogic;
|
full : std_ulogic;
|
full : std_ulogic;
|
--
|
--
|
data : ipb_data_fifo_t; -- fifo memory
|
data : ipb_data_fifo_t; -- fifo memory
|
end record;
|
end record;
|
Line 390... |
Line 391... |
|
|
-- async read --
|
-- async read --
|
ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0))));
|
ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0))));
|
|
|
-- status --
|
-- 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.match <= '1' when (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.full <= '1' when (ipb.r_pnt(ipb.r_pnt'left) /= ipb.w_pnt(ipb.w_pnt'left)) and (ipb.match = '1') else '0';
|
|
ipb.empty <= '1' when (ipb.r_pnt(ipb.r_pnt'left) = ipb.w_pnt(ipb.w_pnt'left)) and (ipb.match = '1') else '0';
|
ipb.free <= not ipb.full;
|
ipb.free <= not ipb.full;
|
ipb.avail <= not ipb.empty;
|
ipb.avail <= not ipb.empty;
|
|
|
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
Line 548... |
Line 549... |
end process instruction_buffer_ctrl;
|
end process instruction_buffer_ctrl;
|
|
|
instruction_buffer_data: process(clk_i)
|
instruction_buffer_data: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if (i_buf.we = '1') and (ipb.clear = '0') then
|
if (i_buf.we = '1') and (i_buf.clear = '0') then
|
i_buf.rdata <= i_buf.wdata;
|
i_buf.rdata <= i_buf.wdata;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process instruction_buffer_data;
|
end process instruction_buffer_data;
|
|
|
Line 595... |
Line 596... |
imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
|
imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
|
imm_o(11) <= execute_engine.i_reg(20);
|
imm_o(11) <= execute_engine.i_reg(20);
|
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
|
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
|
imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
|
imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
|
imm_o(00) <= '0';
|
imm_o(00) <= '0';
|
when opcode_syscsr_c => -- CSR-immediate
|
when opcode_syscsr_c => -- CSR-immediate (uimm5)
|
imm_o(31 downto 05) <= (others => '0');
|
imm_o(31 downto 05) <= (others => '0');
|
imm_o(04 downto 00) <= execute_engine.i_reg(19 downto 15);
|
imm_o(04 downto 00) <= execute_engine.i_reg(19 downto 15);
|
when others => -- I-immediate
|
when others => -- I-immediate
|
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
|
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
|
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
|
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
|
Line 797... |
Line 798... |
end if;
|
end if;
|
end if;
|
end if;
|
|
|
when TRAP => -- Start trap environment (also used as cpu sleep state)
|
when TRAP => -- Start trap environment (also used as cpu sleep state)
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
|
-- stay here for sleep
|
|
if (trap_ctrl.env_start = '1') then -- trap triggered?
|
fetch_engine.reset <= '1';
|
fetch_engine.reset <= '1';
|
execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
|
execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
|
if (trap_ctrl.env_start = '1') then -- check here again if we came directly from DISPATCH
|
|
trap_ctrl.env_start_ack <= '1';
|
trap_ctrl.env_start_ack <= '1';
|
execute_engine.pc_nxt <= csr.mtvec;
|
execute_engine.pc_nxt <= csr.mtvec;
|
execute_engine.sleep_nxt <= '0'; -- waky waky
|
execute_engine.sleep_nxt <= '0'; -- waky waky
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
end if;
|
end if;
|
Line 1480... |
Line 1482... |
csr.mepc <= (others => '0');
|
csr.mepc <= (others => '0');
|
csr.mcause <= (others => '0');
|
csr.mcause <= (others => '0');
|
csr.mtval <= (others => '0');
|
csr.mtval <= (others => '0');
|
csr.pmpcfg <= (others => (others => '0'));
|
csr.pmpcfg <= (others => (others => '0'));
|
csr.pmpaddr <= (others => (others => '0'));
|
csr.pmpaddr <= (others => (others => '0'));
|
|
--
|
|
csr.mcycle <= (others => '0');
|
|
csr.minstret <= (others => '0');
|
|
csr.mcycleh <= (others => '0');
|
|
csr.minstreth <= (others => '0');
|
|
mcycle_msb <= '0';
|
|
minstret_msb <= '0';
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
|
|
-- write access? --
|
-- write access? --
|
csr.we <= csr.we_nxt;
|
csr.we <= csr.we_nxt;
|
|
|
Line 1658... |
Line 1667... |
csr.privilege <= priv_mode_m_c;
|
csr.privilege <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
|
-- --------------------------------------------------------------------------------
|
|
-- Counter CSRs
|
|
-- --------------------------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
|
|
|
-- mcycle (cycle) --
|
|
mcycle_msb <= csr.mcycle(csr.mcycle'left);
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycle_c) then -- write access
|
|
csr.mcycle(31 downto 0) <= csr.wdata;
|
|
csr.mcycle(32) <= '0';
|
|
elsif (execute_engine.sleep = '0') then -- automatic update (if CPU is not in sleep mode)
|
|
csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
|
|
end if;
|
|
|
|
-- mcycleh (cycleh) --
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycleh_c) then -- write access
|
|
csr.mcycleh <= csr.wdata(csr.mcycleh'left downto 0);
|
|
elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
|
|
csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
|
|
end if;
|
|
|
|
-- minstret (instret) --
|
|
minstret_msb <= csr.minstret(csr.minstret'left);
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstret_c) then -- write access
|
|
csr.minstret(31 downto 0) <= csr.wdata;
|
|
csr.minstret(32) <= '0';
|
|
elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
|
|
csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
|
|
end if;
|
|
|
|
-- minstreth (instreth) --
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstreth_c) then -- write access
|
|
csr.minstreth <= csr.wdata(csr.minstreth'left downto 0);
|
|
elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
|
|
csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
|
|
end if;
|
|
end if;
|
end if;
|
end if;
|
end process csr_write_access;
|
end process csr_write_access;
|
|
|
|
-- CPU's current privilege level --
|
|
priv_mode_o <= csr.privilege;
|
|
|
|
-- PMP output --
|
|
pmp_output: process(csr)
|
|
begin
|
|
pmp_addr_o <= (others => (others => '0'));
|
|
pmp_ctrl_o <= (others => (others => '0'));
|
|
if (PMP_USE = true) then
|
|
for i in 0 to PMP_NUM_REGIONS-1 loop
|
|
pmp_addr_o(i) <= csr.pmpaddr(i) & "00";
|
|
pmp_ctrl_o(i) <= csr.pmpcfg(i);
|
|
end loop; -- i
|
|
end if;
|
|
end process pmp_output;
|
|
|
|
|
-- Control and Status Registers Read Access -----------------------------------------------
|
-- Control and Status Registers Read Access -----------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_read_access: process(clk_i)
|
csr_read_access: process(clk_i)
|
begin
|
begin
|
Line 1840... |
Line 1902... |
csr.rdata <= csr.minstreth(31 downto 0);
|
csr.rdata <= csr.minstreth(31 downto 0);
|
|
|
-- machine information registers --
|
-- machine information registers --
|
when csr_mvendorid_c => -- R/-: mvendorid - vendor ID
|
when csr_mvendorid_c => -- R/-: mvendorid - vendor ID
|
csr.rdata <= (others => '0');
|
csr.rdata <= (others => '0');
|
when csr_marchid_c => -- R/-: marchid - architecture ID
|
when csr_marchid_c => -- R/-: marchid - arch ID
|
csr.rdata(4 downto 0) <= "10011"; -- official open-source arch ID
|
csr.rdata(4 downto 0) <= "10011"; -- official RISC-V open-source arch ID
|
when csr_mimpid_c => -- R/-: mimpid - implementation ID
|
when csr_mimpid_c => -- R/-: mimpid - implementation ID
|
csr.rdata <= hw_version_c; -- NEORV32 hardware version
|
csr.rdata <= hw_version_c; -- NEORV32 hardware version
|
when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
|
when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
|
csr.rdata <= HW_THREAD_ID;
|
csr.rdata <= HW_THREAD_ID;
|
|
|
Line 1865... |
Line 1927... |
end process csr_read_access;
|
end process csr_read_access;
|
|
|
-- CSR read data output --
|
-- CSR read data output --
|
csr_rdata_o <= csr.rdata;
|
csr_rdata_o <= csr.rdata;
|
|
|
-- CPU's current privilege level --
|
|
priv_mode_o <= csr.privilege;
|
|
|
|
-- PMP output --
|
|
pmp_output: process(csr)
|
|
begin
|
|
pmp_addr_o <= (others => (others => '0'));
|
|
pmp_ctrl_o <= (others => (others => '0'));
|
|
if (PMP_USE = true) then
|
|
for i in 0 to PMP_NUM_REGIONS-1 loop
|
|
pmp_addr_o(i) <= csr.pmpaddr(i) & "00";
|
|
pmp_ctrl_o(i) <= csr.pmpcfg(i);
|
|
end loop; -- i
|
|
end if;
|
|
end process pmp_output;
|
|
|
|
|
|
-- RISC-V Counter CSRs --------------------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
csr_counters: process(rstn_i, clk_i)
|
|
begin
|
|
if (rstn_i = '0') then
|
|
csr.mcycle <= (others => '0');
|
|
csr.minstret <= (others => '0');
|
|
csr.mcycleh <= (others => '0');
|
|
csr.minstreth <= (others => '0');
|
|
mcycle_msb <= '0';
|
|
minstret_msb <= '0';
|
|
elsif rising_edge(clk_i) then
|
|
|
|
-- mcycle (cycle) --
|
|
mcycle_msb <= csr.mcycle(csr.mcycle'left);
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycle_c) then -- write access
|
|
csr.mcycle(31 downto 0) <= csr.wdata;
|
|
csr.mcycle(32) <= '0';
|
|
elsif (execute_engine.sleep = '0') then -- automatic update (if CPU is not in sleep mode)
|
|
csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
|
|
end if;
|
|
|
|
-- mcycleh (cycleh) --
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycleh_c) then -- write access
|
|
csr.mcycleh <= csr.wdata(csr.mcycleh'left downto 0);
|
|
elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
|
|
csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
|
|
end if;
|
|
|
|
-- minstret (instret) --
|
|
minstret_msb <= csr.minstret(csr.minstret'left);
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstret_c) then -- write access
|
|
csr.minstret(31 downto 0) <= csr.wdata;
|
|
csr.minstret(32) <= '0';
|
|
elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
|
|
csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
|
|
end if;
|
|
|
|
-- minstreth (instreth) --
|
|
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstreth_c) then -- write access
|
|
csr.minstreth <= csr.wdata(csr.minstreth'left downto 0);
|
|
elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
|
|
csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
|
|
end if;
|
|
end if;
|
|
end process csr_counters;
|
|
|
|
|
|
end neorv32_cpu_control_rtl;
|
end neorv32_cpu_control_rtl;
|
|
|
No newline at end of file
|
No newline at end of file
|