Line 15... |
Line 15... |
clk : in std_logic;
|
clk : in std_logic;
|
reset : in std_logic;
|
reset : in std_logic;
|
|
|
stall, flush : in std_logic;
|
stall, flush : in std_logic;
|
|
|
-- IRQ input:
|
-- Interrupt inputs:
|
irq : in std_logic_vector(7 downto 0);
|
irq : in std_logic_vector(7 downto 0);
|
|
software_interrupt, timer_interrupt : in std_logic;
|
|
|
-- Data memory outputs:
|
-- Data memory outputs:
|
dmem_address : out std_logic_vector(31 downto 0);
|
dmem_address : out std_logic_vector(31 downto 0);
|
dmem_data_out : out std_logic_vector(31 downto 0);
|
dmem_data_out : out std_logic_vector(31 downto 0);
|
dmem_data_size : out std_logic_vector( 1 downto 0);
|
dmem_data_size : out std_logic_vector( 1 downto 0);
|
Line 75... |
Line 76... |
-- Whether the instruction should be counted:
|
-- Whether the instruction should be counted:
|
count_instruction_in : in std_logic;
|
count_instruction_in : in std_logic;
|
count_instruction_out : out std_logic;
|
count_instruction_out : out std_logic;
|
|
|
-- Exception control registers:
|
-- Exception control registers:
|
status_in : in csr_status_register;
|
ie_in, ie1_in : in std_logic;
|
evec_in : in std_logic_vector(31 downto 0);
|
mie_in : in std_logic_vector(31 downto 0);
|
evec_out : out std_logic_vector(31 downto 0);
|
mtvec_in : in std_logic_vector(31 downto 0);
|
|
mtvec_out : out std_logic_vector(31 downto 0);
|
|
--mepc_in : in std_logic_vector(31 downto 0);
|
|
|
-- Exception signals:
|
-- Exception signals:
|
decode_exception_in : in std_logic;
|
decode_exception_in : in std_logic;
|
decode_exception_cause_in : in csr_exception_cause;
|
decode_exception_cause_in : in csr_exception_cause;
|
|
|
Line 141... |
Line 144... |
signal branch : branch_type;
|
signal branch : branch_type;
|
signal branch_condition : std_logic;
|
signal branch_condition : std_logic;
|
signal do_jump : std_logic;
|
signal do_jump : std_logic;
|
signal jump_target : std_logic_vector(31 downto 0);
|
signal jump_target : std_logic_vector(31 downto 0);
|
|
|
signal sr : csr_status_register;
|
signal mtvec, mtvec_forwarded : std_logic_vector(31 downto 0);
|
signal evec, evec_forwarded : std_logic_vector(31 downto 0);
|
signal mie, mie_forwarded : std_logic_vector(31 downto 0);
|
|
|
signal csr_write : csr_write_mode;
|
signal csr_write : csr_write_mode;
|
signal csr_addr : csr_address;
|
signal csr_addr : csr_address;
|
signal csr_use_immediate : std_logic;
|
signal csr_use_immediate : std_logic;
|
signal csr_writeable : boolean;
|
signal csr_writeable : boolean;
|
Line 156... |
Line 159... |
signal decode_exception : std_logic;
|
signal decode_exception : std_logic;
|
signal decode_exception_cause : csr_exception_cause;
|
signal decode_exception_cause : csr_exception_cause;
|
|
|
signal exception_taken : std_logic;
|
signal exception_taken : std_logic;
|
signal exception_cause : csr_exception_cause;
|
signal exception_cause : csr_exception_cause;
|
signal exception_vaddr : std_logic_vector(31 downto 0);
|
signal exception_addr : std_logic_vector(31 downto 0);
|
|
|
signal exception_context_forwarded : csr_exception_context;
|
signal exception_context_forwarded : csr_exception_context;
|
|
|
signal data_misaligned, instr_misaligned : std_logic;
|
signal data_misaligned, instr_misaligned : std_logic;
|
|
|
Line 183... |
Line 186... |
|
|
pc_out <= pc;
|
pc_out <= pc;
|
|
|
exception_out <= exception_taken;
|
exception_out <= exception_taken;
|
exception_context_out <= (
|
exception_context_out <= (
|
status => exception_context_forwarded.status,
|
ie => exception_context_forwarded.ie,
|
|
ie1 => exception_context_forwarded.ie1,
|
cause => exception_cause,
|
cause => exception_cause,
|
badvaddr => exception_vaddr
|
badaddr => exception_addr
|
) when exception_taken = '1' else exception_context_forwarded;
|
) when exception_taken = '1' else exception_context_forwarded;
|
|
|
do_jump <= (to_std_logic(branch = BRANCH_JUMP or branch = BRANCH_JUMP_INDIRECT)
|
do_jump <= (to_std_logic(branch = BRANCH_JUMP or branch = BRANCH_JUMP_INDIRECT)
|
or (to_std_logic(branch = BRANCH_CONDITIONAL) and branch_condition)
|
or (to_std_logic(branch = BRANCH_CONDITIONAL) and branch_condition)
|
or to_std_logic(branch = BRANCH_SRET)) and not stall;
|
or to_std_logic(branch = BRANCH_SRET)) and not stall;
|
jump_out <= do_jump;
|
jump_out <= do_jump;
|
jump_target_out <= jump_target;
|
jump_target_out <= jump_target;
|
|
|
evec_out <= evec_forwarded;
|
mtvec_out <= std_logic_vector(unsigned(mtvec_forwarded) + CSR_MTVEC_M_OFFSET);
|
exception_taken <= (decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE) or irq_asserted) and not stall;
|
exception_taken <= not stall and (decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE));
|
|
|
irq_asserted <= to_std_logic(exception_context_forwarded.status.ei = '1' and
|
irq_asserted <= to_std_logic(exception_context_forwarded.ie = '1' and (irq and mie_forwarded(31 downto 24)) /= x"00");
|
(irq and exception_context_forwarded.status.im) /= x"00");
|
|
|
|
rs1_data <= rs1_data_in;
|
rs1_data <= rs1_data_in;
|
rs2_data <= rs2_data_in;
|
rs2_data <= rs2_data_in;
|
|
|
dmem_address <= alu_result;
|
dmem_address <= alu_result when (mem_op /= MEMOP_TYPE_NONE and mem_op /= MEMOP_TYPE_INVALID) and exception_taken = '0'
|
|
else (others => '0');
|
dmem_data_out <= rs2_forwarded;
|
dmem_data_out <= rs2_forwarded;
|
dmem_write_req <= '1' when mem_op = MEMOP_TYPE_STORE else '0';
|
dmem_write_req <= '1' when mem_op = MEMOP_TYPE_STORE and exception_taken = '0' else '0';
|
dmem_read_req <= '1' when memop_is_load(mem_op) else '0';
|
dmem_read_req <= '1' when memop_is_load(mem_op) and exception_taken = '0' else '0';
|
|
|
pipeline_register: process(clk)
|
pipeline_register: process(clk)
|
begin
|
begin
|
if rising_edge(clk) then
|
if rising_edge(clk) then
|
if reset = '1' or flush = '1' then
|
if reset = '1' or flush = '1' then
|
Line 249... |
Line 253... |
csr_write <= csr_write_in;
|
csr_write <= csr_write_in;
|
csr_addr <= csr_addr_in;
|
csr_addr <= csr_addr_in;
|
csr_use_immediate <= csr_use_immediate_in;
|
csr_use_immediate <= csr_use_immediate_in;
|
csr_writeable <= csr_writeable_in;
|
csr_writeable <= csr_writeable_in;
|
|
|
-- Status register;
|
|
sr <= status_in;
|
|
|
|
-- Exception vector base:
|
-- Exception vector base:
|
evec <= evec_in;
|
mtvec <= mtvec_in;
|
|
mie <= mie_in;
|
|
|
-- Instruction decoder exceptions:
|
-- Instruction decoder exceptions:
|
decode_exception <= decode_exception_in;
|
decode_exception <= decode_exception_in;
|
decode_exception_cause <= decode_exception_cause_in;
|
decode_exception_cause <= decode_exception_cause_in;
|
end if;
|
end if;
|
Line 276... |
Line 278... |
when others =>
|
when others =>
|
dmem_data_size <= b"11";
|
dmem_data_size <= b"11";
|
end case;
|
end case;
|
end process set_data_size;
|
end process set_data_size;
|
|
|
get_irq_num: process(irq, exception_context_forwarded)
|
get_irq_num: process(irq, exception_context_forwarded, mie_forwarded)
|
variable temp : std_logic_vector(3 downto 0);
|
variable temp : std_logic_vector(3 downto 0);
|
begin
|
begin
|
temp := (others => '0');
|
temp := (others => '0');
|
|
|
for i in 0 to 7 loop
|
for i in 0 to 7 loop
|
if irq(i) = '1' and exception_context_forwarded.status.im(i) = '1' then
|
if irq(i) = '1' and mie_forwarded(24 + i) = '1' then
|
temp := std_logic_vector(to_unsigned(i, temp'length));
|
temp := std_logic_vector(to_unsigned(i, temp'length));
|
exit;
|
exit;
|
end if;
|
end if;
|
end loop;
|
end loop;
|
|
|
Line 321... |
Line 323... |
instr_misaligned <= '0';
|
instr_misaligned <= '0';
|
end if;
|
end if;
|
end process instr_misalign_check;
|
end process instr_misalign_check;
|
|
|
find_exception_cause: process(decode_exception, decode_exception_cause, mem_op,
|
find_exception_cause: process(decode_exception, decode_exception_cause, mem_op,
|
data_misaligned, instr_misaligned, irq_asserted, irq_asserted_num)
|
data_misaligned, instr_misaligned, irq_asserted, irq_asserted_num, mie_forwarded,
|
|
software_interrupt, timer_interrupt, exception_context_forwarded)
|
begin
|
begin
|
if irq_asserted = '1' then
|
if irq_asserted = '1' then
|
exception_cause <= std_logic_vector(unsigned(CSR_CAUSE_IRQ_BASE) + unsigned(irq_asserted_num));
|
exception_cause <= std_logic_vector(unsigned(CSR_CAUSE_IRQ_BASE) + unsigned(irq_asserted_num));
|
|
elsif software_interrupt = '1' and mie_forwarded(CSR_MIE_MSIE) = '1' and exception_context_forwarded.ie = '1' then
|
|
exception_cause <= CSR_CAUSE_SOFTWARE_INT;
|
|
elsif timer_interrupt = '1' and mie_forwarded(CSR_MIE_MTIE) = '1' and exception_context_forwarded.ie = '1' then
|
|
exception_cause <= CSR_CAUSE_TIMER_INT;
|
elsif decode_exception = '1' then
|
elsif decode_exception = '1' then
|
exception_cause <= decode_exception_cause;
|
exception_cause <= decode_exception_cause;
|
elsif mem_op = MEMOP_TYPE_INVALID then
|
elsif mem_op = MEMOP_TYPE_INVALID then
|
exception_cause <= CSR_CAUSE_INVALID_INSTR;
|
exception_cause <= CSR_CAUSE_INVALID_INSTR;
|
elsif instr_misaligned = '1' then
|
elsif instr_misaligned = '1' then
|
Line 340... |
Line 347... |
else
|
else
|
exception_cause <= CSR_CAUSE_NONE;
|
exception_cause <= CSR_CAUSE_NONE;
|
end if;
|
end if;
|
end process find_exception_cause;
|
end process find_exception_cause;
|
|
|
find_exception_vaddr: process(instr_misaligned, data_misaligned, jump_target, alu_result)
|
find_exception_addr: process(instr_misaligned, data_misaligned, jump_target, alu_result)
|
begin
|
begin
|
if instr_misaligned = '1' then
|
if instr_misaligned = '1' then
|
exception_vaddr <= jump_target;
|
exception_addr <= jump_target;
|
elsif data_misaligned = '1' then
|
elsif data_misaligned = '1' then
|
exception_vaddr <= alu_result;
|
exception_addr <= alu_result;
|
else
|
else
|
exception_vaddr <= (others => '0');
|
exception_addr <= (others => '0');
|
end if;
|
end if;
|
end process find_exception_vaddr;
|
end process find_exception_addr;
|
|
|
calc_jump_tgt: process(branch, pc, rs1_forwarded, immediate, csr_value_forwarded)
|
calc_jump_tgt: process(branch, pc, rs1_forwarded, immediate, csr_value_forwarded)
|
begin
|
begin
|
case branch is
|
case branch is
|
when BRANCH_JUMP | BRANCH_CONDITIONAL =>
|
when BRANCH_JUMP | BRANCH_CONDITIONAL =>
|
jump_target <= std_logic_vector(unsigned(pc) + unsigned(immediate));
|
jump_target <= std_logic_vector(unsigned(pc) + unsigned(immediate));
|
when BRANCH_JUMP_INDIRECT =>
|
when BRANCH_JUMP_INDIRECT =>
|
jump_target <= std_logic_vector(unsigned(rs1_forwarded) + unsigned(immediate));
|
jump_target <= std_logic_vector(unsigned(rs1_forwarded) + unsigned(immediate));
|
when BRANCH_SRET =>
|
when BRANCH_SRET =>
|
jump_target <= csr_value_forwarded; -- Will be the EPC value in the case of SRET
|
jump_target <= csr_value_forwarded;
|
when others =>
|
when others =>
|
jump_target <= (others => '0');
|
jump_target <= (others => '0');
|
end case;
|
end case;
|
end process calc_jump_tgt;
|
end process calc_jump_tgt;
|
|
|
Line 415... |
Line 422... |
|
|
csr_forward: process(mem_csr_write, wb_csr_write, csr_addr, mem_csr_addr, wb_csr_addr,
|
csr_forward: process(mem_csr_write, wb_csr_write, csr_addr, mem_csr_addr, wb_csr_addr,
|
csr_value, mem_csr_value, wb_csr_value, csr_writeable, mem_exception, wb_exception,
|
csr_value, mem_csr_value, wb_csr_value, csr_writeable, mem_exception, wb_exception,
|
mem_exception_context, wb_exception_context)
|
mem_exception_context, wb_exception_context)
|
begin
|
begin
|
if csr_addr = CSR_CAUSE and mem_exception = '1' then
|
if csr_addr = CSR_MCAUSE and mem_exception = '1' then
|
csr_value_forwarded <= to_std_logic_vector(mem_exception_context.cause);
|
csr_value_forwarded <= to_std_logic_vector(mem_exception_context.cause);
|
elsif csr_addr = CSR_STATUS and mem_exception = '1' then
|
elsif csr_addr = CSR_MSTATUS and mem_exception = '1' then
|
csr_value_forwarded <= to_std_logic_vector(mem_exception_context.status);
|
csr_value_forwarded <= csr_make_mstatus(mem_exception_context.ie, mem_exception_context.ie1);
|
elsif csr_addr = CSR_BADVADDR and mem_exception = '1' then
|
elsif csr_addr = CSR_MBADADDR and mem_exception = '1' then
|
csr_value_forwarded <= mem_exception_context.badvaddr;
|
csr_value_forwarded <= mem_exception_context.badaddr;
|
elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = csr_addr and csr_writeable then
|
elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = csr_addr and csr_writeable then
|
csr_value_forwarded <= mem_csr_value;
|
csr_value_forwarded <= mem_csr_value;
|
elsif csr_addr = CSR_CAUSE and wb_exception = '1' then
|
elsif csr_addr = CSR_MCAUSE and wb_exception = '1' then
|
csr_value_forwarded <= to_std_logic_vector(wb_exception_context.cause);
|
csr_value_forwarded <= to_std_logic_vector(wb_exception_context.cause);
|
elsif csr_addr = CSR_STATUS and wb_exception = '1' then
|
elsif csr_addr = CSR_MSTATUS and wb_exception = '1' then
|
csr_value_forwarded <= to_std_logic_vector(wb_exception_context.status);
|
csr_value_forwarded <= csr_make_mstatus(wb_exception_context.ie, wb_exception_context.ie1);
|
elsif csr_addr = CSR_BADVADDR and wb_exception = '1' then
|
elsif csr_addr = CSR_MBADADDR and wb_exception = '1' then
|
csr_value_forwarded <= wb_exception_context.badvaddr;
|
csr_value_forwarded <= wb_exception_context.badaddr;
|
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = csr_addr and csr_writeable then
|
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = csr_addr and csr_writeable then
|
csr_value_forwarded <= wb_csr_value;
|
csr_value_forwarded <= wb_csr_value;
|
else
|
else
|
csr_value_forwarded <= csr_value;
|
csr_value_forwarded <= csr_value;
|
end if;
|
end if;
|
end process csr_forward;
|
end process csr_forward;
|
|
|
evec_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value,
|
mtvec_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value,
|
wb_csr_write, wb_csr_addr, wb_csr_value, evec)
|
wb_csr_write, wb_csr_addr, wb_csr_value, mtvec)
|
begin
|
begin
|
if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_EVEC then
|
if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_MTVEC then
|
evec_forwarded <= mem_csr_value;
|
mtvec_forwarded <= mem_csr_value;
|
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_EVEC then
|
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_MTVEC then
|
evec_forwarded <= wb_csr_value;
|
mtvec_forwarded <= wb_csr_value;
|
else
|
else
|
evec_forwarded <= evec;
|
mtvec_forwarded <= mtvec;
|
end if;
|
end if;
|
end process evec_forward;
|
end process mtvec_forward;
|
|
|
|
mie_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value,
|
|
wb_csr_write, wb_csr_addr, wb_csr_value, mie)
|
|
begin
|
|
if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_MIE then
|
|
mie_forwarded <= mem_csr_value;
|
|
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_MIE then
|
|
mie_forwarded <= wb_csr_value;
|
|
else
|
|
mie_forwarded <= mie;
|
|
end if;
|
|
end process mie_forward;
|
|
|
exception_ctx_forward: process(mem_exception, wb_exception, mem_exception_context, wb_exception_context,
|
exception_ctx_forward: process(mem_exception, wb_exception, mem_exception_context, wb_exception_context,
|
exception_cause, exception_vaddr, mem_csr_write, mem_csr_addr, mem_csr_value,
|
exception_cause, exception_addr, mem_csr_write, mem_csr_addr, mem_csr_value,
|
wb_csr_write, wb_csr_addr, wb_csr_value, sr)
|
wb_csr_write, wb_csr_addr, wb_csr_value, ie_in, ie1_in)
|
begin
|
begin
|
if mem_exception = '1' then
|
if mem_exception = '1' then
|
exception_context_forwarded <= mem_exception_context;
|
exception_context_forwarded <= mem_exception_context;
|
elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_STATUS then
|
elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_MSTATUS then
|
exception_context_forwarded <= (
|
exception_context_forwarded <= (
|
status => to_csr_status_register(mem_csr_value),
|
ie => mem_csr_value(CSR_SR_IE),
|
cause => mem_exception_context.cause,
|
ie1 => mem_csr_value(CSR_SR_IE1),
|
badvaddr => mem_exception_context.badvaddr);
|
cause => exception_cause,
|
|
badaddr => exception_addr);
|
elsif wb_exception = '1' then
|
elsif wb_exception = '1' then
|
exception_context_forwarded <= wb_exception_context;
|
exception_context_forwarded <= wb_exception_context;
|
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_STATUS then
|
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_MSTATUS then
|
exception_context_forwarded <= (
|
exception_context_forwarded <= (
|
status => to_csr_status_register(wb_csr_value),
|
ie => wb_csr_value(CSR_SR_IE),
|
cause => wb_exception_context.cause,
|
ie1 => wb_csr_value(CSR_SR_IE1),
|
badvaddr => wb_exception_context.badvaddr);
|
cause => exception_cause,
|
|
badaddr => exception_addr);
|
else
|
else
|
exception_context_forwarded.status <= sr;
|
exception_context_forwarded.ie <= ie_in;
|
|
exception_context_forwarded.ie1 <= ie1_in;
|
exception_context_forwarded.cause <= exception_cause;
|
exception_context_forwarded.cause <= exception_cause;
|
exception_context_forwarded.badvaddr <= exception_vaddr;
|
exception_context_forwarded.badaddr <= exception_addr;
|
end if;
|
end if;
|
end process exception_ctx_forward;
|
end process exception_ctx_forward;
|
|
|
detect_load_hazard: process(mem_mem_op, mem_rd_addr, rs1_addr, rs2_addr,
|
detect_load_hazard: process(mem_mem_op, mem_rd_addr, rs1_addr, rs2_addr,
|
alu_x_src, alu_y_src)
|
alu_x_src, alu_y_src)
|