|
|
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
-
- use std.env.all;
-
- use work.risc_v_pkg.all;
-
-
- entity risc_v is
- port (
- reset_n_i : in std_logic;
- clk_i : in std_logic;
- -- test out
- reg_file_o : out t_reg_file;
- dmem_o : out t_dmem
- );
- end entity;
-
-
-
- architecture rtl of risc_v is
-
-
- signal s_reg_file : t_reg_file;
- signal s_dmem : t_dmem;
-
- signal s_instr : std_logic_vector(31 downto 0);
- signal s_imm : std_logic_vector(31 downto 0);
- signal s_dec_bits : std_logic_vector(10 downto 0);
- signal s_src1_value : std_logic_vector(31 downto 0);
- signal s_src2_value : std_logic_vector(31 downto 0);
- signal s_ld_data : std_logic_vector(31 downto 0);
- signal s_result : std_logic_vector(31 downto 0);
- signal s_sltu_rslt : std_logic_vector(31 downto 0);
- signal s_sltiu_rslt : std_logic_vector(31 downto 0);
-
- signal s_pc : unsigned(31 downto 0);
- signal s_next_pc : unsigned(31 downto 0);
- signal s_br_tgt_br : unsigned(31 downto 0);
- signal s_jalr_tgt_pc : unsigned(31 downto 0);
-
- signal s_taken_br : boolean;
- signal s_is_r_instr : boolean;
- signal s_is_i_instr : boolean;
- signal s_is_s_instr : boolean;
- signal s_is_b_instr : boolean;
- signal s_is_u_instr : boolean;
- signal s_is_j_instr : boolean;
- signal s_rd_valid : boolean;
- signal s_funct3_valid : boolean;
- signal s_rs1_valid : boolean;
- signal s_rs2_valid : boolean;
- signal s_funct7_valid : boolean;
- signal s_imm_valid : boolean;
- signal s_is_lui : boolean;
- signal s_is_auipc : boolean;
- signal s_is_jal : boolean;
- signal s_is_jalr : boolean;
- signal s_is_beq : boolean;
- signal s_is_bne : boolean;
- signal s_is_blt : boolean;
- signal s_is_bge : boolean;
- signal s_is_bltu : boolean;
- signal s_is_bgeu : boolean;
- signal s_is_addi : boolean;
- signal s_is_slti : boolean;
- signal s_is_sltiu : boolean;
- signal s_is_xori : boolean;
- signal s_is_ori : boolean;
- signal s_is_andi : boolean;
- signal s_is_slli : boolean;
- signal s_is_srli : boolean;
- signal s_is_srai : boolean;
- signal s_is_add : boolean;
- signal s_is_sub : boolean;
- signal s_is_sll : boolean;
- signal s_is_slt : boolean;
- signal s_is_sltu : boolean;
- signal s_is_xor : boolean;
- signal s_is_srl : boolean;
- signal s_is_sra : boolean;
- signal s_is_or : boolean;
- signal s_is_and : boolean;
- signal s_is_load : boolean;
- signal s_is_store : boolean;
- signal s_src_sgn_eq : boolean;
- signal s_imm_sgn_eq : boolean;
-
- alias a_opcode : std_logic_vector(6 downto 0) is s_instr(6 downto 0);
- alias a_rd : std_logic_vector(4 downto 0) is s_instr(11 downto 7);
- alias a_funct3 : std_logic_vector(2 downto 0) is s_instr(14 downto 12);
- alias a_rs1 : std_logic_vector(4 downto 0) is s_instr(19 downto 15);
- alias a_rs2 : std_logic_vector(4 downto 0) is s_instr(24 downto 20);
- alias a_funct7 : std_logic_vector(6 downto 0) is s_instr(31 downto 25);
-
- begin
-
-
- -- Test outs
- reg_file_o <= s_reg_file;
- dmem_o <= s_dmem;
-
- -- prog counter next state logic
- s_next_pc <= 32x"0" when not reset_n_i else
- s_br_tgt_br when s_taken_br or s_is_jal else
- s_jalr_tgt_pc when s_is_jalr else
- s_pc + 4;
-
- -- prog counter register
- process (clk_i) is
- begin
- if rising_edge(clk_i) then
- s_pc <= s_next_pc;
- end if;
- end process;
-
- -- Instruction memory
- s_instr <= c_imem(to_integer(s_pc(31 downto 2)));
-
- -- Decode
- -- Decode instruction type
- s_is_r_instr <= s_instr(6 downto 2) = "01011" or
- s_instr(6 downto 2) = "01100" or
- s_instr(6 downto 2) = "01110" or
- s_instr(6 downto 2) = "10100";
- s_is_i_instr <= std_match(s_instr(6 downto 2), "0000-") or
- std_match(s_instr(6 downto 2), "001-0") or
- s_instr(6 downto 2) = "11001";
- s_is_s_instr <= std_match(s_instr(6 downto 2), "0100-");
- s_is_b_instr <= s_instr(6 downto 2) = "11000";
- s_is_u_instr <= std_match(s_instr(6 downto 2), "0-101");
- s_is_j_instr <= s_instr(6 downto 2) = "11011";
-
- -- Extract instruction fields
- s_imm <= (31 downto 11 => s_instr(31),
- 10 downto 0 => s_instr(30 downto 20)) when s_is_i_instr else
- (31 downto 11 => s_instr(31),
- 10 downto 5 => s_instr(30 downto 25),
- 4 downto 0 => s_instr(11 downto 7)) when s_is_s_instr else
- (31 downto 12 => s_instr(31),
- 11 => s_instr(7),
- 10 downto 5 => s_instr(30 downto 25),
- 4 downto 1 => s_instr(11 downto 8),
- 0 => '0') when s_is_b_instr else
- ( 31 => s_instr(31),
- 30 downto 12 => s_instr(30 downto 12),
- 11 downto 0 => 12x"0") when s_is_u_instr else
- (31 downto 20 => s_instr(31),
- 19 downto 12 => s_instr(19 downto 12),
- 11 => s_instr(20),
- 10 downto 1 => s_instr(30 downto 21),
- 0 => '0') when s_is_j_instr else
- 32x"0";
-
- -- Calculate instruction fields valids
- s_rd_valid <= s_is_r_instr or s_is_i_instr or s_is_u_instr or s_is_j_instr;
- s_funct3_valid <= s_is_r_instr or s_is_i_instr or s_is_s_instr or s_is_b_instr;
- s_rs1_valid <= s_funct3_valid;
- s_rs2_valid <= s_is_r_instr or s_is_s_instr or s_is_b_instr;
- s_funct7_valid <= s_is_r_instr;
- s_imm_valid <= not s_is_r_instr;
-
- -- Instruction code decoding
- s_dec_bits <= (a_funct7(5), a_funct3, a_opcode);
- s_is_lui <= std_match(s_dec_bits, b"-_---_0110111");
- s_is_auipc <= std_match(s_dec_bits, b"-_---_0010111");
- s_is_jal <= std_match(s_dec_bits, b"-_---_1101111");
- s_is_jalr <= std_match(s_dec_bits, b"-_000_1100111");
- s_is_beq <= std_match(s_dec_bits, b"-_000_1100011");
- s_is_bne <= std_match(s_dec_bits, b"-_001_1100011");
- s_is_blt <= std_match(s_dec_bits, b"-_100_1100011");
- s_is_bge <= std_match(s_dec_bits, b"-_101_1100011");
- s_is_bltu <= std_match(s_dec_bits, b"-_110_1100011");
- s_is_bgeu <= std_match(s_dec_bits, b"-_111_1100011");
- s_is_addi <= std_match(s_dec_bits, b"-_000_0010011");
- s_is_slti <= std_match(s_dec_bits, b"-_010_0010011");
- s_is_sltiu <= std_match(s_dec_bits, b"-_011_0010011");
- s_is_xori <= std_match(s_dec_bits, b"-_100_0010011");
- s_is_ori <= std_match(s_dec_bits, b"-_110_0010011");
- s_is_andi <= std_match(s_dec_bits, b"-_111_0010011");
- s_is_slli <= s_dec_bits = b"0_001_0010011";
- s_is_srli <= s_dec_bits = b"0_101_0010011";
- s_is_srai <= s_dec_bits = b"1_101_0010011";
- s_is_add <= s_dec_bits = b"0_000_0110011";
- s_is_sub <= s_dec_bits = b"1_000_0110011";
- s_is_sll <= s_dec_bits = b"0_001_0110011";
- s_is_slt <= s_dec_bits = b"0_010_0110011";
- s_is_sltu <= s_dec_bits = b"0_011_0110011";
- s_is_xor <= s_dec_bits = b"0_100_0110011";
- s_is_srl <= s_dec_bits = b"0_101_0110011";
- s_is_sra <= s_dec_bits = b"1_101_0110011";
- s_is_or <= s_dec_bits = b"0_110_0110011";
- s_is_and <= s_dec_bits = b"0_111_0110011";
- -- LB, LH, LW, LBU, LHU
- s_is_load <= a_opcode = "0000011";
- -- SB, SH, SW
- s_is_store <= s_is_s_instr;
-
- -- Some subexpressions
- s_src_sgn_eq <= s_src1_value(31) = s_src2_value(31);
- s_imm_sgn_eq <= s_src1_value(31) = s_imm(31);
- -- SLTU & SLTI (set if less than, unsigned)
- s_sltu_rslt <= 31x"0" & to_std_logic(unsigned(s_src1_value) < unsigned(s_src2_value));
- s_sltiu_rslt <= 31x"0" & to_std_logic(unsigned(s_src1_value) < unsigned(s_imm));
- -- ALU
- s_result <=
- s_src1_value and s_imm when s_is_andi else
- s_src1_value or s_imm when s_is_ori else
- s_src1_value xor s_imm when s_is_xori else
- std_logic_vector(signed(s_src1_value) + signed(s_imm)) when s_is_addi or
- s_is_load or
- s_is_store else
- shift_left(s_src1_value, s_imm(5 downto 0)) when s_is_slli else
- shift_right(s_src1_value, s_imm(5 downto 0)) when s_is_srli else
- s_src1_value and s_src2_value when s_is_and else
- s_src1_value or s_src2_value when s_is_or else
- s_src1_value xor s_src2_value when s_is_xor else
- std_logic_vector(signed(s_src1_value) + signed(s_src2_value)) when s_is_add else
- std_logic_vector(signed(s_src1_value) - signed(s_src2_value)) when s_is_sub else
- shift_left(s_src1_value, s_src2_value(4 downto 0)) when s_is_sll else
- shift_right(s_src1_value, s_src2_value(4 downto 0)) when s_is_srl else
- s_sltu_rslt when s_is_sltu else
- s_sltiu_rslt when s_is_sltiu else
- s_imm(31 downto 12) & 12x"0" when s_is_lui else
- std_logic_vector(s_pc + unsigned(s_imm)) when s_is_auipc else
- std_logic_vector(s_pc + 4) when s_is_jal or
- s_is_jalr else
- s_sltu_rslt when s_is_slt and
- s_src_sgn_eq else
- 31x"0" & s_src1_value(31) when s_is_slt else
- s_sltiu_rslt when s_is_slti and
- s_imm_sgn_eq else
- 31x"0" & s_src1_value(31) when s_is_slti else
- shift_arith_right(s_src1_value, s_src2_value(4 downto 0)) when s_is_sra else
- shift_arith_right(s_src1_value, s_imm(4 downto 0)) when s_is_srai else
- 32x"0";
-
- -- Branch logic
- s_taken_br <= s_src1_value = s_src2_value when s_is_beq else
- s_src1_value /= s_src2_value when s_is_bne else
- signed(s_src1_value) < signed(s_src2_value) when s_is_blt else
- signed(s_src1_value) >= signed(s_src2_value) when s_is_bge else
- unsigned(s_src1_value) < unsigned(s_src2_value) when s_is_bltu else
- unsigned(s_src1_value) >= unsigned(s_src2_value) when s_is_bgeu else
- false;
- s_br_tgt_br <= s_pc + unsigned(s_imm);
- s_jalr_tgt_pc <= unsigned(s_src1_value) + unsigned(s_imm);
-
- -- Register file
- process (clk_i) is
- variable v_value : std_logic_vector(31 downto 0);
- begin
- if rising_edge(clk_i) then
- if reset_n_i = '0' then
- s_reg_file <= init_reg_file;
- elsif s_rd_valid and a_rd /= 5x"0" then
- v_value := std_logic_vector(s_ld_data) when s_is_load else s_result;
- s_reg_file(to_integer(unsigned(a_rd))) <= v_value;
- end if;
- end if;
- end process;
-
- s_src1_value <= s_reg_file(to_integer(unsigned(a_rs1))) when s_rs1_valid else
- (others => '0');
- s_src2_value <= s_reg_file(to_integer(unsigned(a_rs2))) when s_rs2_valid else
- (others => '0');
-
- -- Data memory
- process (clk_i) is
- begin
- if rising_edge(clk_i) then
- if reset_n_i = '0' then
- s_dmem <= init_dmem;
- elsif s_is_store then
- s_dmem(to_integer(unsigned(s_result(6 downto 2)))) <= std_logic_vector(s_src2_value);
- end if;
- end if;
- end process;
-
- s_ld_data <= s_dmem(to_integer(unsigned(s_result(6 downto 2)))) when s_is_load else
- (others => '0');
-
-
- end architecture rtl;
|