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

Subversion Repositories marca

[/] [marca/] [trunk/] [vhdl/] [mem.vhd] - Rev 8

Compare with Previous | Blame | View Log

--  This file is part of the marca processor.
--  Copyright (C) 2007 Wolfgang Puffitsch
 
--  This program is free software; you can redistribute it and/or modify it
--  under the terms of the GNU Library General Public License as published
--  by the Free Software Foundation; either version 2, 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
--  Library General Public License for more details.
 
--  You should have received a copy of the GNU Library General Public
--  License along with this program; if not, write to the Free Software
--  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
-------------------------------------------------------------------------------
-- MARCA fetch stage
-------------------------------------------------------------------------------
-- architecture for the instruction-fetch pipeline stage
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
-- Wolfgang Puffitsch
-- Computer Architecture Lab, Group 3
-------------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
use work.marca_pkg.all;
use work.sc_pkg.all;
 
architecture behaviour of mem is
 
type WAIT_STATE is (WAIT_LOAD_EVEN,  WAIT_LOAD_ODD,
                    WAIT_LOADL_EVEN, WAIT_LOADL_ODD,
                    WAIT_LOADH_EVEN, WAIT_LOADH_ODD,
                    WAIT_LOADB_EVEN, WAIT_LOADB_ODD,
                    WAIT_STORE,
                    WAIT_NONE);
 
signal state      : WAIT_STATE;
signal next_state : WAIT_STATE;
 
signal old_data   : std_logic_vector(REG_WIDTH-1 downto 0);
signal next_data  : std_logic_vector(REG_WIDTH-1 downto 0);
 
component data_memory
  port (
    clken   : in  std_logic;
    clock   : in  std_logic;
    wren    : in  std_logic;
    address : in  std_logic_vector (ADDR_WIDTH-2 downto 0);
    data    : in  std_logic_vector (DATA_WIDTH-1 downto 0);
    q       : out std_logic_vector (DATA_WIDTH-1 downto 0));
end component;
 
signal ram_enable : std_logic;
 
signal wren0 : std_logic;
signal a0 : std_logic_vector(ADDR_WIDTH-2 downto 0);
signal d0 : std_logic_vector(DATA_WIDTH-1 downto 0);
signal q0 : std_logic_vector(DATA_WIDTH-1 downto 0);
 
signal wren1 : std_logic;
signal a1 : std_logic_vector(ADDR_WIDTH-2 downto 0);
signal d1 : std_logic_vector(DATA_WIDTH-1 downto 0);
signal q1 : std_logic_vector(DATA_WIDTH-1 downto 0);
 
component data_rom
  generic (
    init_file : string);
  port (
    clken   : in  std_logic;
    clock   : in  std_logic;
    address : in  std_logic_vector (RADDR_WIDTH-2 downto 0);
    q       : out std_logic_vector (RDATA_WIDTH-1 downto 0));
end component;
 
signal rom_enable : std_logic;
 
signal ra0 : std_logic_vector(RADDR_WIDTH-2 downto 0);
signal rq0 : std_logic_vector(RDATA_WIDTH-1 downto 0);
 
signal ra1 : std_logic_vector(RADDR_WIDTH-2 downto 0);
signal rq1 : std_logic_vector(RDATA_WIDTH-1 downto 0);
 
 
signal sc_input  : SC_IN;
signal sc_output : SC_OUT;
 
component sc_uart
  generic (
    clock_freq : integer;
    baud_rate  : integer;
    txf_depth  : integer; txf_thres  : integer;
    rxf_depth  : integer; rxf_thres  : integer);
  port (
    clock  : in  std_logic;
    reset  : in  std_logic;
    input  : in  SC_IN;
    output : out SC_OUT;
    intr   : out std_logic;
    txd    : out std_logic;
    rxd    : in  std_logic;
    nrts   : out std_logic;
    ncts   : in  std_logic);
end component;
 
signal uart_input  : SC_IN;
signal uart_output : SC_OUT;
 
begin  -- behaviour
 
  intrs(VEC_COUNT-1 downto 4) <= (others => '0');
 
  data_memory_0_unit : data_memory
    port map (
      clken     => ram_enable,
      clock     => clock,
      wren      => wren0,
      address   => a0,
      data      => d0,
      q         => q0);
 
  data_memory_1_unit : data_memory
    port map (
      clken     => ram_enable,
      clock     => clock,
      wren      => wren1,
      address   => a1,
      data      => d1,
      q         => q1);
 
  data_rom_0_unit : data_rom
    generic map (
      init_file => "../vhdl/rom0.mif")
    port map (
      clken     => rom_enable,
      clock     => clock,
      address   => ra0,
      q         => rq0);
 
  data_rom_1_unit : data_rom
    generic map (
      init_file => "../vhdl/rom1.mif")
    port map (
      clken     => rom_enable,
      clock     => clock,
      address   => ra1,
      q         => rq1);
 
  uart_unit : sc_uart
    generic map (
      clock_freq => CLOCK_FREQ,
      baud_rate => UART_BAUD_RATE,
      txf_depth => 2, txf_thres => 1,
      rxf_depth => 2, rxf_thres => 1)
    port map (
      clock => clock,
      reset => reset,
      input => uart_input,
      output => uart_output,
      intr => intrs(UART_INTR),
      txd => ext_out(UART_TXD),
      rxd => ext_in(UART_RXD),
      nrts => ext_out(UART_NRTS),
      ncts => ext_in(UART_NCTS));
 
  syn_proc: process (clock, reset)
  begin  -- process syn_proc
    if reset = RESET_ACTIVE then                 -- asynchronous reset (active low)
      state <= WAIT_NONE;
      old_data <= (others => '0');
    elsif clock'event and clock = '1' then  -- rising clock edge
      state <= next_state;
      old_data <= next_data;
    end if;
  end process syn_proc;
 
  business: process (next_state)
  begin  -- process business
    if next_state /= WAIT_NONE then
      busy <= '1';
    else
      busy <= '0';
    end if;
  end process business;
 
  sc_mux: process (address, sc_input,
                   uart_output)
  begin  -- process sc_mux
 
    uart_input <= SC_IN_NULL;
    sc_output  <= SC_OUT_NULL;
 
    case address(REG_WIDTH-1 downto SC_ADDR_WIDTH+1) is
      when UART_BASE_ADDR =>
        uart_input <= sc_input;
        sc_output <= uart_output;
      when others => null;
    end case;
 
  end process sc_mux;
 
  readwrite: process (state, op, address, data, old_data, q0, q1, rq0, rq1, sc_output)
  begin  -- process readwrite
    exc <= '0';
 
    ram_enable <= '0';
 
    wren0 <= '0';
    wren1 <= '0';
 
    a0 <= (others => '0');
    d0 <= (others => '0');
 
    a1 <= (others => '0');
    d1 <= (others => '0');
 
    rom_enable <= '0';
 
    ra0 <= (others => '0');
    ra1 <= (others => '0');
 
    sc_input <= SC_IN_NULL;
 
    result <= (others => '0');
 
    next_state <= WAIT_NONE;
    next_data <= data;
 
    if unsigned(address) >= unsigned(MEM_MIN_ADDR)
      and unsigned(address) <= unsigned(MEM_MAX_ADDR) then
 
      -- regular memory access
      if op /= MEM_NOP then
        ram_enable <= '1';
      end if;
 
      case state is
        when WAIT_LOAD_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q1;
                               result(REG_WIDTH/2-1 downto 0) <= q0;
                               next_state <= WAIT_NONE;
 
        when WAIT_LOAD_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q0;
                              result(REG_WIDTH/2-1 downto 0) <= q1;
                              next_state <= WAIT_NONE;
 
        when WAIT_LOADL_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2);
                                result(REG_WIDTH/2-1 downto 0) <= q0;
                                next_state <= WAIT_NONE;
 
        when WAIT_LOADL_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2);
                               result(REG_WIDTH/2-1 downto 0) <= q1;
                               next_state <= WAIT_NONE;
 
        when WAIT_LOADH_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q0;
                                result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0);
                                next_state <= WAIT_NONE;
 
        when WAIT_LOADH_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q1;
                               result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0);
                               next_state <= WAIT_NONE;
 
        when WAIT_LOADB_EVEN => result <= std_logic_vector(resize(signed(q0), REG_WIDTH));
                                next_state <= WAIT_NONE;
 
        when WAIT_LOADB_ODD => result <= std_logic_vector(resize(signed(q1), REG_WIDTH));
                               next_state <= WAIT_NONE;
 
        when WAIT_NONE =>
          case op is
            when MEM_LOAD => if address(0) = '0' then
                               a0 <= address(ADDR_WIDTH-1 downto 1);
                               a1 <= address(ADDR_WIDTH-1 downto 1);
                               next_state <= WAIT_LOAD_EVEN;                         
                             else
                               a1 <= address(ADDR_WIDTH-1 downto 1);
                               a0 <= std_logic_vector(unsigned(address(ADDR_WIDTH-1 downto 1)) + 1);
                               next_state <= WAIT_LOAD_ODD;
                             end if;
            when MEM_LOADL => if address(0) = '0' then
                                a0 <= address(ADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADL_EVEN;
                              else
                                a1 <= address(ADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADL_ODD;
                              end if;
            when MEM_LOADH => if address(0) = '0' then
                                a0 <= address(ADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADH_EVEN;
                              else
                                a1 <= address(ADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADH_ODD;
                              end if;
            when MEM_LOADB => if address(0) = '0' then
                                a0 <= address(ADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADB_EVEN;
                              else
                                a1 <= address(ADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADB_ODD;
                              end if;
            when MEM_STORE => if address(0) = '0' then
                                wren0 <= '1';
                                wren1 <= '1';
                                a0 <= address(ADDR_WIDTH-1 downto 1);
                                a1 <= address(ADDR_WIDTH-1 downto 1);
                                d0 <= data(REG_WIDTH/2-1 downto 0);
                                d1 <= data(REG_WIDTH-1 downto REG_WIDTH/2);
                                next_state <= WAIT_NONE;
                              else
                                wren0 <= '1';
                                wren1 <= '1';
                                a1 <= address(ADDR_WIDTH-1 downto 1);
                                a0 <= std_logic_vector(unsigned(address(ADDR_WIDTH-1 downto 1)) + 1);
                                d1 <= data(REG_WIDTH/2-1 downto 0);
                                d0 <= data(REG_WIDTH-1 downto REG_WIDTH/2);
                                next_state <= WAIT_NONE;
                              end if;
            when MEM_STOREL => if address(0) = '0' then
                                 wren0 <= '1';
                                 a0 <= address(ADDR_WIDTH-1 downto 1);
                                 d0 <= data(REG_WIDTH/2-1 downto 0);
                                 next_state <= WAIT_NONE;
                               else
                                 wren1 <= '1';
                                 a1 <= address(ADDR_WIDTH-1 downto 1);
                                 d1 <= data(REG_WIDTH/2-1 downto 0);
                                 next_state <= WAIT_NONE;
                               end if;
            when MEM_STOREH => if address(0) = '0' then
                                 wren0 <= '1';
                                 a0 <= address(ADDR_WIDTH-1 downto 1);
                                 d0 <= data(REG_WIDTH-1 downto REG_WIDTH/2);
                                 next_state <= WAIT_NONE;
                               else
                                 wren1 <= '1';
                                 a1 <= address(ADDR_WIDTH-1 downto 1);
                                 d1 <= data(REG_WIDTH-1 downto REG_WIDTH/2);
                                 next_state <= WAIT_NONE;
                               end if;
            when MEM_NOP => next_state <= WAIT_NONE;
            when others => null;
          end case;
        when others => null;
      end case;
 
    elsif unsigned(address) >= unsigned(ROM_MIN_ADDR)
      and unsigned(address) <= unsigned(ROM_MAX_ADDR) then
 
      -- accessing the ROM
      if op /= MEM_NOP then
        rom_enable <= '1';
      end if;
 
      case state is
        when WAIT_LOAD_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq1;
                               result(REG_WIDTH/2-1 downto 0) <= rq0;
                               next_state <= WAIT_NONE;
 
        when WAIT_LOAD_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq0;
                              result(REG_WIDTH/2-1 downto 0) <= rq1;
                              next_state <= WAIT_NONE;
 
        when WAIT_LOADL_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2);
                                result(REG_WIDTH/2-1 downto 0) <= rq0;
                                next_state <= WAIT_NONE;
 
        when WAIT_LOADL_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2);
                               result(REG_WIDTH/2-1 downto 0) <= rq1;
                               next_state <= WAIT_NONE;
 
        when WAIT_LOADH_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq0;
                                result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0);
                                next_state <= WAIT_NONE;
 
        when WAIT_LOADH_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq1;
                               result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0);
                               next_state <= WAIT_NONE;
 
        when WAIT_LOADB_EVEN => result <= std_logic_vector(resize(signed(rq0), REG_WIDTH));
                                next_state <= WAIT_NONE;
 
        when WAIT_LOADB_ODD => result <= std_logic_vector(resize(signed(rq1), REG_WIDTH));
                               next_state <= WAIT_NONE;
 
        when WAIT_NONE =>
          case op is
            when MEM_LOAD => if address(0) = '0' then
                               ra0 <= address(RADDR_WIDTH-1 downto 1);
                               ra1 <= address(RADDR_WIDTH-1 downto 1);
                               next_state <= WAIT_LOAD_EVEN;                         
                             else
                               ra1 <= address(RADDR_WIDTH-1 downto 1);
                               ra0 <= std_logic_vector(unsigned(address(RADDR_WIDTH-1 downto 1)) + 1);
                               next_state <= WAIT_LOAD_ODD;
                             end if;
            when MEM_LOADL => if address(0) = '0' then
                                ra0 <= address(RADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADL_EVEN;
                              else
                                ra1 <= address(RADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADL_ODD;
                              end if;
            when MEM_LOADH => if address(0) = '0' then
                                ra0 <= address(RADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADH_EVEN;
                              else
                                ra1 <= address(RADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADH_ODD;
                              end if;
            when MEM_LOADB => if address(0) = '0' then
                                ra0 <= address(RADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADB_EVEN;
                              else
                                ra1 <= address(RADDR_WIDTH-1 downto 1);
                                next_state <= WAIT_LOADB_ODD;
                              end if;
            when MEM_NOP => next_state <= WAIT_NONE;
            when others => exc <= '1';  -- inhibit invalid operations
          end case;
        when others => null;
      end case;      
 
    elsif unsigned(address) >= unsigned(SC_MIN_ADDR)
      and unsigned(address) <= unsigned(SC_MAX_ADDR)
      and address(0) = '0' then
 
      -- access via SimpCon interface
      case state is
 
        when WAIT_LOAD_EVEN =>
          if sc_output.rdy_cnt /= "00" then
            next_state <= WAIT_LOAD_EVEN;
          else
            result <= sc_output.rd_data;
            next_state <= WAIT_NONE;
          end if;          
 
        when WAIT_STORE =>
          if sc_output.rdy_cnt /= "00" then
            next_state <= WAIT_STORE;
          else
            next_state <= WAIT_NONE;
          end if;          
 
        when WAIT_NONE =>
          case op is
 
            when MEM_LOAD =>
              sc_input.address <= address(SC_ADDR_WIDTH downto 1);
              sc_input.wr      <= '0';
              sc_input.wr_data <= (others => '0');
              sc_input.rd      <= '1';
              next_state <= WAIT_LOAD_EVEN;
 
            when MEM_STORE =>
              sc_input.address <= address(SC_ADDR_WIDTH downto 1);
              sc_input.wr      <= '1';
              sc_input.wr_data <= data;
              sc_input.rd      <= '0';
              next_state <= WAIT_STORE;
 
            when MEM_NOP => next_state <= WAIT_NONE;
 
            when others => exc <= '1';   -- inhibit invalid operations
 
          end case;
        when others => null;
      end case;
 
    else
      -- invalid address and/or alignment
      if op /= MEM_NOP then
        exc <= '1';
      end if;
    end if;   
 
  end process readwrite;
 
end behaviour;
 

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.