CSR Unit implemented with all CSR operational modify operations (write, set, clear). Not all CSRs are supported as yet, but cycles, instret and some of the machine identifiers are. Also two R/W locations at 0x400 and 0x401 for testing.

This commit is contained in:
Colin Riley 2018-11-16 22:39:57 +00:00
parent cc388e3a90
commit 25411fd194
4 changed files with 114 additions and 66 deletions

View file

@ -228,12 +228,16 @@ constant CSR_ADDR_ACCESS_READONLY: std_logic_vector(1 downto 0):= "11";
-- 11 - clear bits
-- 4 - immediate or register
constant CSR_OP_BITS_WRITTEN: integer := 0;
constant CSR_OP_BITS_READ: integer := 1;
constant CSR_OP_BITS_READ: integer := 0;
constant CSR_OP_BITS_WRITTEN: integer := 1;
constant CSR_OP_BITS_OPA: integer := 2;
constant CSR_OP_BITS_OPB: integer := 3;
constant CSR_OP_BITS_IMM: integer := 4;
constant CSR_MAINOP_WR: std_logic_vector(1 downto 0) := "01";
constant CSR_MAINOP_SET: std_logic_vector(1 downto 0) := "10";
constant CSR_MAINOP_CLEAR: std_logic_vector(1 downto 0) := "11";
constant CSR_OP_WR: std_logic_vector(4 downto 0) := "00100";
constant CSR_OP_W: std_logic_vector(4 downto 0) := "00101";
constant CSR_OP_R: std_logic_vector(4 downto 0) := "00110";

View file

@ -218,6 +218,7 @@ architecture Behavioral of core is
signal reg_we: std_logic := '0';
signal registerWriteData : std_logic_vector(XLENM1 downto 0) := (others=>'0');
signal alu_or_csr_output : std_logic_vector(XLENM1 downto 0) := (others=>'0');
signal en_fetch : std_logic := '0';
signal en_decode : std_logic := '0';
@ -390,8 +391,8 @@ begin
-- These are the pipeline stage enable bits
en_fetch <= state(0);
en_decode <= state(1);
en_alu <= '0' when aluop = OPCODE_SYSTEM else state(3);
en_csru <= state(3) when aluop = OPCODE_SYSTEM else '0';
en_alu <= '0' when aluop(6 downto 2) = OPCODE_SYSTEM else state(3);
en_csru <= state(3) when aluop(6 downto 2) = OPCODE_SYSTEM else '0';
en_memory <= state(4);
en_regwrite <= state(5);
en_stall <= state(6);
@ -405,8 +406,11 @@ begin
-- The input PC is just always the branch target output from ALU
in_pc <= branchTarget;
-- input data from the register file, or use immediate if the OP specifies it
csru_dataIn <= dataIMM when csru_csrOp(CSR_OP_BITS_IMM) = '1' else dataA;
-- The debug output just allows some internal state to be visible outside the core black box
O_DBG <= "000" & memctl_dataReady & "000" & MEM_I_dataReady & "0" & state & registerWriteData(15 downto 0);
--O_DBG <= "000" & memctl_dataReady & "000" & MEM_I_dataReady & X"0000"&"0" & state;-- & registerWriteData(15 downto 0);
-- Below statements are for memory interface use.
memctl_address <= dataResult when en_memory = '1' else PC;
@ -417,8 +421,8 @@ begin
memctl_size <= memOp(1 downto 0);
memctl_signExtend <= memOp(2);
-- This chooses to write registers with memory data or ALU data
registerWriteData <= memctl_out_data when memOp(4 downto 3) = "10" else dataResult;
-- This chooses to write registers with memory data or ALU/csr data
registerWriteData <= memctl_out_data when memOp(4 downto 3) = "10" else csru_dataOut when aluop(6 downto 2) = OPCODE_SYSTEM else dataResult;
-- The instructions are delivered from memctl
instruction <= memctl_out_data;

View file

@ -3,7 +3,7 @@
-- Description: CSR unit RV32I
--
----------------------------------------------------------------------------------
-- Copyright 2016 Colin Riley
-- Copyright 2018 Colin Riley
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
@ -59,6 +59,10 @@ constant CSR_ADDR_CYCLEH: STD_LOGIC_VECTOR (11 downto 0) := X"C80";
constant CSR_ADDR_TIMEH: STD_LOGIC_VECTOR (11 downto 0) := X"C81";
constant CSR_ADDR_INSTRETH: STD_LOGIC_VECTOR (11 downto 0) := X"C82";
constant CSR_ADDR_TEST_400: STD_LOGIC_VECTOR (11 downto 0) := X"400";
constant CSR_ADDR_TEST_401: STD_LOGIC_VECTOR (11 downto 0) := X"401";
constant CSR_ADDR_MSTATUS: STD_LOGIC_VECTOR (11 downto 0) := X"300";
constant CSR_ADDR_MISA: STD_LOGIC_VECTOR (11 downto 0) := X"301";
constant CSR_ADDR_MEDELEG: STD_LOGIC_VECTOR (11 downto 0) := X"302";
@ -91,10 +95,20 @@ signal csr_instret: STD_LOGIC_VECTOR(63 downto 0) := (others => '0');
signal csr_status : STD_LOGIC_VECTOR (XLENM1 downto 0) := (others => '0');
signal csr_tvec : STD_LOGIC_VECTOR (XLENM1 downto 0) := (others => '0');
signal curr_csr_value: STD_LOGIC_VECTOR(XLENM1 downto 0) := (others=> '0');
signal next_csr_value: STD_LOGIC_VECTOR(XLENM1 downto 0) := (others=> '0');
signal test0_CSR: STD_LOGIC_VECTOR(XLENM1 downto 0) := X"FEFbbEF0";
signal test1_CSR: STD_LOGIC_VECTOR(XLENM1 downto 0) := X"FEFbbEF1";
signal csr_op: STD_LOGIC_VECTOR(4 downto 0) := (others=>'0');
signal opState: integer := 0;
begin
O_csr_status <= csr_status;
O_csr_tvec <= csr_tvec;
O_dataOut <= curr_csr_value;
cycles: process (I_clk)
begin
@ -120,45 +134,89 @@ begin
end if;
end process;
-- Read data is available next cycle, with an additional cycle before another op can be processed
-- Write to CSR occurs 3 cycles later.
-- cycle 1: read of existing csr available
-- cycle 2: update value calculates (whole write, set/clear bit read-modify-write)
-- cycle 3: actual write to csr occurs.
datamain: process (I_clk, I_en)
begin
if rising_edge(I_clk) and I_en = '1' then
case I_csrAddr is
when CSR_ADDR_MVENDORID =>
O_dataOut <= X"00000000"; -- JEDEC non-commercial
when CSR_ADDR_MARCHID =>
O_dataOut <= X"00000000";
when CSR_ADDR_MIMPID =>
O_dataOut <= X"52505530"; -- "RPU0"
when CSR_ADDR_MHARDID =>
O_dataOut <= X"00000000";
when CSR_ADDR_MISA =>
O_dataOut <= X"40000080"; -- XLEN 32, RV32I
when CSR_ADDR_CYCLE =>
O_dataOut <= csr_cycles(31 downto 0);
when CSR_ADDR_CYCLEH =>
O_dataOut <= csr_cycles(63 downto 32);
when CSR_ADDR_INSTRET =>
O_dataOut <= csr_cycles(31 downto 0);
when CSR_ADDR_INSTRETH =>
O_dataOut <= csr_cycles(63 downto 32);
when CSR_ADDR_MCYCLE =>
O_dataOut <= csr_cycles(31 downto 0);
when CSR_ADDR_MCYCLEH =>
O_dataOut <= csr_cycles(63 downto 32);
when CSR_ADDR_MINSTRET =>
O_dataOut <= csr_cycles(31 downto 0);
when CSR_ADDR_MINSTRETH =>
O_dataOut <= csr_cycles(63 downto 32);
when others =>
end case;
end if;
if rising_edge(I_clk) then
if I_en = '1' and opState = 0 then
csr_op <= I_csrOp;
case I_csrAddr is
when CSR_ADDR_MVENDORID =>
curr_csr_value <= X"00000000"; -- JEDEC non-commercial
when CSR_ADDR_MARCHID =>
curr_csr_value <= X"00000000";
when CSR_ADDR_MIMPID =>
curr_csr_value <= X"52505530"; -- "RPU0"
when CSR_ADDR_MHARDID =>
curr_csr_value <= X"00000000";
when CSR_ADDR_MISA =>
curr_csr_value <= X"40000080"; -- XLEN 32, RV32I
when CSR_ADDR_CYCLE =>
curr_csr_value <= csr_cycles(31 downto 0);
when CSR_ADDR_CYCLEH =>
curr_csr_value <= csr_cycles(63 downto 32);
when CSR_ADDR_INSTRET =>
curr_csr_value <= csr_instret(31 downto 0);
when CSR_ADDR_INSTRETH =>
curr_csr_value <= csr_instret(63 downto 32);
when CSR_ADDR_MCYCLE =>
curr_csr_value <= csr_cycles(31 downto 0);
when CSR_ADDR_MCYCLEH =>
curr_csr_value <= csr_cycles(63 downto 32);
when CSR_ADDR_MINSTRET =>
curr_csr_value <= csr_instret(31 downto 0);
when CSR_ADDR_MINSTRETH =>
curr_csr_value <= csr_instret(63 downto 32);
when CSR_ADDR_TEST_400 =>
curr_csr_value <= test0_CSR;
when CSR_ADDR_TEST_401 =>
curr_csr_value <= test1_CSR;
when others =>
-- raise exception for unsupported CSR
end case;
opState <= 1;
elsif opState = 1 then
-- update stage for sets, clears and writes
case csr_op(3 downto 2) is
when CSR_MAINOP_WR =>
next_csr_value <= I_dataIn;
when CSR_MAINOP_SET =>
next_csr_value <= curr_csr_value or I_dataIn;
when CSR_MAINOP_CLEAR =>
next_csr_value <= curr_csr_value and (not I_dataIn);
when others =>
end case;
if I_csrOp(CSR_OP_BITS_WRITTEN) = '1' then
opState <= 2;
else
opState <= 0;
end if;
elsif opState = 2 then
-- write stage
opState <= 0;
case I_csrAddr is
when CSR_ADDR_TEST_400 =>
test0_CSR <= next_csr_value;
when CSR_ADDR_TEST_401 =>
test1_CSR <= next_csr_value;
when others =>
end case;
end if;
end if;
end process;
end Behavioral;

View file

@ -146,7 +146,9 @@ begin
-- is there a destination? if not, CSR is not read
if I_dataInst(RD_START downto RD_END) = "00000" then
O_csrOP(0) <= '0';
O_regDwe <= '0';
else
O_regDwe <= '1';
O_csrOP(0) <= '1';
end if;
@ -158,27 +160,7 @@ begin
end if;
O_csrOp(4 downto 2) <= I_dataInst(FUNCT3_START downto FUNCT3_END);
-- -- operation
-- case '0' & I_dataInst((FUNCT3_START+1) downto FUNCT3_END) is
-- when F3_SYSTEM_CSRRW =>
-- O_csrOP(3 downto 2) <= "00";
--
-- when F3_SYSTEM_CSRRS =>
-- O_csrOP(3 downto 2) <= "10";
--
-- when F3_SYSTEM_CSRRC=>
-- O_csrOP(3 downto 2) <= "11";
--
-- when others =>
-- end case;
--
-- -- immediate or reg source
-- if I_dataInst(FUNCT3_START) = '1' then
-- O_csrOP(4) <= '1';
-- else
-- O_csrOP(4) <= '0';
-- end if;
end if;
when others =>
O_memOp <= "00000";