OpenCores

Subversion Repositories storm_core

[/] [storm_core/] [trunk/] [rtl/] [REG_FILE.vhd] - Rev 23

Go to most recent revision | Compare with Previous | Blame | View Log

-- #######################################################
-- #     < STORM CORE PROCESSOR by Stephan Nolting >     #
-- # *************************************************** #
-- #         30x32-Bit Banked 1w3r Register File         #
-- #            (+ address translation unit)             #
-- # *************************************************** #
-- # Last modified: 28.05.2011                           #
-- #######################################################
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
library work;
use work.STORM_core_package.all;
 
entity REG_FILE is
	port	(
-- ###############################################################################################
-- ##       Global Control                                                                      ##
-- ###############################################################################################
 
				CLK_I       : in  STD_LOGIC; -- global clock network
				G_HALT_I    : in  STD_LOGIC; -- global halt line
				RST_I       : in  STD_LOGIC; -- global reset network
 
-- ###############################################################################################
-- ##       Local Control                                                                       ##
-- ###############################################################################################
 
				CTRL_I      : in  STD_LOGIC_VECTOR(CTRL_MSB downto 0); -- control lines
				OP_ADR_I    : in  STD_LOGIC_VECTOR(14 downto 0);       -- operand addresses
				MODE_I      : in  STD_LOGIC_VECTOR(04 downto 0);       -- current operation mode
				USR_RD_I    : in  STD_LOGIC;                           -- use USR bank
 
-- ###############################################################################################
-- ##       Operand Connection                                                                  ##
-- ###############################################################################################
 
				WB_DATA_I   : in  STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0); -- write back data path
				REG_PC_I    : in  STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0); -- current program counter
 
				OP_A_O      : out STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0); -- register A output
				OP_B_O      : out STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0); -- register B output
				OP_C_O      : out STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0)  -- register C output
 
			);
end REG_FILE;
 
architecture REG_FILE_STRUCTURE of REG_FILE is
 
	-- Data Register File --
	type   REG_FILE_TYPE is array (0 to 31) of STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0);
	signal REG_FILE : REG_FILE_TYPE := (others => (others => '0'));
 
	-- Memory <-> Register Allocation Map
	-- ------------------------------------------------------------------------
	-- 00: USR32 R0		10: USR32 R10		20: FIQ32 R13		30: Dummy Reg
	-- 01: USR32 R1		11: USR32 R11		21: FIQ32 R14 LR	31: Dummy Reg
	-- 02: USR32 R2		12: USR32 R12		22: SVP32 R13
	-- 03: USR32 R3		13: USR32 R13		23: SVP32 R14 LR
	-- 04: USR32 R4		14: USR32 R14 LR	24: ABT32 R13
	-- 05: USR32 R5		15: FIQ32 R8		25: ABT32 R14 LR
	-- 06: USR32 R6		16: FIQ32 R9		26: IRQ32 R13
	-- 07: USR32 R7		17: FIQ32 R10		27: IRQ32 R14 LR
	-- 08: USR32 R8		18: FIQ32 R11		28: UND32 R13
	-- 09: USR32 R9		19: FIQ32 R12		29: UND32 R14 LR
 
	-- Address Busses --
	signal R_ADR_PORT_A, R_ADR_PORT_B, R_ADR_PORT_C : STD_LOGIC_VECTOR(4 downto 0);
	signal W_ADR_PORT, MODE_INT                     : STD_LOGIC_VECTOR(4 downto 0);
 
	-- Address Translator --
	component ADR_TRANSLATION_UNIT
		port	(
					REG_ADR_I   : in  STD_LOGIC_VECTOR(3 downto 0);
					MODE_I      : in  STD_LOGIC_VECTOR(4 downto 0);
					ADR_O       : out STD_LOGIC_VECTOR(4 downto 0)
				);
	end component;
 
begin
 
	-- Register File Write Access ---------------------------------------------------------------------
	-- ---------------------------------------------------------------------------------------------------
 
		--- Write Access Data Port ---
		write_access_data_port:
			ADR_TRANSLATION_UNIT
				port map (
								REG_ADR_I => CTRL_I(CTRL_RD_3 downto CTRL_RD_0),
								MODE_I    => CTRL_I(CTRL_MODE_4 downto CTRL_MODE_0),
								ADR_O     => W_ADR_PORT
							);
 
		--- Clock Triggered Write ---
		SYNCHRONOUS_MEM_WRITE: process(CLK_I, W_ADR_PORT, WB_DATA_I, CTRL_I)
		begin
			if rising_edge(CLK_I) then
				if (G_HALT_I = '0') then
					if ((CTRL_I(CTRL_EN) = '1') and (CTRL_I(CTRL_WB_EN)) = '1') then
						REG_FILE(to_integer(unsigned(W_ADR_PORT))) <= WB_DATA_I;
					end if;
				end if;
			end if;
		end process SYNCHRONOUS_MEM_WRITE;
 
 
 
	-- Register File Read Access ----------------------------------------------------------------------
	-- ---------------------------------------------------------------------------------------------------
 
		--- Force USR bank read ---
		MODE_INT <= MODE_I when (USR_RD_I = '0') else User32_MODE;
 
		--- Read Access Port A ---
		read_access_port_a:
			ADR_TRANSLATION_UNIT
				port map (
								REG_ADR_I => OP_ADR_I(OP_A_ADR_3 downto OP_A_ADR_0),
								MODE_I    => MODE_INT,
								ADR_O     => R_ADR_PORT_A
							);
 
		--- Read Access Port B ---
		read_access_port_b:
			ADR_TRANSLATION_UNIT
				port map (
								REG_ADR_I => OP_ADR_I(OP_B_ADR_3 downto OP_B_ADR_0),
								MODE_I    => MODE_INT,
								ADR_O     => R_ADR_PORT_B
							);
 
		--- Read Access Port C ---
		read_access_port_c:
			ADR_TRANSLATION_UNIT
				port map (
								REG_ADR_I => OP_ADR_I(OP_C_ADR_3 downto OP_C_ADR_0),
								MODE_I    => MODE_INT,
								ADR_O     => R_ADR_PORT_C
							);
 
 
		--- Memory Read Access ---
		OP_A_O <= REG_FILE(to_integer(unsigned(R_ADR_PORT_A))) when (OP_ADR_I(OP_A_ADR_3 downto OP_A_ADR_0) /= C_PC_ADR) else REG_PC_I;
		OP_B_O <= REG_FILE(to_integer(unsigned(R_ADR_PORT_B))) when (OP_ADR_I(OP_B_ADR_3 downto OP_B_ADR_0) /= C_PC_ADR) else REG_PC_I;
		OP_C_O <= REG_FILE(to_integer(unsigned(R_ADR_PORT_C))) when (OP_ADR_I(OP_C_ADR_3 downto OP_C_ADR_0) /= C_PC_ADR) else REG_PC_I;
 
 
end REG_FILE_STRUCTURE;
 
 
----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------
 
 
-- #######################################################
-- #     < STORM CORE PROCESSOR by Stephan Nolting >     #
-- # *************************************************** #
-- #         REG-FILE Address Translation Unit           #
-- # *************************************************** #
-- # Version 1.1, 28.05.2011                             #
-- #######################################################
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
library work;
use work.STORM_core_package.all;
 
entity ADR_TRANSLATION_UNIT is
	port	(
				-- Register Address Input --
				--------------------------------------------------
				REG_ADR_I   : in  STD_LOGIC_VECTOR(3 downto 0);
 
				-- MODE Input --
				--------------------------------------------------
				MODE_I      : in  STD_LOGIC_VECTOR(4 downto 0);
 
				-- Memory Address Output --
				--------------------------------------------------
				ADR_O       : out STD_LOGIC_VECTOR(4 downto 0)
			);
end ADR_TRANSLATION_UNIT;
 
architecture ADRTU_STRUCTURE of ADR_TRANSLATION_UNIT is
 
begin
 
	-- Address Translator -----------------------------------------------------------------------------
	-- ---------------------------------------------------------------------------------------------------
		ADR_TRANSLATOR: process(REG_ADR_I, MODE_I)
			variable VIRT_REG_SEL : STD_LOGIC_VECTOR(15 downto 0);
			variable REAL_REG_SEL : STD_LOGIC_VECTOR(31 downto 0);
		begin
 
			--- One-Hot Virtual Register Select ---
			case (REG_ADR_I) is
				when "0000" => VIRT_REG_SEL := "0000000000000001"; -- R0_<mode>
				when "0001" => VIRT_REG_SEL := "0000000000000010"; -- R1_<mode>
				when "0010" => VIRT_REG_SEL := "0000000000000100"; -- R2_<mode>
				when "0011" => VIRT_REG_SEL := "0000000000001000"; -- R3_<mode>
				when "0100" => VIRT_REG_SEL := "0000000000010000"; -- R4_<mode>
				when "0101" => VIRT_REG_SEL := "0000000000100000"; -- R5_<mode>
				when "0110" => VIRT_REG_SEL := "0000000001000000"; -- R6_<mode>
				when "0111" => VIRT_REG_SEL := "0000000010000000"; -- R7_<mode>
				when "1000" => VIRT_REG_SEL := "0000000100000000"; -- R8_<mode>
				when "1001" => VIRT_REG_SEL := "0000001000000000"; -- R9_<mode>
				when "1010" => VIRT_REG_SEL := "0000010000000000"; -- R10_<mode>
				when "1011" => VIRT_REG_SEL := "0000100000000000"; -- R11_<mode>
				when "1100" => VIRT_REG_SEL := "0001000000000000"; -- R12_<mode>
				when "1101" => VIRT_REG_SEL := "0010000000000000"; -- R13_<mode>
				when "1110" => VIRT_REG_SEL := "0100000000000000"; -- R14_<mode>
				when "1111" => VIRT_REG_SEL := "1000000000000000"; -- DUMMY PC
				when others => VIRT_REG_SEL := "0000000000000000"; -- undefined
			end case;
 
			--- Address Mapping: Virtual Register -> Real Register ---
			REAL_REG_SEL := (others => '0');
			REAL_REG_SEL(07 downto 00) := VIRT_REG_SEL(07 downto 00); -- R0-R7 are always the same
			REAL_REG_SEL(31) := VIRT_REG_SEL(15); -- PC access = dummy access
 
			case (MODE_I) is
 
				when User32_MODE =>
					REAL_REG_SEL(14 downto 08) := VIRT_REG_SEL(14 downto 08);
 
				when FIQ32_MODE =>
					REAL_REG_SEL(21 downto 15) := VIRT_REG_SEL(14 downto 08);
 
				when Supervisor32_MODE | System32_MODE =>
					REAL_REG_SEL(12 downto 08) := VIRT_REG_SEL(12 downto 08);
					REAL_REG_SEL(23 downto 22) := VIRT_REG_SEL(14 downto 13);
 
				when Abort32_MODE =>
					REAL_REG_SEL(12 downto 08) := VIRT_REG_SEL(12 downto 08);
					REAL_REG_SEL(25 downto 24) := VIRT_REG_SEL(14 downto 13);
 
				when IRQ32_MODE =>
					REAL_REG_SEL(12 downto 08) := VIRT_REG_SEL(12 downto 08);
					REAL_REG_SEL(27 downto 26) := VIRT_REG_SEL(14 downto 13);
 
				when Undefined32_MODE =>
					REAL_REG_SEL(12 downto 08) := VIRT_REG_SEL(12 downto 08);
					REAL_REG_SEL(29 downto 28) := VIRT_REG_SEL(14 downto 13);
 
				when others =>
					REAL_REG_SEL(29 downto 00) := (others => '0');
 
			end case;
 
			--- Address Encoder ---
			case (REAL_REG_SEL) is
				when "00000000000000000000000000000001" => ADR_O <= "00000";
				when "00000000000000000000000000000010" => ADR_O <= "00001";
				when "00000000000000000000000000000100" => ADR_O <= "00010";
				when "00000000000000000000000000001000" => ADR_O <= "00011";
				when "00000000000000000000000000010000" => ADR_O <= "00100";
				when "00000000000000000000000000100000" => ADR_O <= "00101";
				when "00000000000000000000000001000000" => ADR_O <= "00110";
				when "00000000000000000000000010000000" => ADR_O <= "00111";
				when "00000000000000000000000100000000" => ADR_O <= "01000";
				when "00000000000000000000001000000000" => ADR_O <= "01001";
				when "00000000000000000000010000000000" => ADR_O <= "01010";
				when "00000000000000000000100000000000" => ADR_O <= "01011";
				when "00000000000000000001000000000000" => ADR_O <= "01100";
				when "00000000000000000010000000000000" => ADR_O <= "01101";
				when "00000000000000000100000000000000" => ADR_O <= "01110";
				when "00000000000000001000000000000000" => ADR_O <= "01111";
				when "00000000000000010000000000000000" => ADR_O <= "10000";
				when "00000000000000100000000000000000" => ADR_O <= "10001";
				when "00000000000001000000000000000000" => ADR_O <= "10010";
				when "00000000000010000000000000000000" => ADR_O <= "10011";
				when "00000000000100000000000000000000" => ADR_O <= "10100";
				when "00000000001000000000000000000000" => ADR_O <= "10101";
				when "00000000010000000000000000000000" => ADR_O <= "10110";
				when "00000000100000000000000000000000" => ADR_O <= "10111";
				when "00000001000000000000000000000000" => ADR_O <= "11000";
				when "00000010000000000000000000000000" => ADR_O <= "11001";
				when "00000100000000000000000000000000" => ADR_O <= "11010";
				when "00001000000000000000000000000000" => ADR_O <= "11011";
				when "00010000000000000000000000000000" => ADR_O <= "11100";
				when "00100000000000000000000000000000" => ADR_O <= "11101";
				when "01000000000000000000000000000000" => ADR_O <= "11110";
				when "10000000000000000000000000000000" => ADR_O <= "11111";
				when others                             => ADR_O <= "11111";
			end case;
 
		end process ADR_TRANSLATOR;
 
 
end ADRTU_STRUCTURE;

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2013 OpenCores.org, equivalent to ORSoC AB, all rights reserved. OpenCores®, registered trademark.