Line 71... |
Line 71... |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
|
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
|
-- Physical Memory Protection (PMP) --
|
-- Physical Memory Protection (PMP) --
|
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
|
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
|
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
-- Hardware Performance Monitors (HPM) --
|
-- Hardware Performance Monitors (HPM) --
|
HPM_NUM_CNTS : natural := 0 -- number of inmplemnted HPM counters (0..29)
|
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29)
|
);
|
);
|
port (
|
port (
|
-- global control --
|
-- global control --
|
clk_i : in std_ulogic := '0'; -- global clock, rising edge
|
clk_i : in std_ulogic := '0'; -- global clock, rising edge
|
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
|
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
|
|
sleep_o : out std_ulogic; -- cpu is in sleep mode when set
|
-- instruction bus interface --
|
-- instruction bus interface --
|
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
|
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
|
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data
|
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data
|
i_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
|
i_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
|
i_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
|
i_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
|
Line 110... |
Line 111... |
-- interrupts (risc-v compliant) --
|
-- interrupts (risc-v compliant) --
|
msw_irq_i : in std_ulogic := '0'; -- machine software interrupt
|
msw_irq_i : in std_ulogic := '0'; -- machine software interrupt
|
mext_irq_i : in std_ulogic := '0'; -- machine external interrupt
|
mext_irq_i : in std_ulogic := '0'; -- machine external interrupt
|
mtime_irq_i : in std_ulogic := '0'; -- machine timer interrupt
|
mtime_irq_i : in std_ulogic := '0'; -- machine timer interrupt
|
-- fast interrupts (custom) --
|
-- fast interrupts (custom) --
|
firq_i : in std_ulogic_vector(3 downto 0) := (others => '0')
|
firq_i : in std_ulogic_vector(7 downto 0) := (others => '0');
|
|
firq_ack_o : out std_ulogic_vector(7 downto 0)
|
);
|
);
|
end neorv32_cpu;
|
end neorv32_cpu;
|
|
|
architecture neorv32_cpu_rtl of neorv32_cpu is
|
architecture neorv32_cpu_rtl of neorv32_cpu is
|
|
|
-- local signals --
|
-- local signals --
|
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
signal alu_cmp : std_ulogic_vector(1 downto 0); -- alu comparator result
|
signal comparator : std_ulogic_vector(1 downto 0); -- comparator result
|
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
|
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
|
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
|
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
|
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
|
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
|
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result
|
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result
|
Line 148... |
Line 150... |
|
|
-- pmp interface --
|
-- pmp interface --
|
signal pmp_addr : pmp_addr_if_t;
|
signal pmp_addr : pmp_addr_if_t;
|
signal pmp_ctrl : pmp_ctrl_if_t;
|
signal pmp_ctrl : pmp_ctrl_if_t;
|
|
|
|
-- atomic memory access - success? --
|
|
signal atomic_sc_res: std_ulogic;
|
|
|
begin
|
begin
|
|
|
-- Sanity Checks --------------------------------------------------------------------------
|
-- Sanity Checks --------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- CSR system --
|
-- CSR system --
|
Line 206... |
Line 211... |
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
|
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
|
-- Physical memory protection (PMP) --
|
-- Physical memory protection (PMP) --
|
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
|
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
|
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
-- Hardware Performance Monitors (HPM) --
|
-- Hardware Performance Monitors (HPM) --
|
HPM_NUM_CNTS => HPM_NUM_CNTS -- number of inmplemnted HPM counters (0..29)
|
HPM_NUM_CNTS => HPM_NUM_CNTS -- number of implemented HPM counters (0..29)
|
)
|
)
|
port map (
|
port map (
|
-- global control --
|
-- global control --
|
clk_i => clk_i, -- global clock, rising edge
|
clk_i => clk_i, -- global clock, rising edge
|
rstn_i => rstn_i, -- global reset, low-active, async
|
rstn_i => rstn_i, -- global reset, low-active, async
|
Line 219... |
Line 224... |
alu_wait_i => alu_wait, -- wait for ALU
|
alu_wait_i => alu_wait, -- wait for ALU
|
bus_i_wait_i => bus_i_wait, -- wait for bus
|
bus_i_wait_i => bus_i_wait, -- wait for bus
|
bus_d_wait_i => bus_d_wait, -- wait for bus
|
bus_d_wait_i => bus_d_wait, -- wait for bus
|
-- data input --
|
-- data input --
|
instr_i => instr, -- instruction
|
instr_i => instr, -- instruction
|
cmp_i => alu_cmp, -- comparator status
|
cmp_i => comparator, -- comparator status
|
alu_add_i => alu_add, -- ALU address result
|
alu_add_i => alu_add, -- ALU address result
|
rs1_i => rs1, -- rf source 1
|
rs1_i => rs1, -- rf source 1
|
-- data output --
|
-- data output --
|
imm_o => imm, -- immediate
|
imm_o => imm, -- immediate
|
fetch_pc_o => fetch_pc, -- PC for instruction fetch
|
fetch_pc_o => fetch_pc, -- PC for instruction fetch
|
Line 232... |
Line 237... |
-- interrupts (risc-v compliant) --
|
-- interrupts (risc-v compliant) --
|
msw_irq_i => msw_irq_i, -- machine software interrupt
|
msw_irq_i => msw_irq_i, -- machine software interrupt
|
mext_irq_i => mext_irq_i, -- machine external interrupt
|
mext_irq_i => mext_irq_i, -- machine external interrupt
|
mtime_irq_i => mtime_irq_i, -- machine timer interrupt
|
mtime_irq_i => mtime_irq_i, -- machine timer interrupt
|
-- fast interrupts (custom) --
|
-- fast interrupts (custom) --
|
firq_i => firq_i,
|
firq_i => firq_i, -- fast interrupt trigger
|
|
firq_ack_o => firq_ack_o, -- fast interrupt acknowledge mask
|
-- system time input from MTIME --
|
-- system time input from MTIME --
|
time_i => time_i, -- current system time
|
time_i => time_i, -- current system time
|
-- physical memory protection --
|
-- physical memory protection --
|
pmp_addr_o => pmp_addr, -- addresses
|
pmp_addr_o => pmp_addr, -- addresses
|
pmp_ctrl_o => pmp_ctrl, -- configs
|
pmp_ctrl_o => pmp_ctrl, -- configs
|
Line 248... |
Line 254... |
be_instr_i => be_instr, -- bus error on instruction access
|
be_instr_i => be_instr, -- bus error on instruction access
|
be_load_i => be_load, -- bus error on load data access
|
be_load_i => be_load, -- bus error on load data access
|
be_store_i => be_store -- bus error on store data access
|
be_store_i => be_store -- bus error on store data access
|
);
|
);
|
|
|
|
-- CPU is sleeping? --
|
|
sleep_o <= ctrl(ctrl_sleep_c); -- set when CPU is sleeping (after WFI)
|
|
|
|
|
-- Register File --------------------------------------------------------------------------
|
-- Register File --------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_regfile_inst: neorv32_cpu_regfile
|
neorv32_cpu_regfile_inst: neorv32_cpu_regfile
|
generic map (
|
generic map (
|
Line 265... |
Line 274... |
mem_i => rdata, -- memory read data
|
mem_i => rdata, -- memory read data
|
alu_i => alu_res, -- ALU result
|
alu_i => alu_res, -- ALU result
|
csr_i => csr_rdata, -- CSR read data
|
csr_i => csr_rdata, -- CSR read data
|
-- data output --
|
-- data output --
|
rs1_o => rs1, -- operand 1
|
rs1_o => rs1, -- operand 1
|
rs2_o => rs2 -- operand 2
|
rs2_o => rs2, -- operand 2
|
|
cmp_o => comparator -- comparator status
|
);
|
);
|
|
|
|
|
-- ALU ------------------------------------------------------------------------------------
|
-- ALU ------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
Line 287... |
Line 297... |
rs1_i => rs1, -- rf source 1
|
rs1_i => rs1, -- rf source 1
|
rs2_i => rs2, -- rf source 2
|
rs2_i => rs2, -- rf source 2
|
pc2_i => curr_pc, -- delayed PC
|
pc2_i => curr_pc, -- delayed PC
|
imm_i => imm, -- immediate
|
imm_i => imm, -- immediate
|
-- data output --
|
-- data output --
|
cmp_o => alu_cmp, -- comparator status
|
|
res_o => alu_res, -- ALU result
|
res_o => alu_res, -- ALU result
|
add_o => alu_add, -- address computation result
|
add_o => alu_add, -- address computation result
|
-- co-processor interface --
|
-- co-processor interface --
|
cp0_start_o => cp0_start, -- trigger co-processor 0
|
cp0_start_o => cp0_start, -- trigger co-processor 0
|
cp0_data_i => cp0_data, -- co-processor 0 result
|
cp0_data_i => cp0_data, -- co-processor 0 result
|
Line 308... |
Line 317... |
-- status --
|
-- status --
|
wait_o => alu_wait -- busy due to iterative processing units
|
wait_o => alu_wait -- busy due to iterative processing units
|
);
|
);
|
|
|
|
|
-- Co-Processor 0: MULDIV Unit ------------------------------------------------------------
|
-- Co-Processor 0: Integer Multiplication/Division ('M' Extension) ------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_cp_muldiv_inst_true:
|
neorv32_cpu_cp_muldiv_inst_true:
|
if (CPU_EXTENSION_RISCV_M = true) generate
|
if (CPU_EXTENSION_RISCV_M = true) generate
|
neorv32_cpu_cp_muldiv_inst: neorv32_cpu_cp_muldiv
|
neorv32_cpu_cp_muldiv_inst: neorv32_cpu_cp_muldiv
|
generic map (
|
generic map (
|
Line 338... |
Line 347... |
cp0_data <= (others => '0');
|
cp0_data <= (others => '0');
|
cp0_valid <= cp0_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp0_valid <= cp0_start; -- to make sure CPU does not get stalled if there is an accidental access
|
end generate;
|
end generate;
|
|
|
|
|
-- Co-Processor 1: Atomic Memory Access, SC - store-conditional ('M' extension) -----------
|
-- Co-Processor 1: Atomic Memory Access ('A' Extension) -----------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
atomic_op_cp: process(cp1_start, ctrl)
|
-- "pseudo" co-processor for atomic operations
|
begin
|
|
-- "fake" co-processor for atomic operations
|
|
-- used to get the result of a store-conditional operation into the data path
|
-- used to get the result of a store-conditional operation into the data path
|
if (CPU_EXTENSION_RISCV_A = true) then
|
atomic_op_cp: process(clk_i)
|
|
begin
|
|
if rising_edge(clk_i) then
|
if (cp1_start = '1') then
|
if (cp1_start = '1') then
|
cp1_data <= (others => '0');
|
atomic_sc_res <= not ctrl(ctrl_bus_lock_c);
|
cp1_data(0) <= not ctrl(ctrl_bus_lock_c);
|
|
cp1_valid <= '1';
|
|
else
|
else
|
cp1_data <= (others => '0');
|
atomic_sc_res <= '0';
|
cp1_valid <= '0';
|
|
end if;
|
end if;
|
else
|
|
cp1_data <= (others => '0');
|
|
cp1_valid <= cp1_start; -- to make sure CPU does not get stalled if there is an accidental access
|
|
end if;
|
end if;
|
end process atomic_op_cp;
|
end process atomic_op_cp;
|
|
|
|
-- CP result --
|
|
cp1_data(data_width_c-1 downto 1) <= (others => '0');
|
|
cp1_data(0) <= atomic_sc_res when (CPU_EXTENSION_RISCV_A = true) else '0';
|
|
cp1_valid <= cp1_start; -- always assigned even if A is disabled to make sure CPU does not get stalled if there is an accidental access
|
|
|
|
|
-- Co-Processor 2: Not implemented (yet) --------------------------------------------------
|
-- Co-Processor 2: Bit Manipulation ('B' Extension) ---------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_cp_bitmanip_inst_true:
|
neorv32_cpu_cp_bitmanip_inst_true:
|
if (CPU_EXTENSION_RISCV_B = true) generate
|
if (CPU_EXTENSION_RISCV_B = true) generate
|
neorv32_cpu_cp_bitmanip_inst: neorv32_cpu_cp_bitmanip
|
neorv32_cpu_cp_bitmanip_inst: neorv32_cpu_cp_bitmanip
|
port map (
|
port map (
|
Line 372... |
Line 380... |
clk_i => clk_i, -- global clock, rising edge
|
clk_i => clk_i, -- global clock, rising edge
|
rstn_i => rstn_i, -- global reset, low-active, async
|
rstn_i => rstn_i, -- global reset, low-active, async
|
ctrl_i => ctrl, -- main control bus
|
ctrl_i => ctrl, -- main control bus
|
start_i => cp2_start, -- trigger operation
|
start_i => cp2_start, -- trigger operation
|
-- data input --
|
-- data input --
|
cmp_i => alu_cmp, -- comparator status
|
cmp_i => comparator, -- comparator status
|
rs1_i => rs1, -- rf source 1
|
rs1_i => rs1, -- rf source 1
|
rs2_i => rs2, -- rf source 2
|
rs2_i => rs2, -- rf source 2
|
-- result and status --
|
-- result and status --
|
res_o => cp2_data, -- operation result
|
res_o => cp2_data, -- operation result
|
valid_o => cp2_valid -- data output valid
|
valid_o => cp2_valid -- data output valid
|
Line 388... |
Line 396... |
cp2_data <= (others => '0');
|
cp2_data <= (others => '0');
|
cp2_valid <= cp2_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp2_valid <= cp2_start; -- to make sure CPU does not get stalled if there is an accidental access
|
end generate;
|
end generate;
|
|
|
|
|
-- Co-Processor 3: Not implemented (yet) --------------------------------------------------
|
-- Co-Processor 3: Not implemented --------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- control: ctrl cp3_start
|
|
-- inputs: rs1 rs2 alu_cmp
|
|
cp3_data <= (others => '0');
|
cp3_data <= (others => '0');
|
cp3_valid <= cp3_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp3_valid <= cp3_start; -- to make sure CPU does not get stalled if there is an accidental access
|
|
|
|
|
-- Bus Interface Unit ---------------------------------------------------------------------
|
-- Bus Interface Unit ---------------------------------------------------------------------
|