DLX-Microprocessor / components / registerfile.vhd
registerfile.vhd
Raw
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

use work.constants.all;

entity register_file is
  generic (
    NBit : integer := numBit; -- number of bit per register
    NReg : integer := numReg -- number of memory locations/registers
  );
  port (
    CLK     : in std_logic; -- Clock Signal
    RESET   : in std_logic; -- Reset Signal
    ENABLE  : in std_logic; -- Enable Signal
    RD1     : in std_logic; -- Read 1 Signal
    RD2     : in std_logic; -- Read 2 Signal
    WR      : in std_logic; -- Write Signal
    ADD_WR  : in std_logic_vector(integer(ceil(log2(real(NReg)))) - 1 downto 0); -- Write Address
    ADD_RD1 : in std_logic_vector(integer(ceil(log2(real(NReg)))) - 1 downto 0); -- Read 1 Address
    ADD_RD2 : in std_logic_vector(integer(ceil(log2(real(NReg)))) - 1 downto 0); -- Read 2 Address
    DATAIN  : in std_logic_vector(NBit - 1 downto 0); -- Data in Signal
    OUT1    : out std_logic_vector(NBit - 1 downto 0); -- Data Out 1 Signal
    OUT2    : out std_logic_vector(NBit - 1 downto 0) -- Data Out 2 Signal
  );
end register_file;

architecture A of register_file is

  component FD is
    generic (NBIT : integer := NumBit);
    port (
      D     : in std_logic_vector(NBIT - 1 downto 0);
      CK    : in std_logic;
      RESET : in std_logic;
      Q     : out std_logic_vector(NBIT - 1 downto 0)
    );
  end component;

  type REG_ARRAY is array(NReg - 1 downto 0) of std_logic_vector(NBit - 1 downto 0);
  signal REG_ARRAY_IN, REG_ARRAY_OUT : REG_ARRAY;

begin

  -- We are using the FF form the first laboratory. 
  -- We create an array of registers and connect them to the input 
  -- via REG_ARRAY_IN and to the output via REG_ARRAY_OUT

  register_file_FD_gen : for i in NReg - 1 downto 0 generate
    REG_i : FD
    generic map(
      NBIT => NBit
    )
    port map
    (
      CK    => CLK,
      RESET => RESET,
      D     => REG_ARRAY_IN(i),
      Q     => REG_ARRAY_OUT(i)
    );
  end generate;

  -- The addressing of the register file is combinatorial ad the sequential behavior
  -- is baked into the registers already (basically the multiplexer in front of a memory)
  process (WR, ENABLE, RESET, ADD_WR, DATAIN)
  begin
    if WR = '1' and ENABLE = '1' and RESET = '0' then
      REG_ARRAY_IN(to_integer(unsigned(ADD_WR))) <= DATAIN;

    elsif RESET = '1' then

      for i in NReg - 1 downto 0 loop
        REG_ARRAY_IN(i) <= (others => '0');
      end loop;
    end if;

  end process;

  -- The output logic is not combinatorial because if the RDx signal is asserted
  -- then the output is asserted on the output line, but the new value should only be 
  -- asserted on the next rising clock edge after the RD signal is put to a high value.
  -- process (CLK)
  process (ADD_RD1, ADD_RD2, ENABLE, RESET)
  begin
    if RESET = '1' then
      OUT1 <= (others => '0'); -- Reset output 1
      OUT2 <= (others => '0'); -- Reset output 2
    end if;
    -- if rising_edge(CLK) then
    if ENABLE = '1' and RESET = '0' then
      -- if the RD signal is asserted we just update the output with the 
      -- correct value of the output signlas net of the registers 
      if RD1 = '1' then
        OUT1 <= REG_ARRAY_OUT(to_integer(unsigned(ADD_RD1)));
      end if;
      if RD2 = '1' then
        OUT2 <= REG_ARRAY_OUT(to_integer(unsigned(ADD_RD2)));
      end if;
    end if;
    -- end if;
  end process;
end A;

configuration CFG_RF_BEH of register_file is
  for A
  end for;
end configuration;