mirror of
https://github.com/Domipheus/RPU.git
synced 2025-04-18 19:15:13 -04:00
Updated ISA support to RV32IMZcsr - Passes riscv-compliance. Integer divide/rem in 34 cycles. Integer multiply in 2 cycles (when using xilinx dsp blocks!) Saved multiple cycles from fetch/memory load stages by short-cutting the start of memory requests. Compliant misaligned exceptions for jumps,loads and stores. Addrs starting 0xFxxxxxxx ignore alignment requests (assumes mmio space). Added CSRs for riscv-compliance requirements. Source ran through a formatter for ease of use.
127 lines
No EOL
4.5 KiB
VHDL
127 lines
No EOL
4.5 KiB
VHDL
----------------------------------------------------------------------------------
|
|
-- 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.
|
|
--
|
|
----------------------------------------------------------------------------------
|
|
-- Copyright 2016,2018,2019,2020 Colin Riley
|
|
--
|
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
|
-- you may not use this file except in compliance with the License.
|
|
-- You may obtain a copy of the License at
|
|
--
|
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
|
--
|
|
-- Unless required by applicable law or agreed to in writing, software
|
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
-- See the License for the specific language governing permissions and
|
|
-- limitations under the License.
|
|
----------------------------------------------------------------------------------
|
|
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.all;
|
|
|
|
use ieee.numeric_std.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);
|
|
I_signExtend : in STD_LOGIC;
|
|
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 outdata : 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';
|
|
outdata <= X"ABCDEFEE";
|
|
if I_dataWe = '0' then
|
|
state <= 1;-- read
|
|
else
|
|
state <= 2;-- write
|
|
end if;
|
|
elsif state = 1 then
|
|
cmd <= '0';
|
|
if MEM_I_dataReady = '1' then
|
|
O_dataReady <= '1';
|
|
-- sign extend, if required
|
|
if I_signExtend = '1' then
|
|
if I_dataByteEn = F2_MEM_LS_SIZE_W then
|
|
outdata <= MEM_I_data;
|
|
elsif I_dataByteEn = F2_MEM_LS_SIZE_H then
|
|
outdata <= std_logic_vector(resize(signed(MEM_I_data(15 downto 0)), XLEN));
|
|
elsif I_dataByteEn = F2_MEM_LS_SIZE_B then
|
|
outdata <= std_logic_vector(resize(signed(MEM_I_data(7 downto 0)), XLEN));
|
|
end if;
|
|
else
|
|
outdata <= MEM_I_data;
|
|
end if;
|
|
state <= 2;
|
|
end if;
|
|
elsif state = 2 then
|
|
cmd <= '0';
|
|
state <= 0;
|
|
O_dataReady <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
O_data <= outdata;
|
|
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; |