OpenCores
URL https://opencores.org/ocsvn/plasma/plasma/trunk

Subversion Repositories plasma

[/] [plasma/] [trunk/] [vhdl/] [mem_ctrl.vhd] - Rev 368

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

---------------------------------------------------------------------
-- TITLE: Memory Controller
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 1/31/01
-- FILENAME: mem_ctrl.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
--    Software 'as is' without warranty.  Author liable for nothing.
-- DESCRIPTION:
--    Memory controller for the Plasma CPU.
--    Supports Big or Little Endian mode.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity mem_ctrl is
   port(clk          : in std_logic;
        reset_in     : in std_logic;
        pause_in     : in std_logic;
        nullify_op   : in std_logic;
        address_pc   : in std_logic_vector(31 downto 2);
        opcode_out   : out std_logic_vector(31 downto 0);
 
        address_in   : in std_logic_vector(31 downto 0);
        mem_source   : in mem_source_type;
        data_write   : in std_logic_vector(31 downto 0);
        data_read    : out std_logic_vector(31 downto 0);
        pause_out    : out std_logic;
 
        address_next : out std_logic_vector(31 downto 2);
        byte_we_next : out std_logic_vector(3 downto 0);
 
        address      : out std_logic_vector(31 downto 2);
        byte_we      : out std_logic_vector(3 downto 0);
        data_w       : out std_logic_vector(31 downto 0);
        data_r       : in std_logic_vector(31 downto 0));
end; --entity mem_ctrl
 
architecture logic of mem_ctrl is
   --"00" = big_endian; "11" = little_endian
   constant ENDIAN_MODE   : std_logic_vector(1 downto 0) := "00";
   signal opcode_reg      : std_logic_vector(31 downto 0);
   signal next_opcode_reg : std_logic_vector(31 downto 0);
   signal address_reg     : std_logic_vector(31 downto 2);
   signal byte_we_reg     : std_logic_vector(3 downto 0);
 
   signal mem_state_reg   : std_logic;
   constant STATE_ADDR    : std_logic := '0';
   constant STATE_ACCESS  : std_logic := '1';
 
begin
 
mem_proc: process(clk, reset_in, pause_in, nullify_op, 
                  address_pc, address_in, mem_source, data_write, 
                  data_r, opcode_reg, next_opcode_reg, mem_state_reg,
                  address_reg, byte_we_reg)
   variable address_var    : std_logic_vector(31 downto 2);
   variable data_read_var  : std_logic_vector(31 downto 0);
   variable data_write_var : std_logic_vector(31 downto 0);
   variable opcode_next    : std_logic_vector(31 downto 0);
   variable byte_we_var    : std_logic_vector(3 downto 0);
   variable mem_state_next : std_logic;
   variable pause_var      : std_logic;
   variable bits           : std_logic_vector(1 downto 0);
begin
   byte_we_var := "0000";
   pause_var := '0';
   data_read_var := ZERO;
   data_write_var := ZERO;
   mem_state_next := mem_state_reg;
   opcode_next := opcode_reg;
 
   case mem_source is
   when MEM_READ32 =>
      data_read_var := data_r;
 
   when MEM_READ16 | MEM_READ16S =>
      if address_in(1) = ENDIAN_MODE(1) then
         data_read_var(15 downto 0) := data_r(31 downto 16);
      else
         data_read_var(15 downto 0) := data_r(15 downto 0);
      end if;
      if mem_source = MEM_READ16 or data_read_var(15) = '0' then
         data_read_var(31 downto 16) := ZERO(31 downto 16);
      else
         data_read_var(31 downto 16) := ONES(31 downto 16);
      end if;
 
   when MEM_READ8 | MEM_READ8S =>
      bits := address_in(1 downto 0) xor ENDIAN_MODE;
      case bits is
      when "00" => data_read_var(7 downto 0) := data_r(31 downto 24);
      when "01" => data_read_var(7 downto 0) := data_r(23 downto 16);
      when "10" => data_read_var(7 downto 0) := data_r(15 downto 8);
      when others => data_read_var(7 downto 0) := data_r(7 downto 0);
      end case;
      if mem_source = MEM_READ8 or data_read_var(7) = '0' then
         data_read_var(31 downto 8) := ZERO(31 downto 8);
      else
         data_read_var(31 downto 8) := ONES(31 downto 8);
      end if;
 
   when MEM_WRITE32 =>
      data_write_var := data_write;
      byte_we_var := "1111";
 
   when MEM_WRITE16 =>
      data_write_var := data_write(15 downto 0) & data_write(15 downto 0);
      if address_in(1) = ENDIAN_MODE(1) then
         byte_we_var := "1100";
      else
         byte_we_var := "0011";
      end if;
 
   when MEM_WRITE8 =>
      data_write_var := data_write(7 downto 0) & data_write(7 downto 0) &
                  data_write(7 downto 0) & data_write(7 downto 0);
      bits := address_in(1 downto 0) xor ENDIAN_MODE;
      case bits is
      when "00" =>
         byte_we_var := "1000"; 
      when "01" => 
         byte_we_var := "0100"; 
      when "10" =>
         byte_we_var := "0010"; 
      when others =>
         byte_we_var := "0001"; 
      end case;
 
   when others =>
   end case;
 
   if mem_source = MEM_FETCH then --opcode fetch
      address_var := address_pc;
      opcode_next := data_r;
      mem_state_next := STATE_ADDR;
   else
      if mem_state_reg = STATE_ADDR then
         if pause_in = '0' then
            address_var := address_in(31 downto 2);
            mem_state_next := STATE_ACCESS;
            pause_var := '1';
         else
            address_var := address_pc;
            byte_we_var := "0000";
         end if;
      else  --STATE_ACCESS
         if pause_in = '0' then
            address_var := address_pc;
            opcode_next := next_opcode_reg;
            mem_state_next := STATE_ADDR;
            byte_we_var := "0000";
         else
            address_var := address_in(31 downto 2);
            byte_we_var := "0000";
         end if;
      end if;
   end if;
 
   if nullify_op = '1' and pause_in = '0' then
      opcode_next := ZERO;  --NOP after beql
   end if;
 
   if reset_in = '1' then
      mem_state_reg <= STATE_ADDR;
      opcode_reg <= ZERO;
      next_opcode_reg <= ZERO;
      address_reg <= ZERO(31 downto 2);
      byte_we_reg <= "0000";
   elsif rising_edge(clk) then
      if pause_in = '0' then
         address_reg <= address_var;
         byte_we_reg <= byte_we_var;
         mem_state_reg <= mem_state_next;
         opcode_reg <= opcode_next;
         if mem_state_reg = STATE_ADDR then
            next_opcode_reg <= data_r;
         end if;
      end if;
   end if;
 
   opcode_out <= opcode_reg;
   data_read <= data_read_var;
   pause_out <= pause_var;
 
   address_next <= address_var;
   byte_we_next <= byte_we_var;
 
   address <= address_reg;
   byte_we <= byte_we_reg;
   data_w <= data_write_var;
 
end process; --data_proc
 
end; --architecture logic
 

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.