[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[f-cpu] Register Bank



To illustrate what I said before, I wrote a little register bank entity.
It's not the real thing (there is no scoreboard interface, it's not
SIMD capable, and register 0 isn't handled either) but it already has
3 read and 2 write ports that can be used simultaneously (except for
the special case that both writers try to write to the same register;
in that case, write port 0 has priority).

-- 
 Michael "Tired" Riepe <Michael.Riepe@stud.uni-hannover.de>
 "All I wanna do is have a little fun before I die"
-- regbank.vhdl -- Simple Register Bank
-- Copyright (C) 2001 Michael Riepe <michael@stud.uni-hannover.de>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

-- $Id$

library IEEE;
use IEEE.std_logic_1164.all;

entity Register_Bank is
	generic (
		WIDTH : natural := 64;
		NREGS : natural := 64
	);
	port (
		-- data inputs
		Write_0 : in std_ulogic_vector(WIDTH-1 downto 0);
		Write_1 : in std_ulogic_vector(WIDTH-1 downto 0);
		-- write enable (decoded)
		Write_Enable_0 : in std_ulogic_vector(NREGS-1 downto 0);
		Write_Enable_1 : in std_ulogic_vector(NREGS-1 downto 0);
		-- read enable (decoded)
		Read_Enable_0 : in std_ulogic_vector(NREGS-1 downto 0);
		Read_Enable_1 : in std_ulogic_vector(NREGS-1 downto 0);
		Read_Enable_2 : in std_ulogic_vector(NREGS-1 downto 0);
		-- clock/reset
		Clk : in std_ulogic;
		Rst : in std_ulogic;
	--
		-- data outputs
		Read_0 : out std_ulogic_vector(WIDTH-1 downto 0);
		Read_1 : out std_ulogic_vector(WIDTH-1 downto 0);
		Read_2 : out std_ulogic_vector(WIDTH-1 downto 0)
	);
end Register_Bank;

architecture Behave_1 of Register_Bank is
	subtype reg is std_ulogic_vector(WIDTH-1 downto 0);
	type bank is array (natural range <>) of reg;

	function read_reg (Regs : bank;
					  Enable : std_ulogic_vector) return reg is
		alias myrb : bank(Regs'length-1 downto 0) is Regs;
		alias myen : std_ulogic_vector(Enable'length-1 downto 0) is Enable;
	begin
		assert Regs'length = Enable'length;
		for i in myrb'range loop
			if to_X01(myen(i)) = '1' then
				return myrb(i);
			end if;
		end loop;
		return reg'(others => 'Z');	-- port unused
	end read_reg;

	signal Regs : bank(NREGS-1 downto 0);
begin
	-- readers (combinatorial)
	Read_0 <= read_reg(Regs, Read_Enable_0);
	Read_1 <= read_reg(Regs, Read_Enable_1);
	Read_2 <= read_reg(Regs, Read_Enable_2);

	-- writers (sequential)
	process (Write_0, Write_1, Write_Enable_0, Write_Enable_1, Clk, Rst)
	begin
		if Rst = '1' then
			Regs <= (others => (others => '0'));
		elsif rising_edge(Clk) then
			for i in NREGS-1 downto 0 loop
				if to_X01(Write_Enable_0(i)) = '1' then
					Regs(i) <= Write_0;
				elsif to_X01(Write_Enable_1(i)) = '1' then
					Regs(i) <= Write_1;
				else
					-- register remains unchanged
				end if;
			end loop;
		end if;
	end process;
end Behave_1;