mirror of
https://github.com/Domipheus/RPU.git
synced 2025-04-16 01:54:46 -04:00
Initial commit. Tested on ArtyS7-RPU-SoC and passes SD bootloader and DDR3 memory testing.
This commit is contained in:
parent
84a652b41c
commit
439781c194
12 changed files with 1526 additions and 0 deletions
|
@ -1,2 +1,10 @@
|
|||
# RPU
|
||||
Basic RISC-V CPU implementation in VHDL.
|
||||
|
||||
This is a RV32I ISA CPU implementation, based off of my TPU CPU design. It is very simple, is missing several features, but can run rv32i-compiled GCC toolchain binaries at over 200MHz on a Digilent Arty S7-50 board, built with Xilinx Spartan 7 tools.
|
||||
|
||||
Implementation detail is written about via blogs available at http://labs.domipheus.com/blog/designing-a-cpu-in-vhdl-part-15-introducing-rpu/
|
||||
|
||||
The tests in the repo are incredibly old and basic, and included only as a baseline to help. They will be expanded upon in time.
|
||||
|
||||
Please let me know if you are using any of the RPU design in your own projects! I am contactable on twitter @domipheus.
|
||||
|
|
BIN
rpu_core_diagram.png
Normal file
BIN
rpu_core_diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
155
tests/tb_unit_alu_RV32I_01.vhd
Normal file
155
tests/tb_unit_alu_RV32I_01.vhd
Normal file
|
@ -0,0 +1,155 @@
|
|||
--------------------------------------------------------------------------------
|
||||
-- Company:
|
||||
-- Engineer:
|
||||
--
|
||||
-- Create Date: 16:43:32 12/10/2016
|
||||
-- Design Name:
|
||||
-- Module Name: C:/Users/colin/Desktop/riscy/ise/tb_unit_alu_RV32I_01.vhd
|
||||
-- Project Name: riscv32_v1
|
||||
-- Target Device:
|
||||
-- Tool versions:
|
||||
-- Description:
|
||||
--
|
||||
-- VHDL Test Bench Created by ISE for module: alu_RV32I
|
||||
--
|
||||
-- Dependencies:
|
||||
--
|
||||
-- Revision:
|
||||
-- Revision 0.01 - File Created
|
||||
-- Additional Comments:
|
||||
--
|
||||
-- Notes:
|
||||
-- This testbench has been automatically generated using types std_logic and
|
||||
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
|
||||
-- that these types always be used for the top-level I/O of a design in order
|
||||
-- to guarantee that the testbench will bind correctly to the post-implementation
|
||||
-- simulation model.
|
||||
--------------------------------------------------------------------------------
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.ALL;
|
||||
|
||||
use work.constants.all;
|
||||
|
||||
-- Uncomment the following library declaration if using
|
||||
-- arithmetic functions with Signed or Unsigned values
|
||||
--USE ieee.numeric_std.ALL;
|
||||
|
||||
ENTITY tb_unit_alu_RV32I_01 IS
|
||||
END tb_unit_alu_RV32I_01;
|
||||
|
||||
ARCHITECTURE behavior OF tb_unit_alu_RV32I_01 IS
|
||||
|
||||
-- Component Declaration for the Unit Under Test (UUT)
|
||||
|
||||
COMPONENT alu_RV32I
|
||||
PORT(
|
||||
I_clk : IN std_logic;
|
||||
I_en : IN std_logic;
|
||||
I_dataA : IN std_logic_vector(31 downto 0);
|
||||
I_dataB : IN std_logic_vector(31 downto 0);
|
||||
I_dataDwe : IN std_logic;
|
||||
I_aluop : IN std_logic_vector(4 downto 0);
|
||||
I_aluFunc : IN std_logic_vector(15 downto 0);
|
||||
I_PC : IN std_logic_vector(31 downto 0);
|
||||
I_dataIMM : IN std_logic_vector(31 downto 0);
|
||||
O_dataResult : OUT std_logic_vector(31 downto 0);
|
||||
O_branchTarget : OUT std_logic_vector(31 downto 0);
|
||||
O_dataWriteReg : OUT std_logic;
|
||||
O_shouldBranch : OUT std_logic
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
|
||||
--Inputs
|
||||
signal I_clk : std_logic := '0';
|
||||
signal I_en : std_logic := '0';
|
||||
signal I_dataA : std_logic_vector(31 downto 0) := (others => '0');
|
||||
signal I_dataB : std_logic_vector(31 downto 0) := (others => '0');
|
||||
signal I_dataDwe : std_logic := '0';
|
||||
signal I_aluop : std_logic_vector(4 downto 0) := (others => '0');
|
||||
signal I_aluFunc : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal I_PC : std_logic_vector(31 downto 0) := (others => '0');
|
||||
signal I_dataIMM : std_logic_vector(31 downto 0) := (others => '0');
|
||||
|
||||
--Outputs
|
||||
signal O_dataResult : std_logic_vector(31 downto 0);
|
||||
signal O_branchTarget : std_logic_vector(31 downto 0);
|
||||
signal O_dataWriteReg : std_logic := '0';
|
||||
signal O_shouldBranch : std_logic := '0';
|
||||
|
||||
-- Clock period definitions
|
||||
constant I_clk_period : time := 10 ns;
|
||||
|
||||
BEGIN
|
||||
|
||||
-- Instantiate the Unit Under Test (UUT)
|
||||
uut: alu_RV32I PORT MAP (
|
||||
I_clk => I_clk,
|
||||
I_en => I_en,
|
||||
I_dataA => I_dataA,
|
||||
I_dataB => I_dataB,
|
||||
I_dataDwe => I_dataDwe,
|
||||
I_aluop => I_aluop,
|
||||
I_aluFunc => I_aluFunc,
|
||||
I_PC => I_PC,
|
||||
I_dataIMM => I_dataIMM,
|
||||
O_dataResult => O_dataResult,
|
||||
O_branchTarget => O_branchTarget,
|
||||
O_dataWriteReg => O_dataWriteReg,
|
||||
O_shouldBranch => O_shouldBranch
|
||||
);
|
||||
|
||||
-- Clock process definitions
|
||||
I_clk_process :process
|
||||
begin
|
||||
I_clk <= '0';
|
||||
wait for I_clk_period/2;
|
||||
I_clk <= '1';
|
||||
wait for I_clk_period/2;
|
||||
end process;
|
||||
|
||||
|
||||
-- Stimulus process
|
||||
stim_proc: process
|
||||
begin
|
||||
-- hold reset state for 100 ns.
|
||||
wait for 100 ns;
|
||||
|
||||
wait for I_clk_period*10;
|
||||
-- insert stimulus here
|
||||
|
||||
I_dataA <= X"00001000";
|
||||
I_dataB <= X"01A01001";
|
||||
I_aluOp <= OPCODE_OP;
|
||||
I_aluFunc <= "000000" & F7_OP_ADD & F3_OP_ADD;
|
||||
I_dataImm <= X"00000000";
|
||||
I_PC <= X"A0000000";
|
||||
I_dataDwe <= '1';
|
||||
I_en <= '1';
|
||||
|
||||
wait for I_clk_period*2;
|
||||
|
||||
I_dataA <= X"00000001";
|
||||
I_dataB <= X"00000006";
|
||||
I_aluOp <= OPCODE_OP;
|
||||
I_aluFunc <= "000000" & F7_OP_ADD & F3_OP_ADD;
|
||||
I_dataImm <= X"00000000";
|
||||
I_PC <= X"A0000004";
|
||||
I_dataDwe <= '1';
|
||||
I_en <= '1';
|
||||
|
||||
wait for I_clk_period*2;
|
||||
|
||||
I_dataA <= X"00346A00";
|
||||
I_dataB <= X"120000B6";
|
||||
I_aluOp <= OPCODE_OP;
|
||||
I_aluFunc <= "000000" & F7_OP_OR & F3_OP_OR;
|
||||
I_dataImm <= X"00000000";
|
||||
I_PC <= X"A0000008";
|
||||
I_dataDwe <= '1';
|
||||
I_en <= '1';
|
||||
|
||||
wait;
|
||||
end process;
|
||||
|
||||
END;
|
136
tests/tb_unit_decoder_RV32_01.vhd
Normal file
136
tests/tb_unit_decoder_RV32_01.vhd
Normal file
|
@ -0,0 +1,136 @@
|
|||
--------------------------------------------------------------------------------
|
||||
-- Company:
|
||||
-- Engineer:
|
||||
--
|
||||
-- Create Date: 22:43:26 12/08/2016
|
||||
-- Design Name:
|
||||
-- Module Name: C:/Users/colin/Desktop/riscy/ise/tb_unit_decoder_RV32_01.vhd
|
||||
-- Project Name: riscv32_v1
|
||||
-- Target Device:
|
||||
-- Tool versions:
|
||||
-- Description:
|
||||
--
|
||||
-- VHDL Test Bench Created by ISE for module: decoder_RV32
|
||||
--
|
||||
-- Dependencies:
|
||||
--
|
||||
-- Revision:
|
||||
-- Revision 0.01 - File Created
|
||||
-- Additional Comments:
|
||||
--
|
||||
-- Notes:
|
||||
-- This testbench has been automatically generated using types std_logic and
|
||||
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
|
||||
-- that these types always be used for the top-level I/O of a design in order
|
||||
-- to guarantee that the testbench will bind correctly to the post-implementation
|
||||
-- simulation model.
|
||||
--------------------------------------------------------------------------------
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if using
|
||||
-- arithmetic functions with Signed or Unsigned values
|
||||
--USE ieee.numeric_std.ALL;
|
||||
|
||||
ENTITY tb_unit_decoder_RV32_01 IS
|
||||
END tb_unit_decoder_RV32_01;
|
||||
|
||||
ARCHITECTURE behavior OF tb_unit_decoder_RV32_01 IS
|
||||
|
||||
-- Component Declaration for the Unit Under Test (UUT)
|
||||
|
||||
COMPONENT decoder_RV32
|
||||
PORT(
|
||||
I_clk : IN std_logic;
|
||||
I_en : IN std_logic;
|
||||
I_dataInst : IN std_logic_vector(31 downto 0);
|
||||
O_selRS1 : OUT std_logic_vector(4 downto 0);
|
||||
O_selRS2 : OUT std_logic_vector(4 downto 0);
|
||||
O_selD : OUT std_logic_vector(4 downto 0);
|
||||
O_dataIMM : OUT std_logic_vector(31 downto 0);
|
||||
O_regDwe : OUT std_logic;
|
||||
O_aluOp : OUT std_logic_vector(6 downto 0);
|
||||
O_aluFunc : OUT std_logic_vector(15 downto 0); -- ALU function
|
||||
O_memOp : out STD_LOGIC_VECTOR(4 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
|
||||
--Inputs
|
||||
signal I_clk : std_logic := '0';
|
||||
signal I_en : std_logic := '0';
|
||||
signal I_dataInst : std_logic_vector(31 downto 0) := (others => '0');
|
||||
|
||||
--Outputs
|
||||
signal O_selRS1 : std_logic_vector(4 downto 0);
|
||||
signal O_selRS2 : std_logic_vector(4 downto 0);
|
||||
signal O_selD : std_logic_vector(4 downto 0);
|
||||
signal O_dataIMM : std_logic_vector(31 downto 0);
|
||||
signal O_regDwe : std_logic;
|
||||
signal O_aluOp : std_logic_vector(6 downto 0);
|
||||
signal O_aluFunc : std_logic_vector(15 downto 0);
|
||||
signal O_memOp : STD_LOGIC_VECTOR(4 downto 0);
|
||||
|
||||
-- Clock period definitions
|
||||
constant I_clk_period : time := 10 ns;
|
||||
|
||||
BEGIN
|
||||
|
||||
-- Instantiate the Unit Under Test (UUT)
|
||||
uut: decoder_RV32 PORT MAP (
|
||||
I_clk => I_clk,
|
||||
I_en => I_en,
|
||||
I_dataInst => I_dataInst,
|
||||
O_selRS1 => O_selRS1,
|
||||
O_selRS2 => O_selRS2,
|
||||
O_selD => O_selD,
|
||||
O_dataIMM => O_dataIMM,
|
||||
O_regDwe => O_regDwe,
|
||||
O_aluOp => O_aluOp,
|
||||
O_aluFunc => O_aluFunc,
|
||||
O_memOp => O_memOp
|
||||
);
|
||||
|
||||
-- Clock process definitions
|
||||
I_clk_process :process
|
||||
begin
|
||||
I_clk <= '0';
|
||||
wait for I_clk_period/2;
|
||||
I_clk <= '1';
|
||||
wait for I_clk_period/2;
|
||||
end process;
|
||||
|
||||
|
||||
-- Stimulus process
|
||||
stim_proc: process
|
||||
begin
|
||||
-- hold reset state for 100 ns.
|
||||
wait for 100 ns;
|
||||
|
||||
wait for I_clk_period*10;
|
||||
|
||||
-- insert stimulus here
|
||||
I_dataInst <= "0000000" & "00001" & "00010" & "000" & "01001" & "0110011";
|
||||
I_en <= '1';
|
||||
|
||||
wait for I_clk_period*2;
|
||||
|
||||
I_dataInst <= "000000000001" & "00010" & "000" & "01001" & "0010011";
|
||||
I_en <= '1';
|
||||
|
||||
wait for I_clk_period*2;
|
||||
|
||||
I_dataInst <= "100000000001" & "00010" & "000" & "01001" & "0010011";
|
||||
I_en <= '1';
|
||||
|
||||
wait for I_clk_period*2;
|
||||
|
||||
I_dataInst <= "100001000001" & "00000" & "010" & "00001" & "0000011";
|
||||
I_en <= '1';
|
||||
|
||||
wait for I_clk_period*2;
|
||||
|
||||
wait;
|
||||
end process;
|
||||
|
||||
END;
|
158
vhdl/constants.vhd
Normal file
158
vhdl/constants.vhd
Normal file
|
@ -0,0 +1,158 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RISC-V CPU
|
||||
-- Description: Constants for instruction forms, opcodes, conditional flags, etc.
|
||||
--
|
||||
-- Revision: 1
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.all;
|
||||
|
||||
package constants is
|
||||
|
||||
|
||||
constant XLEN: integer := 32;
|
||||
constant XLENM1: integer := XLEN - 1;
|
||||
|
||||
constant XLEN32: integer:= 32;
|
||||
constant XLEN32M1: integer:= XLEN32 -1;
|
||||
|
||||
|
||||
constant BWIDTH: integer:= 32;
|
||||
constant BWIDTHM1: integer:= BWIDTH -1;
|
||||
|
||||
|
||||
constant ADDR_RESET: std_logic_vector(XLEN32M1 downto 0) := X"00000000";
|
||||
constant ADDR_INTVEC: std_logic_vector(XLEN32M1 downto 0) := X"00000100";
|
||||
|
||||
|
||||
-- PC unit opcodes
|
||||
constant PCU_OP_NOP: std_logic_vector(1 downto 0):= "00";
|
||||
constant PCU_OP_INC: std_logic_vector(1 downto 0):= "01";
|
||||
constant PCU_OP_ASSIGN: std_logic_vector(1 downto 0):= "10";
|
||||
constant PCU_OP_RESET: std_logic_vector(1 downto 0):= "11";
|
||||
|
||||
-- Instruction Form Offsets
|
||||
constant OPCODE_START: integer := 6;
|
||||
constant OPCODE_END: integer := 0;
|
||||
constant OPCODE_END_2: integer := 2;
|
||||
|
||||
constant RD_START: integer := 11;
|
||||
constant RD_END: integer := 7;
|
||||
|
||||
constant FUNCT3_START: integer := 14;
|
||||
constant FUNCT3_END: integer := 12;
|
||||
|
||||
constant R1_START: integer := 19;
|
||||
constant R1_END: integer := 15;
|
||||
|
||||
constant R2_START: integer := 24;
|
||||
constant R2_END: integer := 20;
|
||||
|
||||
constant FUNCT7_START: integer := 31;
|
||||
constant FUNCT7_END: integer := 25;
|
||||
|
||||
constant IMM_I_START: integer := 31;
|
||||
constant IMM_I_END: integer := 20;
|
||||
|
||||
constant IMM_U_START: integer := 31;
|
||||
constant IMM_U_END: integer := 12;
|
||||
|
||||
constant IMM_S_A_START: integer := 31;
|
||||
constant IMM_S_A_END: integer := 25;
|
||||
|
||||
constant IMM_S_B_START: integer := 11;
|
||||
constant IMM_S_B_END: integer := 7;
|
||||
|
||||
-- Opcodes
|
||||
constant OPCODE_LOAD: std_logic_vector(4 downto 0) := "00000";
|
||||
constant OPCODE_STORE: std_logic_vector(4 downto 0) := "01000";
|
||||
constant OPCODE_MADD: std_logic_vector(4 downto 0) := "10000";
|
||||
constant OPCODE_BRANCH: std_logic_vector(4 downto 0) := "11000";
|
||||
constant OPCODE_JALR: std_logic_vector(4 downto 0) := "11001";
|
||||
constant OPCODE_JAL: std_logic_vector(4 downto 0) := "11011";
|
||||
constant OPCODE_SYSTEM: std_logic_vector(4 downto 0) := "11100";
|
||||
constant OPCODE_OP: std_logic_vector(4 downto 0) := "01100";
|
||||
constant OPCODE_OPIMM: std_logic_vector(4 downto 0) := "00100";
|
||||
constant OPCODE_MISCMEM: std_logic_vector(4 downto 0) := "00011";
|
||||
constant OPCODE_AUIPC: std_logic_vector(4 downto 0) := "00101";
|
||||
constant OPCODE_LUI: std_logic_vector(4 downto 0) := "01101";
|
||||
|
||||
-- Flags
|
||||
constant F3_BRANCH_BEQ: std_logic_vector(2 downto 0) := "000";
|
||||
constant F3_BRANCH_BNE: std_logic_vector(2 downto 0) := "001";
|
||||
constant F3_BRANCH_BLT: std_logic_vector(2 downto 0) := "100";
|
||||
constant F3_BRANCH_BGE: std_logic_vector(2 downto 0) := "101";
|
||||
constant F3_BRANCH_BLTU: std_logic_vector(2 downto 0) := "110";
|
||||
constant F3_BRANCH_BGEU: std_logic_vector(2 downto 0) := "111";
|
||||
|
||||
constant F3_JALR: std_logic_vector(2 downto 0) := "000";
|
||||
|
||||
constant F3_LOAD_LB: std_logic_vector(2 downto 0) := "000";
|
||||
constant F3_LOAD_LH: std_logic_vector(2 downto 0) := "001";
|
||||
constant F3_LOAD_LW: std_logic_vector(2 downto 0) := "010";
|
||||
constant F3_LOAD_LBU: std_logic_vector(2 downto 0) := "100";
|
||||
constant F3_LOAD_LHU: std_logic_vector(2 downto 0) := "101";
|
||||
|
||||
constant F2_MEM_LS_SIZE_B: std_logic_vector(1 downto 0) := "00";
|
||||
constant F2_MEM_LS_SIZE_H: std_logic_vector(1 downto 0) := "01";
|
||||
constant F2_MEM_LS_SIZE_W: std_logic_vector(1 downto 0) := "10";
|
||||
|
||||
constant F3_STORE_SB: std_logic_vector(2 downto 0) := "000";
|
||||
constant F3_STORE_SH: std_logic_vector(2 downto 0) := "001";
|
||||
constant F3_STORE_SW: std_logic_vector(2 downto 0) := "010";
|
||||
|
||||
constant F3_OPIMM_ADDI: std_logic_vector(2 downto 0) := "000";
|
||||
constant F3_OPIMM_SLTI: std_logic_vector(2 downto 0) := "010";
|
||||
constant F3_OPIMM_SLTIU: std_logic_vector(2 downto 0) := "011";
|
||||
constant F3_OPIMM_XORI: std_logic_vector(2 downto 0) := "100";
|
||||
constant F3_OPIMM_ORI: std_logic_vector(2 downto 0) := "110";
|
||||
constant F3_OPIMM_ANDI: std_logic_vector(2 downto 0) := "111";
|
||||
|
||||
constant F3_OPIMM_SLLI: std_logic_vector(2 downto 0) := "001";
|
||||
constant F7_OPIMM_SLLI: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OPIMM_SRLI: std_logic_vector(2 downto 0) := "101";
|
||||
constant F7_OPIMM_SRLI: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OPIMM_SRAI: std_logic_vector(2 downto 0) := "101";
|
||||
constant F7_OPIMM_SRAI: std_logic_vector(6 downto 0) := "0100000";
|
||||
|
||||
constant F3_OP_ADD: std_logic_vector(2 downto 0) := "000";
|
||||
constant F7_OP_ADD: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OP_SUB: std_logic_vector(2 downto 0) := "000";
|
||||
constant F7_OP_SUB: std_logic_vector(6 downto 0) := "0100000";
|
||||
constant F3_OP_SLL: std_logic_vector(2 downto 0) := "001";
|
||||
constant F7_OP_SLL: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OP_SLT: std_logic_vector(2 downto 0) := "010";
|
||||
constant F7_OP_SLT: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OP_SLTU: std_logic_vector(2 downto 0) := "011";
|
||||
constant F7_OP_SLTU: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OP_XOR: std_logic_vector(2 downto 0) := "100";
|
||||
constant F7_OP_XOR: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OP_SRL: std_logic_vector(2 downto 0) := "101";
|
||||
constant F7_OP_SRL: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OP_SRA: std_logic_vector(2 downto 0) := "101";
|
||||
constant F7_OP_SRA: std_logic_vector(6 downto 0) := "0100000";
|
||||
constant F3_OP_OR: std_logic_vector(2 downto 0) := "110";
|
||||
constant F7_OP_OR: std_logic_vector(6 downto 0) := "0000000";
|
||||
constant F3_OP_AND: std_logic_vector(2 downto 0) := "111";
|
||||
constant F7_OP_AND: std_logic_vector(6 downto 0) := "0000000";
|
||||
|
||||
constant F3_MISCMEM_FENCE: std_logic_vector(2 downto 0) := "000";
|
||||
constant F3_MISCMEM_FENCEI: std_logic_vector(2 downto 0) := "001";
|
||||
|
||||
constant F3_SYSTEM_ECALL: std_logic_vector(2 downto 0) := "000";
|
||||
constant IMM_I_SYSTEM_ECALL: std_logic_vector(11 downto 0) := "000000000000";
|
||||
constant F3_SYSTEM_EBREAK: std_logic_vector(2 downto 0) := "000";
|
||||
constant IMM_I_SYSTEM_EBREAK: std_logic_vector(11 downto 0) := "000000000001";
|
||||
constant F3_SYSTEM_CSRRW: std_logic_vector(2 downto 0) := "001";
|
||||
constant F3_SYSTEM_CSRRS: std_logic_vector(2 downto 0) := "010";
|
||||
constant F3_SYSTEM_CSRRC: std_logic_vector(2 downto 0) := "011";
|
||||
constant F3_SYSTEM_CSRRWI: std_logic_vector(2 downto 0) := "101";
|
||||
constant F3_SYSTEM_CSRRSI: std_logic_vector(2 downto 0) := "110";
|
||||
constant F3_SYSTEM_CSRRCI: std_logic_vector(2 downto 0) := "111";
|
||||
|
||||
end constants;
|
||||
|
||||
package body constants is
|
||||
|
||||
end constants;
|
174
vhdl/control_unit.vhd
Normal file
174
vhdl/control_unit.vhd
Normal file
|
@ -0,0 +1,174 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RPU
|
||||
-- Description: control unit
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
library work;
|
||||
use work.constants.all;
|
||||
|
||||
entity control_unit is
|
||||
Port (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_reset : in STD_LOGIC;
|
||||
I_aluop : in STD_LOGIC_VECTOR (6 downto 0);
|
||||
|
||||
-- interrupts
|
||||
I_int_enabled: in std_logic;
|
||||
I_int: in STD_LOGIC;
|
||||
O_int_ack: out STD_LOGIC;
|
||||
I_int_mem_data: in STD_LOGIC_VECTOR(XLENM1 downto 0);
|
||||
O_idata: out STD_LOGIC_VECTOR(XLENM1 downto 0);
|
||||
O_set_idata:out STD_LOGIC;
|
||||
O_set_ipc: out STD_LOGIC;
|
||||
O_set_irpc: out STD_LOGIC;
|
||||
|
||||
-- mem controller state and control
|
||||
I_ready: in STD_LOGIC;
|
||||
O_execute: out STD_LOGIC;
|
||||
I_dataReady: in STD_LOGIC;
|
||||
|
||||
O_state : out STD_LOGIC_VECTOR (6 downto 0)
|
||||
);
|
||||
end control_unit;
|
||||
|
||||
architecture Behavioral of control_unit is
|
||||
signal s_state: STD_LOGIC_VECTOR(6 downto 0) := "0000001";
|
||||
|
||||
signal mem_ready: std_logic;
|
||||
signal mem_execute: std_logic:='0';
|
||||
signal mem_dataReady: std_logic;
|
||||
|
||||
signal mem_cycles : integer := 0;
|
||||
|
||||
signal next_s_state: STD_LOGIC_VECTOR(6 downto 0) := "0000001";
|
||||
|
||||
signal interrupt_state: STD_LOGIC_VECTOR(2 downto 0) := "000";
|
||||
signal interrupt_ack: STD_LOGIC := '0';
|
||||
signal interrupt_was_inactive: STD_LOGIC := '1';
|
||||
signal set_idata: STD_LOGIC := '0';
|
||||
signal set_ipc: STD_LOGIC := '0';
|
||||
|
||||
begin
|
||||
|
||||
O_execute <= mem_execute;
|
||||
mem_ready <= I_ready;
|
||||
mem_dataReady <= I_dataReady;
|
||||
O_int_ack <= interrupt_ack;
|
||||
O_set_idata <= set_idata;
|
||||
O_set_irpc <= set_idata;
|
||||
O_set_ipc <= set_ipc;
|
||||
|
||||
process(I_clk)
|
||||
begin
|
||||
if rising_edge(I_clk) then
|
||||
if I_reset = '1' then
|
||||
s_state <= "0000001";
|
||||
next_s_state <= "0000001";
|
||||
mem_cycles <= 0;
|
||||
mem_execute <= '0';
|
||||
interrupt_was_inactive <= '1';
|
||||
interrupt_ack <= '0';
|
||||
interrupt_state <= "000";
|
||||
set_ipc <= '0';
|
||||
O_idata <= X"00000000";
|
||||
set_idata <= '0';
|
||||
else
|
||||
if I_int = '0' then
|
||||
interrupt_was_inactive <= '1';
|
||||
end if;
|
||||
case s_state is
|
||||
when "0000001" => -- fetch
|
||||
if mem_cycles = 0 and mem_ready = '1' then
|
||||
mem_execute <= '1';
|
||||
mem_cycles <= 1;
|
||||
|
||||
elsif mem_cycles = 1 then
|
||||
mem_execute <= '0';
|
||||
mem_cycles <= 2;
|
||||
|
||||
elsif mem_cycles = 2 then
|
||||
if mem_dataReady = '1' then
|
||||
mem_cycles <= 0;
|
||||
s_state <= "0000010";
|
||||
end if;
|
||||
end if;
|
||||
when "0000010" => --- decode
|
||||
s_state <= "0001000"; --E "0000100"; --R
|
||||
when "0000100" => -- read -- DEPRECATED STAGE
|
||||
s_state <= "0001000"; --E
|
||||
when "0001000" => -- execute
|
||||
--MEM/WB
|
||||
-- if it's not a memory alu op, goto writeback
|
||||
if (I_aluop(6 downto 2) = OPCODE_LOAD or
|
||||
I_aluop(6 downto 2) = OPCODE_STORE) then
|
||||
s_state <= "0010000"; -- MEM
|
||||
else
|
||||
s_state <= "0100000"; -- WB
|
||||
end if;
|
||||
when "0010000" => -- mem
|
||||
-- sometimes memory can be busy, if so we need to relook here
|
||||
if mem_cycles = 0 and mem_ready = '1' then
|
||||
mem_execute <= '1';
|
||||
mem_cycles <= 1;
|
||||
|
||||
elsif mem_cycles = 1 then
|
||||
mem_execute <= '0';
|
||||
-- if it's a write, go through
|
||||
if I_aluop(6 downto 2) = OPCODE_STORE then
|
||||
mem_cycles <= 0;
|
||||
s_state <= "0100001";-- "0100000"; -- WB
|
||||
elsif mem_dataReady = '1' then
|
||||
-- if read, wait for data
|
||||
mem_cycles <= 0;
|
||||
s_state <= "0100000"; -- WB
|
||||
end if;
|
||||
end if;
|
||||
when "0100000" => -- writeback
|
||||
-- check interrupt?
|
||||
if I_int_enabled='1' and interrupt_was_inactive = '1' and I_int = '1' then
|
||||
interrupt_ack <= '1';
|
||||
interrupt_was_inactive <= '0';
|
||||
interrupt_state <= "001";
|
||||
next_s_state <= "0000001"; --F
|
||||
s_state <= "1000000"; --F
|
||||
else
|
||||
s_state <= "0000001"; --F
|
||||
end if;
|
||||
|
||||
when "1000000" => -- stalls
|
||||
-- interrupt stall
|
||||
if interrupt_state = "001" then
|
||||
-- give a cycle of latency
|
||||
interrupt_state <= "010";
|
||||
elsif interrupt_state = "010" then
|
||||
-- sample input data for state?
|
||||
O_idata <= I_int_mem_data;
|
||||
set_idata <= '1';
|
||||
interrupt_state <= "100";
|
||||
elsif interrupt_state = "100" then
|
||||
set_idata <= '0';
|
||||
-- set PC to interrupt vector.
|
||||
set_ipc <= '1';
|
||||
interrupt_state <= "101";
|
||||
elsif interrupt_state = "101" then
|
||||
set_ipc <= '0';
|
||||
interrupt_ack <= '0';
|
||||
interrupt_state <= "000";
|
||||
s_state <= "0000001"; --F
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
s_state <= "0000001";
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
O_state <= s_state;
|
||||
end Behavioral;
|
||||
|
||||
|
||||
|
351
vhdl/core.vhd
Normal file
351
vhdl/core.vhd
Normal file
|
@ -0,0 +1,351 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RPU
|
||||
-- Description: RPU core glue entity
|
||||
--
|
||||
-- Brings all core components together with a little logic.
|
||||
-- This is the CPU interface required.
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
library work;
|
||||
use work.constants.all;
|
||||
|
||||
entity core is
|
||||
Port (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_reset : in STD_LOGIC;
|
||||
I_halt : in STD_LOGIC;
|
||||
|
||||
-- unused interrupt interface, relic from TPU implementation
|
||||
I_int: in STD_LOGIC;
|
||||
O_int_ack: out STD_LOGIC;
|
||||
|
||||
-- memory interface
|
||||
MEM_I_ready : IN std_logic;
|
||||
MEM_O_cmd : OUT std_logic;
|
||||
MEM_O_we : OUT std_logic;
|
||||
-- fixme: this is not a true byteEnable and so is confusing.
|
||||
-- Will be fixed when memory swizzling is brought core-size
|
||||
MEM_O_byteEnable : OUT std_logic_vector(1 downto 0);
|
||||
MEM_O_addr : OUT std_logic_vector(XLEN32M1 downto 0);
|
||||
MEM_O_data : OUT std_logic_vector(XLEN32M1 downto 0);
|
||||
MEM_I_data : IN std_logic_vector(XLEN32M1 downto 0);
|
||||
MEM_I_dataReady : IN std_logic
|
||||
|
||||
; -- This debug output contains some internal state for debugging
|
||||
O_DBG:out std_logic_vector(XLEN32M1 downto 0)
|
||||
);
|
||||
end core;
|
||||
|
||||
architecture Behavioral of core is
|
||||
COMPONENT pc_unit
|
||||
PORT(
|
||||
I_clk : IN std_logic;
|
||||
I_nPC : IN std_logic_vector(XLENM1 downto 0);
|
||||
I_nPCop : IN std_logic_vector(1 downto 0);
|
||||
I_intVec: IN std_logic;
|
||||
O_PC : OUT std_logic_vector(XLENM1 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT control_unit
|
||||
PORT (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_reset : in STD_LOGIC;
|
||||
I_aluop : in STD_LOGIC_VECTOR (6 downto 0);
|
||||
O_state : out STD_LOGIC_VECTOR (6 downto 0);
|
||||
|
||||
I_int: in STD_LOGIC;
|
||||
O_int_ack: out STD_LOGIC;
|
||||
|
||||
I_int_enabled: in STD_LOGIC;
|
||||
I_int_mem_data: in STD_LOGIC_VECTOR(XLENM1 downto 0);
|
||||
O_idata: out STD_LOGIC_VECTOR(XLENM1 downto 0);
|
||||
O_set_idata:out STD_LOGIC;
|
||||
O_set_ipc: out STD_LOGIC;
|
||||
O_set_irpc: out STD_LOGIC;
|
||||
|
||||
I_ready: in STD_LOGIC;
|
||||
O_execute: out STD_LOGIC;
|
||||
I_dataReady: in STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
|
||||
COMPONENT decoder_RV32
|
||||
PORT(
|
||||
I_clk : IN std_logic;
|
||||
I_en : IN std_logic;
|
||||
I_dataInst : IN std_logic_vector(31 downto 0);
|
||||
O_selRS1 : OUT std_logic_vector(4 downto 0);
|
||||
O_selRS2 : OUT std_logic_vector(4 downto 0);
|
||||
O_selD : OUT std_logic_vector(4 downto 0);
|
||||
O_dataIMM : OUT std_logic_vector(31 downto 0);
|
||||
O_regDwe : OUT std_logic;
|
||||
O_aluOp : OUT std_logic_vector(6 downto 0);
|
||||
O_aluFunc : OUT std_logic_vector(15 downto 0); -- ALU function
|
||||
O_memOp : out STD_LOGIC_VECTOR(4 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
|
||||
component alu_RV32I is
|
||||
Port ( I_clk : in STD_LOGIC;
|
||||
I_en : in STD_LOGIC;
|
||||
I_dataA : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
I_dataB : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
I_dataDwe : in STD_LOGIC;
|
||||
I_aluop : in STD_LOGIC_VECTOR (4 downto 0);
|
||||
I_aluFunc : in STD_LOGIC_VECTOR (15 downto 0);
|
||||
I_PC : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
I_dataIMM : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
O_dataResult : out STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
O_branchTarget : out STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
O_dataWriteReg : out STD_LOGIC;
|
||||
O_shouldBranch : out std_logic
|
||||
|
||||
);
|
||||
end component;
|
||||
|
||||
COMPONENT register_set
|
||||
PORT(
|
||||
I_clk : IN std_logic;
|
||||
I_en : IN std_logic;
|
||||
I_dataD : IN std_logic_vector(31 downto 0);
|
||||
I_selRS1 : IN std_logic_vector(4 downto 0);
|
||||
I_selRS2 : IN std_logic_vector(4 downto 0);
|
||||
I_selD : IN std_logic_vector(4 downto 0);
|
||||
I_we : IN std_logic;
|
||||
O_dataA : OUT std_logic_vector(31 downto 0);
|
||||
O_dataB : OUT std_logic_vector(31 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
|
||||
|
||||
COMPONENT mem_controller
|
||||
PORT(
|
||||
I_clk : IN std_logic;
|
||||
I_reset : IN std_logic;
|
||||
O_ready : OUT std_logic;
|
||||
I_execute : IN std_logic;
|
||||
I_dataWe : IN std_logic;
|
||||
I_address : IN std_logic_vector(XLENM1 downto 0);
|
||||
I_data : IN std_logic_vector(XLENM1 downto 0);
|
||||
I_dataByteEn : IN std_logic_vector(1 downto 0);
|
||||
O_data : OUT std_logic_vector(XLENM1 downto 0);
|
||||
O_dataReady : OUT std_logic;
|
||||
MEM_I_ready : IN std_logic;
|
||||
MEM_O_cmd : OUT std_logic;
|
||||
MEM_O_we : OUT std_logic;
|
||||
MEM_O_byteEnable : OUT std_logic_vector(1 downto 0);
|
||||
MEM_O_addr : OUT std_logic_vector(XLENM1 downto 0);
|
||||
MEM_O_data : OUT std_logic_vector(XLENM1 downto 0);
|
||||
MEM_I_data : IN std_logic_vector(XLENM1 downto 0);
|
||||
MEM_I_dataReady : IN std_logic
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
|
||||
signal state : std_logic_vector(6 downto 0) := (others => '0');
|
||||
|
||||
|
||||
signal pcop: std_logic_vector(1 downto 0);
|
||||
signal in_pc: std_logic_vector(XLENM1 downto 0);
|
||||
|
||||
signal aluFunc: std_logic_vector(15 downto 0);
|
||||
signal memOp: std_logic_vector(4 downto 0);
|
||||
|
||||
signal branchTarget:std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
|
||||
signal instruction : std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
signal dataA : std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
signal dataB : std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
signal dataDwe : std_logic := '0';
|
||||
signal aluop : std_logic_vector(6 downto 0) := (others => '0');
|
||||
signal dataIMM : std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
signal selRS1 : std_logic_vector(4 downto 0) := (others => '0');
|
||||
signal selRS2 : std_logic_vector(4 downto 0) := (others => '0');
|
||||
signal selD : std_logic_vector(4 downto 0) := (others => '0');
|
||||
signal dataregWrite: std_logic := '0';
|
||||
signal dataResult : std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
signal dataWriteReg : std_logic := '0';
|
||||
signal shouldBranch : std_logic := '0';
|
||||
signal memMode : std_logic := '0';
|
||||
signal ram_req_size : std_logic := '0';
|
||||
|
||||
signal reg_en: std_logic := '0';
|
||||
signal reg_we: std_logic := '0';
|
||||
|
||||
signal registerWriteData : std_logic_vector(XLENM1 downto 0) := (others=>'0');
|
||||
|
||||
signal en_fetch : std_logic := '0';
|
||||
signal en_decode : std_logic := '0';
|
||||
signal en_alu : std_logic := '0';
|
||||
signal en_memory : std_logic := '0';
|
||||
signal en_regwrite : std_logic := '0';
|
||||
signal en_stall : std_logic := '0';
|
||||
|
||||
signal PC : std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
|
||||
signal memctl_ready : std_logic;
|
||||
signal memctl_execute : std_logic := '0';
|
||||
signal memctl_dataWe : std_logic;
|
||||
signal memctl_address : std_logic_vector(XLENM1 downto 0);
|
||||
signal memctl_in_data : std_logic_vector(XLENM1 downto 0);
|
||||
signal memctl_dataByteEn : std_logic_vector(1 downto 0);
|
||||
signal memctl_out_data : std_logic_vector(XLENM1 downto 0) := (others => '0');
|
||||
signal memctl_dataReady : std_logic := '0';
|
||||
signal memctl_size : std_logic_vector(1 downto 0);
|
||||
signal memctl_signExtend: std_logic := '0';
|
||||
|
||||
signal PCintVec: STD_LOGIC := '0';
|
||||
|
||||
signal int_idata: STD_LOGIC_VECTOR(XLENM1 downto 0);
|
||||
signal int_set_idata: STD_LOGIC;
|
||||
signal int_enabled: std_logic;
|
||||
signal int_set_irpc: STD_LOGIC;
|
||||
|
||||
signal core_clock:STD_LOGIC := '0';
|
||||
|
||||
begin
|
||||
core_clock <= I_clk;
|
||||
|
||||
memctl: mem_controller PORT MAP (
|
||||
I_clk => I_clk,
|
||||
I_reset => I_reset,
|
||||
|
||||
O_ready => memctl_ready,
|
||||
I_execute => memctl_execute,
|
||||
I_dataWe => memctl_dataWe,
|
||||
I_address => memctl_address,
|
||||
I_data => memctl_in_data,
|
||||
I_dataByteEn => memctl_dataByteEn,
|
||||
O_data => memctl_out_data,
|
||||
O_dataReady => memctl_dataReady,
|
||||
|
||||
MEM_I_ready => MEM_I_ready,
|
||||
MEM_O_cmd => MEM_O_cmd,
|
||||
MEM_O_we => MEM_O_we,
|
||||
MEM_O_byteEnable => MEM_O_byteEnable,
|
||||
MEM_O_addr => MEM_O_addr,
|
||||
MEM_O_data => MEM_O_data,
|
||||
MEM_I_data => MEM_I_data,
|
||||
MEM_I_dataReady => MEM_I_dataReady
|
||||
);
|
||||
|
||||
pcunit: pc_unit Port map (
|
||||
I_clk => core_clock,
|
||||
I_nPC => in_pc,
|
||||
I_nPCop => pcop,
|
||||
I_intVec => PCintVec,
|
||||
O_PC => PC
|
||||
);
|
||||
|
||||
control: control_unit PORT MAP (
|
||||
I_clk => core_clock,
|
||||
I_reset => I_reset,
|
||||
I_aluop => aluop,
|
||||
|
||||
I_int => I_int,
|
||||
O_int_ack => O_int_ack,
|
||||
|
||||
I_int_enabled => int_enabled,
|
||||
I_int_mem_data=>MEM_I_data,
|
||||
O_idata=> int_idata,
|
||||
O_set_idata=> int_set_idata,
|
||||
O_set_ipc=> PCintVec,
|
||||
O_set_irpc => int_set_irpc,
|
||||
I_ready => memctl_ready,
|
||||
O_execute => memctl_execute,
|
||||
I_dataReady => memctl_dataReady,
|
||||
|
||||
O_state => state
|
||||
);
|
||||
|
||||
|
||||
decoder: decoder_RV32 PORT MAP (
|
||||
I_clk => core_clock,
|
||||
I_en => en_decode,
|
||||
I_dataInst => instruction,
|
||||
O_selRS1 => selRS1,
|
||||
O_selRS2 => selRS2,
|
||||
O_selD => selD,
|
||||
O_dataIMM => dataIMM,
|
||||
O_regDwe => dataDwe,
|
||||
O_aluOp => aluOp,
|
||||
O_aluFunc => aluFunc,
|
||||
O_memOp => memOp
|
||||
);
|
||||
|
||||
alu: alu_RV32I PORT MAP (
|
||||
I_clk => core_clock,
|
||||
I_en => en_alu,
|
||||
I_dataA => dataA,
|
||||
I_dataB => dataB,
|
||||
I_dataDwe => dataDwe,
|
||||
I_aluop => aluop(6 downto 2),
|
||||
I_aluFunc => aluFunc,
|
||||
I_PC => PC,
|
||||
I_dataIMM => dataIMM,
|
||||
O_dataResult => dataResult,
|
||||
O_branchTarget => branchTarget,
|
||||
O_dataWriteReg => dataWriteReg,
|
||||
O_shouldBranch => shouldBranch
|
||||
);
|
||||
|
||||
reg: register_set PORT MAP (
|
||||
I_clk => core_clock,
|
||||
I_en => reg_en,
|
||||
I_dataD => registerWriteData,
|
||||
O_dataA => dataA,
|
||||
O_dataB => dataB,
|
||||
I_selRS1 => selRS1,
|
||||
I_selRS2 => selRS2,
|
||||
I_selD => selD,
|
||||
I_we => reg_we
|
||||
);
|
||||
|
||||
-- Register file controls
|
||||
reg_en <= en_decode or en_regwrite;
|
||||
reg_we <= dataWriteReg and en_regwrite;
|
||||
|
||||
-- These are the pipeline stage enable bits
|
||||
en_fetch <= state(0);
|
||||
en_decode <= state(1);
|
||||
en_alu <= state(3);
|
||||
en_memory <= state(4);
|
||||
en_regwrite <= state(5);
|
||||
en_stall <= state(6);
|
||||
|
||||
-- This decides what the next PC should be
|
||||
pcop <= PCU_OP_RESET when I_reset = '1' else
|
||||
PCU_OP_ASSIGN when shouldBranch = '1' and state(5) = '1' else
|
||||
PCU_OP_INC when shouldBranch = '0' and state(5) = '1' else
|
||||
PCU_OP_NOP;
|
||||
|
||||
-- The input PC is just always the branch target output from ALU
|
||||
in_pc <= branchTarget;
|
||||
|
||||
-- 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);
|
||||
|
||||
-- Below statements are for memory interface use.
|
||||
memctl_address <= dataResult when en_memory = '1' else PC;
|
||||
ram_req_size <= memMode when en_memory = '1' else '0';
|
||||
memctl_dataByteEn <= memctl_size when en_memory = '1' else F2_MEM_LS_SIZE_W;
|
||||
memctl_in_data <= dataB;
|
||||
memctl_dataWe <= '1' when en_memory = '1' and memOp(4 downto 3) = "11" else '0';
|
||||
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;
|
||||
|
||||
-- The instructions are delivered from memctl
|
||||
instruction <= memctl_out_data;
|
||||
|
||||
end Behavioral;
|
||||
|
101
vhdl/mem_controller.vhd
Normal file
101
vhdl/mem_controller.vhd
Normal file
|
@ -0,0 +1,101 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RPU
|
||||
-- Description: Memory controller unit of RPU
|
||||
--
|
||||
-- Very simple. Allows for delays in reads, whilsts writes go through immediately.
|
||||
-- MEM_ signals are expected to be exposted to any SoC fabric.
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
library work;
|
||||
use work.constants.all;
|
||||
|
||||
|
||||
entity mem_controller is
|
||||
Port (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_reset : in STD_LOGIC;
|
||||
|
||||
O_ready : out STD_LOGIC;
|
||||
I_execute: in STD_LOGIC;
|
||||
I_dataWe : in STD_LOGIC;
|
||||
I_address : in STD_LOGIC_VECTOR (XLENM1 downto 0);
|
||||
I_data : in STD_LOGIC_VECTOR (XLENM1 downto 0);
|
||||
I_dataByteEn : in STD_LOGIC_VECTOR(1 downto 0);
|
||||
O_data : out STD_LOGIC_VECTOR (XLENM1 downto 0);
|
||||
O_dataReady: out STD_LOGIC;
|
||||
|
||||
MEM_I_ready: in STD_LOGIC;
|
||||
MEM_O_cmd: out STD_LOGIC;
|
||||
MEM_O_we : out STD_LOGIC;
|
||||
MEM_O_byteEnable : out STD_LOGIC_VECTOR (1 downto 0);
|
||||
MEM_O_addr : out STD_LOGIC_VECTOR (XLENM1 downto 0);
|
||||
MEM_O_data : out STD_LOGIC_VECTOR (XLENM1 downto 0);
|
||||
MEM_I_data : in STD_LOGIC_VECTOR (XLENM1 downto 0);
|
||||
MEM_I_dataReady : in STD_LOGIC
|
||||
);
|
||||
end mem_controller;
|
||||
|
||||
architecture Behavioral of mem_controller is
|
||||
|
||||
signal we : std_logic := '0';
|
||||
signal addr : STD_LOGIC_VECTOR (XLENM1 downto 0) := X"00000000";
|
||||
signal indata: STD_LOGIC_VECTOR (XLENM1 downto 0) := X"00000000";
|
||||
signal byteEnable: STD_LOGIC_VECTOR ( 1 downto 0) := "11";
|
||||
signal cmd : STD_LOGIC := '0';
|
||||
signal state: integer := 0;
|
||||
|
||||
signal ready: STD_LOGIC := '0';
|
||||
|
||||
begin
|
||||
|
||||
process (I_clk, I_execute)
|
||||
begin
|
||||
if rising_edge(I_clk) then
|
||||
if I_reset = '1' then
|
||||
we <= '0';
|
||||
cmd <= '0';
|
||||
state <= 0;
|
||||
O_dataReady <= '0';
|
||||
elsif state = 0 and I_execute = '1' and MEM_I_ready = '1' then
|
||||
we <= I_dataWe;
|
||||
addr <= I_address;
|
||||
indata <= I_data;
|
||||
byteEnable <= I_dataByteEn;
|
||||
cmd <= '1';
|
||||
O_dataReady <= '0';
|
||||
if I_dataWe = '0' then
|
||||
state <= 3;-- read
|
||||
else
|
||||
state <= 2;-- write
|
||||
end if;
|
||||
elsif state = 3 then
|
||||
cmd <= '0';
|
||||
state <= 1;
|
||||
elsif state = 1 then
|
||||
cmd <= '0';
|
||||
if MEM_I_dataReady = '1' then
|
||||
O_dataReady <= '1';
|
||||
O_data <= MEM_I_data;
|
||||
state <= 2;
|
||||
end if;
|
||||
elsif state = 2 then
|
||||
cmd <= '0';
|
||||
state <= 0;
|
||||
O_dataReady <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
O_ready <= ( MEM_I_ready and not I_execute ) when state = 0 else '0';
|
||||
|
||||
MEM_O_cmd <= cmd;
|
||||
MEM_O_byteEnable <= byteEnable;
|
||||
MEM_O_data <= indata;
|
||||
MEM_O_addr <= addr;
|
||||
MEM_O_we <= we;
|
||||
|
||||
end Behavioral;
|
||||
|
52
vhdl/pc_unit.vhd
Normal file
52
vhdl/pc_unit.vhd
Normal file
|
@ -0,0 +1,52 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RPU
|
||||
-- Description: Program Counter unit of RPU
|
||||
--
|
||||
-- Simple black box for holding and manipulating the PC
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.constants.all;
|
||||
|
||||
entity pc_unit is
|
||||
Port (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_nPC : in STD_LOGIC_VECTOR (XLENM1 downto 0);
|
||||
I_nPCop : in STD_LOGIC_VECTOR (1 downto 0);
|
||||
I_intVec: in STD_LOGIC;
|
||||
O_PC : out STD_LOGIC_VECTOR (XLENM1 downto 0)
|
||||
);
|
||||
end pc_unit;
|
||||
|
||||
architecture Behavioral of pc_unit is
|
||||
signal current_pc: std_logic_vector( XLENM1 downto 0) := ADDR_RESET;
|
||||
begin
|
||||
|
||||
process (I_clk)
|
||||
begin
|
||||
if rising_edge(I_clk) then
|
||||
case I_nPCop is
|
||||
when PCU_OP_NOP => -- NOP, keep PC the same/halt
|
||||
if I_intVec = '1' then -- in a NOP, you can get intterupts. check.
|
||||
current_pc <= ADDR_INTVEC;-- set PC to interrupt vector;
|
||||
end if;
|
||||
when PCU_OP_INC => -- increment
|
||||
current_pc <= std_logic_vector(unsigned(current_pc) + 4); -- 32bit byte addressing
|
||||
when PCU_OP_ASSIGN => -- set from external input
|
||||
current_pc <= I_nPC;
|
||||
when PCU_OP_RESET => -- Reset
|
||||
current_pc <= ADDR_RESET;
|
||||
when others =>
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
O_PC <= current_pc;
|
||||
|
||||
end Behavioral;
|
||||
|
49
vhdl/register_set.vhd
Normal file
49
vhdl/register_set.vhd
Normal file
|
@ -0,0 +1,49 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RISC-V CPU
|
||||
-- Description: Register file unit
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.constants.all;
|
||||
|
||||
entity register_set is
|
||||
Port (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_en : in STD_LOGIC;
|
||||
I_dataD : in STD_LOGIC_VECTOR (XLENM1 downto 0); -- Data to write to regD
|
||||
I_selRS1 : in STD_LOGIC_VECTOR (4 downto 0); -- Select line for regRS1
|
||||
I_selRS2 : in STD_LOGIC_VECTOR (4 downto 0); -- Select line for regRS2
|
||||
I_selD : in STD_LOGIC_VECTOR (4 downto 0); -- Select line for regD
|
||||
I_we : in STD_LOGIC; -- Write enable for regD
|
||||
O_dataA : out STD_LOGIC_VECTOR (XLENM1 downto 0);-- regRS1 data out
|
||||
O_dataB : out STD_LOGIC_VECTOR (XLENM1 downto 0) -- regRS2 data out
|
||||
);
|
||||
end register_set;
|
||||
|
||||
architecture Behavioral of register_set is
|
||||
type store_t is array (0 to 31) of std_logic_vector(XLENM1 downto 0);
|
||||
signal regs: store_t := (others => X"00000000");
|
||||
signal dataAout: STD_LOGIC_VECTOR (XLENM1 downto 0) := (others=>'0');
|
||||
signal dataBout: STD_LOGIC_VECTOR (XLENM1 downto 0) := (others=>'0');
|
||||
begin
|
||||
|
||||
process(I_clk, I_en)
|
||||
begin
|
||||
if rising_edge(I_clk) and I_en='1' then
|
||||
dataAout <= regs(to_integer(unsigned(I_selRS1)));
|
||||
dataBout <= regs(to_integer(unsigned(I_selRS2)));
|
||||
if (I_we = '1') then
|
||||
regs(to_integer(unsigned(I_selD))) <= I_dataD;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
O_dataA <= dataAout;
|
||||
O_dataB <= dataBout;
|
||||
|
||||
end Behavioral;
|
||||
|
215
vhdl/unit_alu_RV32_I.vhd
Normal file
215
vhdl/unit_alu_RV32_I.vhd
Normal file
|
@ -0,0 +1,215 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RISC-V CPU
|
||||
-- Description: ALU unit suitable for RV32I operational use
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.constants.all;
|
||||
|
||||
entity alu_RV32I is
|
||||
Port (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_en : in STD_LOGIC;
|
||||
I_dataA : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
I_dataB : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
I_dataDwe : in STD_LOGIC;
|
||||
I_aluop : in STD_LOGIC_VECTOR (4 downto 0);
|
||||
I_aluFunc : in STD_LOGIC_VECTOR (15 downto 0);
|
||||
I_PC : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
I_dataIMM : in STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
O_dataResult : out STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
O_branchTarget : out STD_LOGIC_VECTOR (XLEN32M1 downto 0);
|
||||
O_dataWriteReg : out STD_LOGIC;
|
||||
O_shouldBranch : out std_logic
|
||||
);
|
||||
end alu_RV32I;
|
||||
|
||||
architecture Behavioral of alu_RV32I is
|
||||
-- The internal register for results of operations.
|
||||
-- 32 bit + carry/overflow
|
||||
|
||||
signal s_branchTarget : STD_LOGIC_VECTOR (XLEN32M1 downto 0) := (others => '0');
|
||||
signal s_result: STD_LOGIC_VECTOR(XLEN32M1+2 downto 0) := (others => '0');
|
||||
signal s_shouldBranch: STD_LOGIC := '0';
|
||||
begin
|
||||
|
||||
process (I_clk, I_en)
|
||||
begin
|
||||
if rising_edge(I_clk) and I_en = '1' then
|
||||
O_dataWriteReg <= I_dataDwe;
|
||||
case I_aluop is
|
||||
when OPCODE_OPIMM =>
|
||||
s_shouldBranch <= '0';
|
||||
case I_aluFunc(2 downto 0) is
|
||||
when F3_OPIMM_ADDI =>
|
||||
s_result(31 downto 0) <= std_logic_vector(signed( I_dataA) + signed( I_dataIMM));
|
||||
|
||||
when F3_OPIMM_XORI =>
|
||||
s_result(31 downto 0) <= I_dataA xor I_dataIMM;
|
||||
|
||||
when F3_OPIMM_ORI =>
|
||||
s_result(31 downto 0) <= I_dataA or I_dataIMM;
|
||||
|
||||
when F3_OPIMM_ANDI =>
|
||||
s_result(31 downto 0) <= I_dataA and I_dataIMM;
|
||||
|
||||
when F3_OPIMM_SLTI =>
|
||||
if signed(I_dataA) < signed(I_dataIMM) then
|
||||
s_result(31 downto 0) <= X"00000001";
|
||||
else
|
||||
s_result(31 downto 0) <= X"00000000";
|
||||
end if;
|
||||
|
||||
when F3_OPIMM_SLTIU =>
|
||||
if unsigned(I_dataA) < unsigned(I_dataIMM) then
|
||||
s_result(31 downto 0) <= X"00000001";
|
||||
else
|
||||
s_result(31 downto 0) <= X"00000000";
|
||||
end if;
|
||||
|
||||
when F3_OPIMM_SLLI =>
|
||||
s_result(31 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), to_integer(unsigned(I_dataIMM(4 downto 0)))));
|
||||
|
||||
when F3_OPIMM_SRLI =>
|
||||
case I_aluFunc(9 downto 3) is
|
||||
when F7_OPIMM_SRLI =>
|
||||
s_result(31 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), to_integer(unsigned(I_dataIMM(4 downto 0)))));
|
||||
when F7_OPIMM_SRAI =>
|
||||
s_result(31 downto 0) <= std_logic_vector(shift_right(signed(I_dataA), to_integer(unsigned(I_dataIMM(4 downto 0)))));
|
||||
when others=>
|
||||
end case;
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
when OPCODE_OP =>
|
||||
case I_aluFunc(9 downto 0) is
|
||||
when F7_OP_ADD & F3_OP_ADD =>
|
||||
s_result(31 downto 0) <= std_logic_vector(signed( I_dataA) + signed( I_dataB));
|
||||
|
||||
when F7_OP_SUB & F3_OP_SUB =>
|
||||
s_result(31 downto 0) <= std_logic_vector(signed( I_dataA) - signed( I_dataB));
|
||||
|
||||
when F7_OP_SLT & F3_OP_SLT =>
|
||||
if signed(I_dataA) < signed(I_dataB) then
|
||||
s_result(31 downto 0) <= X"00000001";
|
||||
else
|
||||
s_result(31 downto 0) <= X"00000000";
|
||||
end if;
|
||||
|
||||
when F7_OP_SLTU & F3_OP_SLTU =>
|
||||
if unsigned(I_dataA) < unsigned(I_dataB) then
|
||||
s_result(31 downto 0) <= X"00000001";
|
||||
else
|
||||
s_result(31 downto 0) <= X"00000000";
|
||||
end if;
|
||||
|
||||
when F7_OP_XOR & F3_OP_XOR =>
|
||||
s_result(31 downto 0) <= I_dataA xor I_dataB;
|
||||
|
||||
when F7_OP_OR & F3_OP_OR =>
|
||||
s_result(31 downto 0) <= I_dataA or I_dataB;
|
||||
|
||||
when F7_OP_AND & F3_OP_AND =>
|
||||
s_result(31 downto 0) <= I_dataA and I_dataB;
|
||||
|
||||
when F7_OP_SLL & F3_OP_SLL =>
|
||||
s_result(31 downto 0) <= std_logic_vector(shift_left(unsigned(I_dataA), to_integer(unsigned(I_dataB(4 downto 0)))));
|
||||
|
||||
when F7_OP_SRL & F3_OP_SRL =>
|
||||
s_result(31 downto 0) <= std_logic_vector(shift_right(unsigned(I_dataA), to_integer(unsigned(I_dataB(4 downto 0)))));
|
||||
|
||||
when F7_OP_SRA & F3_OP_SRA =>
|
||||
s_result(31 downto 0) <= std_logic_vector(shift_right(signed(I_dataA), to_integer(unsigned(I_dataB(4 downto 0)))));
|
||||
|
||||
when others=>
|
||||
s_result <= "00" & X"CDC1FEF1";
|
||||
end case;
|
||||
|
||||
s_shouldBranch <= '0';
|
||||
|
||||
when OPCODE_LOAD | OPCODE_STORE =>
|
||||
s_shouldBranch <= '0';
|
||||
s_result(31 downto 0) <= std_logic_vector(signed( I_dataA) + signed( I_dataIMM));
|
||||
|
||||
when OPCODE_JALR =>
|
||||
s_branchTarget <= std_logic_vector(signed( I_dataA) + signed( I_dataIMM));
|
||||
s_shouldBranch <= '1';
|
||||
s_result(31 downto 0) <= std_logic_vector(signed( I_PC) + 4);
|
||||
|
||||
when OPCODE_JAL =>
|
||||
s_branchTarget <= std_logic_vector(signed( I_PC) + signed( I_dataIMM));
|
||||
s_shouldBranch <= '1';
|
||||
s_result(31 downto 0) <= std_logic_vector(signed( I_PC) + 4);
|
||||
|
||||
when OPCODE_LUI =>
|
||||
s_shouldBranch <= '0';
|
||||
s_result(31 downto 0) <= I_dataIMM;
|
||||
|
||||
when OPCODE_AUIPC =>
|
||||
s_shouldBranch <= '0';
|
||||
s_result(31 downto 0) <= std_logic_vector( signed( I_PC) + signed( I_dataIMM));
|
||||
|
||||
when OPCODE_BRANCH =>
|
||||
s_branchTarget <= std_logic_vector(signed( I_PC) + signed( I_dataIMM));
|
||||
case I_aluFunc(2 downto 0) is
|
||||
when F3_BRANCH_BEQ =>
|
||||
if I_dataA = I_dataB then
|
||||
s_shouldBranch <= '1';
|
||||
else
|
||||
s_shouldBranch <= '0';
|
||||
end if;
|
||||
|
||||
when F3_BRANCH_BNE =>
|
||||
if I_dataA /= I_dataB then
|
||||
s_shouldBranch <= '1';
|
||||
else
|
||||
s_shouldBranch <= '0';
|
||||
end if;
|
||||
|
||||
when F3_BRANCH_BLT =>
|
||||
if signed(I_dataA) < signed(I_dataB) then
|
||||
s_shouldBranch <= '1';
|
||||
else
|
||||
s_shouldBranch <= '0';
|
||||
end if;
|
||||
|
||||
when F3_BRANCH_BGE =>
|
||||
if signed(I_dataA) >= signed(I_dataB) then
|
||||
s_shouldBranch <= '1';
|
||||
else
|
||||
s_shouldBranch <= '0';
|
||||
end if;
|
||||
|
||||
when F3_BRANCH_BLTU =>
|
||||
if unsigned(I_dataA) < unsigned(I_dataB) then
|
||||
s_shouldBranch <= '1';
|
||||
else
|
||||
s_shouldBranch <= '0';
|
||||
end if;
|
||||
|
||||
when F3_BRANCH_BGEU =>
|
||||
if unsigned(I_dataA) >= unsigned(I_dataB) then
|
||||
s_shouldBranch <= '1';
|
||||
else
|
||||
s_shouldBranch <= '0';
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
when others =>
|
||||
s_result <= "00" & X"CDCDFEFE";
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
O_dataResult <= s_result(XLEN32M1 downto 0);
|
||||
O_shouldBranch <= s_shouldBranch;
|
||||
O_branchTarget <= s_branchTarget;
|
||||
|
||||
end Behavioral;
|
127
vhdl/unit_decoder_RV32I.vhd
Normal file
127
vhdl/unit_decoder_RV32I.vhd
Normal file
|
@ -0,0 +1,127 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Project Name: RISC-V CPU
|
||||
-- Description: decoder unit RV32I
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.constants.all;
|
||||
|
||||
entity decoder_RV32 is
|
||||
Port (
|
||||
I_clk : in STD_LOGIC;
|
||||
I_en : in STD_LOGIC;
|
||||
I_dataInst : in STD_LOGIC_VECTOR (31 downto 0); -- Instruction to be decoded
|
||||
O_selRS1 : out STD_LOGIC_VECTOR (4 downto 0); -- Selection out for regrs1
|
||||
O_selRS2 : out STD_LOGIC_VECTOR (4 downto 0); -- Selection out for regrs2
|
||||
O_selD : out STD_LOGIC_VECTOR (4 downto 0); -- Selection out for regD
|
||||
O_dataIMM : out STD_LOGIC_VECTOR (31 downto 0); -- Immediate value out
|
||||
O_regDwe : out STD_LOGIC; -- RegD wrtite enable
|
||||
O_aluOp : out STD_LOGIC_VECTOR (6 downto 0); -- ALU opcode
|
||||
O_aluFunc : out STD_LOGIC_VECTOR (15 downto 0); -- ALU function
|
||||
O_memOp : out STD_LOGIC_VECTOR(4 downto 0) -- Memory operation
|
||||
);
|
||||
end decoder_RV32;
|
||||
|
||||
architecture Behavioral of decoder_RV32 is
|
||||
begin
|
||||
-- Register selects for reads are async
|
||||
O_selRS1 <= I_dataInst(R1_START downto R1_END);
|
||||
O_selRS2 <= I_dataInst(R2_START downto R2_END);
|
||||
|
||||
process (I_clk, I_en)
|
||||
begin
|
||||
if rising_edge(I_clk) and I_en = '1' then
|
||||
|
||||
O_selD <= I_dataInst(RD_START downto RD_END);
|
||||
|
||||
O_aluOp <= I_dataInst(OPCODE_START downto OPCODE_END);
|
||||
|
||||
O_aluFunc <= "000000" & I_dataInst(FUNCT7_START downto FUNCT7_END)
|
||||
& I_dataInst(FUNCT3_START downto FUNCT3_END);
|
||||
|
||||
case I_dataInst(OPCODE_START downto OPCODE_END_2) is
|
||||
when OPCODE_LUI =>
|
||||
O_regDwe <= '1';
|
||||
O_memOp <= "00000";
|
||||
O_dataIMM <= I_dataInst(IMM_U_START downto IMM_U_END)
|
||||
& "000000000000";
|
||||
when OPCODE_AUIPC =>
|
||||
O_regDwe <= '1';
|
||||
O_memOp <= "00000";
|
||||
O_dataIMM <= I_dataInst(IMM_U_START downto IMM_U_END)
|
||||
& "000000000000";
|
||||
when OPCODE_JAL =>
|
||||
if I_dataInst(RD_START downto RD_END) = "00000" then
|
||||
O_regDwe <= '0';
|
||||
else
|
||||
O_regDwe <= '1';
|
||||
end if;
|
||||
O_memOp <= "00000";
|
||||
if I_dataInst(IMM_U_START) = '1' then
|
||||
O_dataIMM <= "111111111111" & I_dataInst(19 downto 12) & I_dataInst(20) & I_dataInst(30 downto 21) & '0';
|
||||
else
|
||||
O_dataIMM <= "000000000000" & I_dataInst(19 downto 12) & I_dataInst(20) & I_dataInst(30 downto 21) & '0';
|
||||
end if;
|
||||
when OPCODE_JALR =>
|
||||
if I_dataInst(RD_START downto RD_END) = "00000" then
|
||||
O_regDwe <= '0';
|
||||
else
|
||||
O_regDwe <= '1';
|
||||
end if;
|
||||
O_memOp <= "00000";
|
||||
if I_dataInst(IMM_U_START) = '1' then
|
||||
O_dataIMM <= X"FFFF" & "1111" & I_dataInst(IMM_I_START downto IMM_I_END);
|
||||
else
|
||||
O_dataIMM <= X"0000" & "0000" & I_dataInst(IMM_I_START downto IMM_I_END);
|
||||
end if;
|
||||
when OPCODE_OPIMM =>
|
||||
O_regDwe <= '1';
|
||||
O_memOp <= "00000";
|
||||
if I_dataInst(IMM_U_START) = '1' then
|
||||
O_dataIMM <= X"FFFF" & "1111" & I_dataInst(IMM_I_START downto IMM_I_END);
|
||||
else
|
||||
O_dataIMM <= X"0000" & "0000" & I_dataInst(IMM_I_START downto IMM_I_END);
|
||||
end if;
|
||||
when OPCODE_LOAD =>
|
||||
O_regDwe <= '1';
|
||||
O_memOp <= "10" & I_dataInst(FUNCT3_START downto FUNCT3_END);
|
||||
if I_dataInst(IMM_U_START) = '1' then
|
||||
O_dataIMM <= X"FFFF" & "1111" & I_dataInst(IMM_I_START downto IMM_I_END);
|
||||
else
|
||||
O_dataIMM <= X"0000" & "0000" & I_dataInst(IMM_I_START downto IMM_I_END);
|
||||
end if;
|
||||
when OPCODE_STORE =>
|
||||
O_regDwe <= '0';
|
||||
O_memOp <= "11" & I_dataInst(FUNCT3_START downto FUNCT3_END);
|
||||
if I_dataInst(IMM_U_START) = '1' then
|
||||
O_dataIMM <= X"FFFF" & "1111" & I_dataInst(IMM_S_A_START downto IMM_S_A_END) & I_dataInst(IMM_S_B_START downto IMM_S_B_END);
|
||||
else
|
||||
O_dataIMM <= X"0000" & "0000" & I_dataInst(IMM_S_A_START downto IMM_S_A_END) & I_dataInst(IMM_S_B_START downto IMM_S_B_END);
|
||||
end if;
|
||||
when OPCODE_BRANCH =>
|
||||
O_regDwe <= '0';
|
||||
O_memOp <= "00000";
|
||||
if I_dataInst(IMM_U_START) = '1' then
|
||||
O_dataIMM <= X"FFFF" & "1111" & I_dataInst(7) & I_dataInst(30 downto 25) & I_dataInst(11 downto 8) & '0';
|
||||
else
|
||||
O_dataIMM <= X"0000" & "0000" & I_dataInst(7) & I_dataInst(30 downto 25) & I_dataInst(11 downto 8) & '0';
|
||||
end if;
|
||||
when OPCODE_MISCMEM =>
|
||||
O_regDwe <= '0';
|
||||
O_memOp <= "01000";
|
||||
O_dataIMM <= I_dataInst;
|
||||
when others =>
|
||||
O_memOp <= "00000";
|
||||
O_regDwe <= '1';
|
||||
O_dataIMM <= I_dataInst(IMM_I_START downto IMM_S_B_END)
|
||||
& "0000000";
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
|
Loading…
Add table
Reference in a new issue