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

Subversion Repositories ion

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 45 to Rev 46
    Reverse comparison

Rev 45 → Rev 46

/ion/trunk/vhdl/demo/mips_mpu.vhdl
1,3 → 1,14
--------------------------------------------------------------------------------
-- This file was generated automatically from '/src/mips_mpu2_template.vhdl'.
--------------------------------------------------------------------------------
-- Synthesizable MPU -- CPU + cache + bootstrap BRAM + UART
--
-- This module uses the 'stub' version of the cache: a cache which actually is
-- only an interface between the cpu and external static memory. This is useful
-- to test external memory interface and cache-cpu interface without the cache
-- functionality getting in the way.
--------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
5,192 → 16,76
use work.mips_pkg.all;
 
entity mips_mpu is
generic(
mult_type : string := "NONE"; -- {NONE|SEQUENTIAL}
ld_interlock : boolean := FALSE
generic (
SRAM_ADDR_SIZE : integer := 17
);
port(
clk : in std_logic;
reset : in std_logic;
interrupt : in std_logic;
 
rd_addr : out std_logic_vector(31 downto 0);
data_r : in std_logic_vector(31 downto 0);
vma_data : out std_logic;
wr_addr : 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);
-- interface to FPGA i/o devices
io_rd_data : in std_logic_vector(31 downto 0);
io_rd_addr : out std_logic_vector(31 downto 2);
io_wr_addr : out std_logic_vector(31 downto 2);
io_wr_data : out std_logic_vector(31 downto 0);
io_rd_vma : out std_logic;
io_byte_we : out std_logic_vector(3 downto 0);
-- interface to asynchronous 16-bit-wide EXTERNAL SRAM
sram_address : out std_logic_vector(SRAM_ADDR_SIZE downto 1);
sram_databus : inout std_logic_vector(15 downto 0);
sram_byte_we_n : out std_logic_vector(1 downto 0);
sram_oe_n : out std_logic;
 
-- UART
uart_rxd : in std_logic;
uart_txd : out std_logic;
 
mem_wait : in std_logic
uart_txd : out std_logic
);
end; --entity mips_mpu
 
architecture rtl of mips_mpu is
 
-- Data RAM table and interface signals ----------------------------------------
constant DATA_RAM_SIZE : integer := 256;
constant DATA_ADDR_SIZE : integer := 8;
subtype t_data_address is std_logic_vector(DATA_ADDR_SIZE-1 downto 0);
-- (this table holds one byte-slice; the RAM will have 4 of these)
type t_data_ram is array(0 to DATA_RAM_SIZE-1) of std_logic_vector(7 downto 0);
 
signal data_addr_rd : t_data_address;
signal data_addr_wr : t_data_address;
signal reset_sync : std_logic_vector(2 downto 0);
 
-- ram0 is LSB, ram3 is MSB
signal ram3 : t_data_ram := (
X"63",X"69",X"74",X"3A",X"62",X"20",X"31",X"20",
X"32",X"38",X"67",X"76",X"69",X"20",X"34",X"00",
X"0A",X"6C",X"57",X"64",X"0A",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
signal ram2 : t_data_ram := (
X"6F",X"6C",X"69",X"20",X"20",X"32",X"20",X"31",
X"39",X"0A",X"63",X"65",X"6F",X"20",X"2E",X"00",
X"0A",X"6C",X"6F",X"21",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
signal ram1 : t_data_ram := (
X"6D",X"65",X"6D",X"46",X"20",X"30",X"2D",X"31",
X"3A",X"00",X"63",X"72",X"6E",X"34",X"31",X"00",
X"48",X"6F",X"72",X"0A",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
signal ram0 : t_data_ram := (
X"70",X"20",X"65",X"65",X"32",X"31",X"2D",X"3A",
X"30",X"00",X"20",X"73",X"3A",X"2E",X"0A",X"00",
X"65",X"20",X"6C",X"0A",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
-- interface cpu-cache
signal cpu_data_rd_addr : t_word;
signal cpu_data_rd_vma : std_logic;
signal cpu_data_rd : t_word;
signal cpu_code_rd_addr : t_pc;
signal cpu_code_rd : t_word;
signal cpu_code_rd_vma : std_logic;
signal cpu_data_wr_addr : t_pc;
signal cpu_data_wr : t_word;
signal cpu_byte_we : std_logic_vector(3 downto 0);
signal cpu_mem_wait : std_logic;
 
-- interface to i/o
signal mpu_io_rd_data : std_logic_vector(31 downto 0);
signal mpu_io_wr_data : std_logic_vector(31 downto 0);
signal mpu_io_rd_addr : std_logic_vector(31 downto 2);
signal mpu_io_wr_addr : std_logic_vector(31 downto 2);
signal mpu_io_rd_vma : std_logic;
signal mpu_io_byte_we : std_logic_vector(3 downto 0);
 
-- Code RAM table and interface signals ----------------------------------------
constant CODE_RAM_SIZE : integer := 1024;
constant CODE_ADDR_SIZE : integer := 10;
subtype t_code_address is std_logic_vector(CODE_ADDR_SIZE-1 downto 0);
-- (this table holds one byte-slice; the RAM will have 4 of these)
type t_code_ram is array(0 to CODE_RAM_SIZE-1) of std_logic_vector(7 downto 0);
-- interface to UARTs
signal data_uart : t_word;
signal data_uart_status : t_word;
signal uart_tx_rdy : std_logic := '1';
signal uart_rx_rdy : std_logic := '1';
signal uart_write_tx : std_logic;
signal uart_read_rx : std_logic;
 
signal code_addr_rd : t_code_address;
 
-- ram0 is LSB, ram3 is MSB
signal rom3 : t_code_ram := (
-- Block ram
constant BRAM_SIZE : integer := 1024;
constant BRAM_ADDR_SIZE : integer := log2(BRAM_SIZE);
 
type t_bram is array(0 to BRAM_SIZE-1) of std_logic_vector(7 downto 0);
 
-- bram0 is LSB, bram3 is MSB
signal bram3 : t_bram := (
X"3C",X"27",X"3C",X"24",X"3C",X"24",X"3C",X"27",
X"AC",X"00",X"14",X"24",X"0C",X"00",X"08",X"23",
X"AF",X"AF",X"AF",X"AF",X"AF",X"AF",X"AF",X"AF",
221,7 → 116,10
X"00",X"24",X"24",X"AD",X"14",X"00",X"03",X"00",
X"3C",X"8C",X"00",X"30",X"10",X"3C",X"24",X"AC",
X"03",X"00",X"3C",X"8C",X"03",X"30",X"3C",X"8C",
X"00",X"30",X"10",X"3C",X"8C",X"03",X"00",X"00",
X"00",X"30",X"10",X"3C",X"8C",X"03",X"00",X"63",
X"69",X"74",X"3A",X"62",X"20",X"31",X"20",X"31",
X"39",X"67",X"76",X"69",X"20",X"34",X"00",X"0A",
X"6C",X"57",X"64",X"0A",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
315,12 → 213,9
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
signal rom2 : t_code_ram := (
signal bram2 : t_bram := (
X"1C",X"9C",X"05",X"A5",X"04",X"84",X"1D",X"BD",
X"A0",X"A4",X"60",X"A5",X"00",X"00",X"00",X"BD",
X"A1",X"A2",X"A3",X"A4",X"A5",X"A6",X"A7",X"A8",
351,7 → 246,10
X"00",X"C6",X"A5",X"06",X"A7",X"A4",X"E0",X"00",
X"03",X"62",X"00",X"42",X"40",X"02",X"03",X"43",
X"E0",X"00",X"02",X"42",X"E0",X"42",X"03",X"62",
X"00",X"42",X"40",X"02",X"42",X"E0",X"00",X"00",
X"00",X"42",X"40",X"02",X"42",X"E0",X"00",X"6F",
X"6C",X"69",X"20",X"20",X"32",X"20",X"31",X"30",
X"0A",X"63",X"65",X"6F",X"20",X"2E",X"00",X"0A",
X"6C",X"6F",X"21",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
445,13 → 343,10
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
signal rom1 : t_code_ram := (
X"80",X"7F",X"80",X"00",X"80",X"02",X"80",X"02",
signal bram1 : t_bram := (
X"80",X"7F",X"80",X"00",X"80",X"02",X"80",X"01",
X"00",X"18",X"FF",X"00",X"00",X"00",X"00",X"FF",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
468,8 → 363,8
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"10",X"20",X"00",X"00",
X"00",X"00",X"00",X"80",X"FF",X"00",X"00",X"00",
X"80",X"00",X"00",X"80",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"FF",X"00",X"00",X"03",
X"00",X"00",X"04",X"00",X"00",X"04",X"00",X"00",
X"20",X"00",X"00",X"00",X"FF",X"20",X"00",X"00",
X"10",X"00",X"00",X"00",X"00",X"20",X"20",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"FF",X"00",
481,7 → 376,10
X"00",X"00",X"FF",X"00",X"FF",X"30",X"00",X"00",
X"20",X"00",X"00",X"00",X"FF",X"20",X"00",X"00",
X"00",X"00",X"20",X"00",X"00",X"00",X"20",X"00",
X"00",X"00",X"FF",X"20",X"00",X"00",X"00",X"00",
X"00",X"00",X"FF",X"20",X"00",X"00",X"00",X"6D",
X"65",X"6D",X"46",X"20",X"30",X"2D",X"36",X"3A",
X"00",X"63",X"72",X"6E",X"34",X"31",X"00",X"48",
X"6F",X"72",X"0A",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
575,13 → 473,10
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
signal rom0 : t_code_ram := (
X"00",X"F0",X"00",X"58",X"00",X"60",X"00",X"48",
signal bram0 : t_bram := (
X"00",X"F0",X"00",X"00",X"00",X"00",X"00",X"E8",
X"00",X"2A",X"FD",X"04",X"8B",X"00",X"0E",X"98",
X"10",X"14",X"18",X"1C",X"20",X"24",X"28",X"2C",
X"30",X"34",X"38",X"3C",X"40",X"44",X"48",X"4C",
598,8 → 493,8
X"28",X"2C",X"08",X"00",X"00",X"04",X"08",X"0C",
X"10",X"14",X"18",X"1C",X"20",X"24",X"28",X"2C",
X"00",X"08",X"00",X"19",X"12",X"10",X"08",X"00",
X"0C",X"08",X"00",X"00",X"E8",X"14",X"A1",X"00",
X"00",X"A1",X"28",X"00",X"14",X"40",X"A1",X"18",
X"0C",X"08",X"00",X"00",X"E8",X"14",X"A1",X"DC",
X"00",X"A1",X"04",X"00",X"14",X"1C",X"A1",X"18",
X"00",X"20",X"00",X"02",X"FC",X"00",X"00",X"08",
X"21",X"00",X"00",X"11",X"0A",X"00",X"00",X"0D",
X"0E",X"00",X"01",X"20",X"00",X"02",X"FC",X"00",
611,7 → 506,10
X"00",X"57",X"FC",X"00",X"E7",X"06",X"08",X"00",
X"00",X"20",X"00",X"02",X"FC",X"00",X"49",X"00",
X"08",X"00",X"00",X"20",X"08",X"01",X"00",X"20",
X"00",X"01",X"FC",X"00",X"00",X"08",X"00",X"00",
X"00",X"01",X"FC",X"00",X"00",X"08",X"00",X"70",
X"20",X"65",X"65",X"36",X"31",X"2D",X"3A",X"32",
X"00",X"20",X"73",X"3A",X"2E",X"0A",X"00",X"65",
X"20",X"6C",X"0A",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
705,154 → 603,161
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00"
);
 
--------------------------------------------------------------------------------
subtype t_bram_address is std_logic_vector(BRAM_ADDR_SIZE-1 downto 0);
 
signal reset_sync : std_logic_vector(2 downto 0);
signal cpu_rd_addr : std_logic_vector(31 downto 0);
signal prev_rd_addr : std_logic_vector(31 downto 28);
signal cpu_vma_data : std_logic;
signal cpu_vma_code : std_logic;
signal cpu_wr_addr : std_logic_vector(31 downto 2);
signal cpu_byte_we : std_logic_vector(3 downto 0);
signal cpu_data_r : std_logic_vector(31 downto 0);
signal data_ram : std_logic_vector(31 downto 0);
signal data_uart : std_logic_vector(31 downto 0);
signal data_uart_status : std_logic_vector(31 downto 0);
signal uart_tx_rdy : std_logic;
signal uart_rx_rdy : std_logic;
signal uart_write_tx : std_logic;
signal uart_read_rx : std_logic;
signal cpu_data_w : std_logic_vector(31 downto 0);
signal cpu_code_addr : std_logic_vector(31 downto 2);
signal cpu_code_r : std_logic_vector(31 downto 0);
signal bram_rd_addr : t_bram_address;
signal bram_wr_addr : t_bram_address;
signal bram_rd_data : t_word;
signal bram_wr_data : t_word;
signal bram_byte_we : std_logic_vector(3 downto 0);
 
 
--------------------------------------------------------------------------------
begin
 
cpu: entity work.mips_cpu
cpu: entity work.mips_cpu
port map (
interrupt => '0',
data_rd_addr=> cpu_rd_addr,
data_rd_vma => cpu_vma_data,
data_rd => cpu_data_r,
data_rd_addr=> cpu_data_rd_addr,
data_rd_vma => cpu_data_rd_vma,
data_rd => cpu_data_rd,
code_rd_addr=> cpu_code_addr,
code_rd => cpu_code_r,
code_rd_vma => cpu_vma_code,
code_rd_addr=> cpu_code_rd_addr,
code_rd => cpu_code_rd,
code_rd_vma => cpu_code_rd_vma,
data_wr_addr=> cpu_wr_addr,
data_wr => cpu_data_w,
data_wr_addr=> cpu_data_wr_addr,
data_wr => cpu_data_wr,
byte_we => cpu_byte_we,
 
mem_wait => '0',
mem_wait => cpu_mem_wait,
clk => clk,
reset => reset_sync(0)
reset => reset
);
 
 
-- RAM vs. IO data read mux
cpu_data_r <= data_ram when prev_rd_addr/=X"2" else data_uart;
cache: entity work.mips_cache_stub
generic map (
BRAM_ADDR_SIZE => BRAM_ADDR_SIZE,
SRAM_ADDR_SIZE => SRAM_ADDR_SIZE
)
port map (
clk => clk,
reset => reset,
-- Interface to CPU core
data_rd_addr => cpu_data_rd_addr,
data_rd => cpu_data_rd,
data_rd_vma => cpu_data_rd_vma,
code_rd_addr => cpu_code_rd_addr,
code_rd => cpu_code_rd,
code_rd_vma => cpu_code_rd_vma,
data_wr_addr => cpu_data_wr_addr,
byte_we => cpu_byte_we,
data_wr => cpu_data_wr,
mem_wait => cpu_mem_wait,
cache_enable => '1',
-- interface to FPGA i/o devices
io_rd_data => mpu_io_rd_data,
io_wr_data => mpu_io_wr_data,
io_rd_addr => mpu_io_rd_addr,
io_wr_addr => mpu_io_wr_addr,
io_rd_vma => mpu_io_rd_vma,
io_byte_we => mpu_io_byte_we,
-- interface to synchronous 32-bit-wide FPGA BRAM
bram_rd_data => bram_rd_data,
bram_wr_data => bram_wr_data,
bram_rd_addr => bram_rd_addr,
bram_wr_addr => bram_wr_addr,
bram_byte_we => bram_byte_we,
-- interface to asynchronous 16-bit-wide external SRAM
sram_address => sram_address,
sram_databus => sram_databus,
sram_byte_we_n => sram_byte_we_n,
sram_oe_n => sram_oe_n
);
 
-- Take the slices of the addr buses that will reach the ram blocks
data_addr_rd <= cpu_rd_addr(DATA_ADDR_SIZE-1+2 downto 2);
data_addr_wr <= cpu_wr_addr(DATA_ADDR_SIZE-1+2 downto 2);
code_addr_rd <= cpu_code_addr(CODE_ADDR_SIZE-1+2 downto 2);
 
--------------------------------------------------------------------------------
-- BRAM interface
 
data_ram_block:
process(clk)
begin
if clk'event and clk='1' then
prev_rd_addr <= cpu_rd_addr(31 downto 28);
data_ram <=
ram3(conv_integer(unsigned(data_addr_rd))) &
ram2(conv_integer(unsigned(data_addr_rd))) &
ram1(conv_integer(unsigned(data_addr_rd))) &
ram0(conv_integer(unsigned(data_addr_rd)));
fpga_ram_block:
process(clk)
begin
if clk'event and clk='1' then
if cpu_byte_we/="0000" and cpu_wr_addr(31 downto 28)/=X"2" then
-- Write to RAM
if cpu_byte_we(3)='1' then
ram3(conv_integer(unsigned(data_addr_wr))) <= cpu_data_w(31 downto 24);
end if;
if cpu_byte_we(2)='1' then
ram2(conv_integer(unsigned(data_addr_wr))) <= cpu_data_w(23 downto 16);
end if;
if cpu_byte_we(1)='1' then
ram1(conv_integer(unsigned(data_addr_wr))) <= cpu_data_w(15 downto 8);
end if;
if cpu_byte_we(0)='1' then
ram0(conv_integer(unsigned(data_addr_wr))) <= cpu_data_w( 7 downto 0);
end if;
end if;
end if;
end process data_ram_block;
bram_rd_data <=
bram3(conv_integer(unsigned(bram_rd_addr))) &
bram2(conv_integer(unsigned(bram_rd_addr))) &
bram1(conv_integer(unsigned(bram_rd_addr))) &
bram0(conv_integer(unsigned(bram_rd_addr)));
end if;
end process fpga_ram_block;
 
code_ram_block:
process(clk)
begin
if clk'event and clk='1' then
cpu_code_r <=
rom3(conv_integer(unsigned(code_addr_rd))) &
rom2(conv_integer(unsigned(code_addr_rd))) &
rom1(conv_integer(unsigned(code_addr_rd))) &
rom0(conv_integer(unsigned(code_addr_rd)));
end if;
end process code_ram_block;
-- FIXME this should be in parent block
reset_synchronization:
process(clk)
begin
if clk'event and clk='1' then
reset_sync(2) <= reset;
reset_sync(1) <= reset_sync(2);
reset_sync(0) <= reset_sync(1);
end if;
end process reset_synchronization;
 
reset_synchronization:
process(clk)
begin
if clk'event and clk='1' then
reset_sync(2) <= reset;
reset_sync(1) <= reset_sync(2);
reset_sync(0) <= reset_sync(1);
end if;
end process reset_synchronization;
 
--------------------------------------------------------------------------------
 
data_w <= cpu_data_w;
wr_addr <= cpu_wr_addr;
vma_data <= cpu_vma_data;
 
--------------------------------------------------------------------------------
 
serial_rx : entity work.rs232_rx port map(
rxd => uart_rxd,
data_rx => OPEN, --rs232_data_rx,
rx_rdy => uart_rx_rdy,
read_rx => '1', --read_rx,
clk => clk,
reset => reset_sync(0)
);
serial_rx : entity work.rs232_rx
port map(
rxd => uart_rxd,
data_rx => OPEN, --rs232_data_rx,
rx_rdy => uart_rx_rdy,
read_rx => '1', --read_rx,
clk => clk,
reset => reset_sync(0)
);
 
 
uart_write_tx <= '1' when cpu_byte_we/="0000" and cpu_wr_addr(31 downto 28)=X"2"
else '0';
uart_write_tx <= '1'
when mpu_io_byte_we/="0000" and mpu_io_wr_addr(31 downto 28)=X"2"
else '0';
 
serial_tx : entity work.rs232_tx port map(
clk => clk,
reset => reset_sync(0),
rdy => uart_tx_rdy,
load => uart_write_tx,
data_i => cpu_data_w(7 downto 0),
txd => uart_txd
);
serial_tx : entity work.rs232_tx
port map(
clk => clk,
reset => reset_sync(0),
rdy => uart_tx_rdy,
load => uart_write_tx,
data_i => mpu_io_wr_data(7 downto 0),
txd => uart_txd
);
 
-- UART read registers; only status, and hardwired, for the time being
data_uart <= data_uart_status; -- FIXEM no data rx yet
data_uart <= data_uart_status; -- FIXME no data rx yet
data_uart_status <= X"0000000" & "00" & uart_tx_rdy & uart_rx_rdy;
 
mpu_io_rd_data <= data_uart;
 
-- io_rd_data
io_rd_addr <= mpu_io_rd_addr;
io_wr_addr <= mpu_io_wr_addr;
io_wr_data <= mpu_io_wr_data;
io_rd_vma <= mpu_io_rd_vma;
io_byte_we <= mpu_io_byte_we;
 
 
end architecture rtl;
/ion/trunk/vhdl/demo/c2sb_demo.vhdl
1,8 → 1,8
--#############################################################################
--##############################################################################
-- ION MIPS-compatible CPU demo on Terasic DE-1 Cyclone-II starter board
--#############################################################################
--##############################################################################
-- This module is little more than a wrapper around the CPU and its memories.
--#############################################################################
--##############################################################################
 
library ieee;
use ieee.std_logic_1164.all;
64,6 → 64,8
--##############################################################################
--
 
constant SRAM_ADDR_SIZE : integer := 18;
 
--##############################################################################
-- RS232 interface signals
 
115,37 → 117,49
signal reg_sd_clk : std_logic;
signal reg_sd_cs : std_logic;
 
signal cpu_rd_addr : std_logic_vector(31 downto 0);
signal cpu_rd_data : std_logic_vector(31 downto 0);
signal prev_rd_addr : std_logic_vector(31 downto 28);
signal cpu_vma_data : std_logic;
 
signal cpu_wr_addr : std_logic_vector(31 downto 2);
signal cpu_wr_data : std_logic_vector(31 downto 0);
signal cpu_byte_we : std_logic_vector(3 downto 0);
 
-- MPU interface signals
signal data_uart : std_logic_vector(31 downto 0);
 
signal data_uart_status : std_logic_vector(31 downto 0);
signal uart_tx_rdy : std_logic := '1';
signal uart_rx_rdy : std_logic := '1';
 
signal io_rd_data : std_logic_vector(31 downto 0);
signal io_rd_addr : std_logic_vector(31 downto 2);
signal io_wr_addr : std_logic_vector(31 downto 2);
signal io_wr_data : std_logic_vector(31 downto 0);
signal io_rd_vma : std_logic;
signal io_byte_we : std_logic_vector(3 downto 0);
 
signal mpu_sram_address : std_logic_vector(SRAM_ADDR_SIZE downto 1);
signal mpu_sram_databus : std_logic_vector(15 downto 0);
signal mpu_sram_byte_we_n : std_logic_vector(1 downto 0);
signal mpu_sram_oe_n : std_logic;
 
 
 
begin
 
mpu: entity work.mips_mpu
generic map (
SRAM_ADDR_SIZE => SRAM_ADDR_SIZE
)
port map (
interrupt => '0',
rd_addr => cpu_rd_addr,
vma_data => cpu_vma_data,
data_r => cpu_rd_data,
-- interface to FPGA i/o devices
io_rd_data => io_rd_data,
io_rd_addr => io_rd_addr,
io_wr_addr => io_wr_addr,
io_wr_data => io_wr_data,
io_rd_vma => io_rd_vma,
io_byte_we => io_byte_we,
wr_addr => cpu_wr_addr,
data_w => cpu_wr_data,
byte_we => cpu_byte_we,
-- interface to asynchronous 16-bit-wide EXTERNAL SRAM
sram_address => mpu_sram_address,
sram_databus => sram_data,
sram_byte_we_n => mpu_sram_byte_we_n,
sram_oe_n => mpu_sram_oe_n,
 
mem_wait => '0',
uart_rxd => rxd,
uart_txd => txd,
155,8 → 169,8
);
 
 
reg_display <= cpu_wr_addr(17 downto 2);
reg_gleds <= cpu_vma_data & "000" & cpu_byte_we;
reg_display <= io_wr_data(15 downto 0);
reg_gleds <= io_rd_vma & "000" & io_byte_we;
 
-- red leds (light with '1') -- some CPU control signals
red_leds(0) <= '0';
180,7 → 194,6
--##############################################################################
 
flash_addr <= (others => '0');
 
flash_we_n <= '1'; -- all enable signals inactive
flash_oe_n <= '1';
flash_reset_n <= '1';
192,14 → 205,12
-- NOTE: All writes go to SRAM independent of rom paging status
--##############################################################################
 
-- SRAM disabled for the time being
sram_addr <= (others => '0');
sram_data <= (others => 'Z');
sram_oe_n <= '1';
sram_ub_n <= '1';
sram_lb_n <= '1';
sram_ce_n <= '1';
sram_we_n <= '1';
sram_addr <= mpu_sram_address;
sram_oe_n <= mpu_sram_oe_n;
sram_ub_n <= mpu_sram_byte_we_n(1) and mpu_sram_oe_n;
sram_lb_n <= mpu_sram_byte_we_n(0) and mpu_sram_oe_n;
sram_ce_n <= '0';
sram_we_n <= mpu_sram_byte_we_n(1) and mpu_sram_byte_we_n(0);
 
 
--##############################################################################
/ion/trunk/vhdl/mips_cache_stub.vhdl
1,19 → 1,43
--------------------------------------------------------------------------------
-- mips_cache_stub.vhdl -- cache module with no actual cache memory.
-- mips_cache_stub.vhdl -- 1-word cache module
--
-- FOR SIMULATION ONLY! does not resemble structure of final cache
-- This module has the same interface and logic as a real cache but the cache
-- memory is just 1 word for each of code and data.
--
-- This module has the same interface as a real cache but has no cache memory.
-- It just interfaces the CPU to the following:
-- It interfaces the CPU to the following:
--
-- 1.- Internal 32-bit-wide BRAM for read and write
-- 1.- Internal 32-bit-wide BRAM for read only
-- 2.- Internal 32-bit I/O bus
-- 3.- External 16-bit wide SRAM
--
-- The purpose of this module is just to test the SRAM interface in simulation.
-- It will evolve to a real cache as the project goes on.
-- The SRAM memory interface signals are meant to connect directly to FPGA pins
-- and all outputs are registered (tco should be minimal).
-- SRAM data inputs are NOT registered, though. They go through a couple muxes
-- before reaching the first register so watch out for tsetup.
-- The SRAM is assumed to be fast enough to read or write in a clock cycle.
--
-- Obviously this module provides no performance gain; on the contrary, by
-- coupling the CPU to slow external memory (16 bit bus) it actually slows it
-- down. The purpose of this module is just to test the SRAM interface and the
-- cache logic and timing.
--
--------------------------------------------------------------------------------
-- KNOWN TROUBLE:
--
-- Apart from the very rough looks of the code, there's a few known faults with
-- it:
--
-- 1.- Access to unmapped areas wil crash the CPU
-- A couple states are missing in the state machine for handling accesses
-- to unmapped areas. I haven't yet decided how to handle that (return
-- zero, trigger trap, mirror another mapped area...)
-- 2.- Address decoding is hardcoded in mips_pkg
-- It should be done here using module generics and not package constants.
-- 3.- Does not work as a real 1-word cache yet
-- That functionality is still missing, all accesses 'miss'. It should be
-- implemented, as a way to test the real cache logic on a small scale.
--
--------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
29,22 → 53,23
port(
clk : in std_logic;
reset : in std_logic;
 
-- Interface to CPU core
data_rd_addr : in std_logic_vector(31 downto 0);
data_rd : out std_logic_vector(31 downto 0);
data_rd_vma : in std_logic;
 
code_rd_addr : in std_logic_vector(31 downto 2);
code_rd : out std_logic_vector(31 downto 0);
code_rd_vma : in std_logic;
 
data_wr_addr : in std_logic_vector(31 downto 2);
byte_we : in std_logic_vector(3 downto 0);
data_wr : in std_logic_vector(31 downto 0);
 
mem_wait : out std_logic;
cache_enable : in std_logic;
 
-- interface to FPGA i/o devices
io_rd_data : in std_logic_vector(31 downto 0);
io_rd_addr : out std_logic_vector(31 downto 2);
52,16 → 77,17
io_wr_data : out std_logic_vector(31 downto 0);
io_rd_vma : out std_logic;
io_byte_we : out std_logic_vector(3 downto 0);
 
-- interface to synchronous 32-bit-wide FPGA BRAM (possibly used as ROM)
bram_rd_data : in std_logic_vector(31 downto 0);
bram_wr_data : out std_logic_vector(31 downto 0);
bram_rd_addr : out std_logic_vector(BRAM_ADDR_SIZE+1 downto 2);
bram_wr_addr : out std_logic_vector(BRAM_ADDR_SIZE+1 downto 2);
bram_byte_we : out std_logic_vector(3 downto 0);
bram_byte_we : out std_logic_vector(3 downto 0);
bram_data_rd_vma: out std_logic;
 
-- interface to asynchronous 16-bit-wide EXTERNAL SRAM
sram_address : out std_logic_vector(SRAM_ADDR_SIZE-1 downto 1);
sram_address : out std_logic_vector(SRAM_ADDR_SIZE downto 1);
sram_databus : inout std_logic_vector(15 downto 0);
sram_byte_we_n : out std_logic_vector(1 downto 0);
sram_oe_n : out std_logic
72,227 → 98,462
 
architecture stub of mips_cache_stub is
 
type t_cache_state is (
idle,
type t_code_cache_state is (
code_normal,
code_wait_for_dcache,
 
code_refill_bram_0, -- pc in bram_rd_addr
code_refill_bram_1, -- op in bram_rd
code_refill_bram_2, -- op in code_rd
code_refill_bram_3,
 
code_refill_sram_0,
code_refill_sram_1,
code_refill_sram_2,
 
code_bug
);
 
signal cps, cns : t_code_cache_state;
 
 
type t_data_cache_state is (
data_normal,
 
data_refill_sram_0,
data_refill_sram_1,
 
data_refill_bram_0, -- rd addr in bram_rd_addr
data_refill_bram_1, -- rd data in bram_rd_data
read_bram_data_0,
read_bram_data_1,
data_read_io_0, -- rd addr on io_rd_addr, io_vma active
data_read_io_1, -- rd data on io_rd_data
data_write_io_0,
data_write_io_1,
 
data_writethrough_sram_0,
data_writethrough_sram_1,
read_data_0,
read_data_1,
read_code_0,
read_code_1,
data_ignore_write,
 
write_0,
write_1
data_bug
);
 
signal ps, ns : t_cache_state;
 
signal dps, dns : t_data_cache_state;
 
 
signal use_sram_wr : std_logic;
signal use_sram_rd : std_logic;
signal use_io_wr : std_logic;
signal use_io_rd : std_logic;
signal data_addr_reg : std_logic_vector(SRAM_ADDR_SIZE-1 downto 2);
signal data_addr_reg : std_logic_vector(SRAM_ADDR_SIZE downto 2);
signal data_wr_reg : std_logic_vector(31 downto 0);
signal data_input_reg : std_logic_vector(15 downto 0);
signal bram_rd_data_reg : std_logic_vector(31 downto 0);
signal io_rd_data_reg : std_logic_vector(31 downto 0);
signal byte_we_reg : std_logic_vector(3 downto 0);
 
 
signal code_rd_addr_reg : t_pc;
 
subtype t_code_tag is std_logic_vector(23 downto 2);
signal code_cache_tag : t_code_tag;
signal code_cache_tag_store : t_code_tag;
signal code_cache_store : t_word;
 
signal code_cache_rd : t_word;
signal code_miss : std_logic;
 
 
signal data_rd_addr_reg : t_pc;
signal data_wr_addr_reg : t_pc;
 
subtype t_data_tag is std_logic_vector(23 downto 2);
signal data_cache_tag : t_data_tag;
signal data_cache_tag_store : t_data_tag;
signal data_cache_store : t_word;
-- Stores first (high) HW read from SRAM
signal sram_rd_data_reg : std_logic_vector(31 downto 16);
-- Data read from SRAM, valid in refill_1
signal sram_rd_data : t_word;
 
signal write_pending : std_logic;
signal read_pending : std_logic;
 
signal data_cache_rd : t_word;
signal data_miss : std_logic;
 
signal code_wait : std_logic;
signal data_wait : std_logic;
 
 
signal code_rd_addr_mask : t_addr_decode;
signal data_rd_addr_mask : t_addr_decode;
signal data_wr_addr_mask : t_addr_decode;
 
signal code_rd_area : std_logic_vector(1 downto 0);
signal data_rd_area : std_logic_vector(1 downto 0);
signal data_wr_area : std_logic_vector(1 downto 0);
 
begin
 
 
cache_state_machine_reg:
cache_state_machine_regs:
process(clk)
begin
if clk'event and clk='1' then
if reset='1' then
ps <= idle; --wait_idle;
cps <= code_normal;
dps <= data_normal;
else
ps <= ns;
cps <= cns;
dps <= dns;
end if;
end if;
end process cache_state_machine_reg;
end process cache_state_machine_regs;
 
 
 
cache_state_machine_transitions:
process(clk,ps)
code_state_machine_transitions:
process(cps, dps, code_rd_vma, code_miss, code_rd_area, write_pending, read_pending)
begin
case ps is
when idle =>
ns <= ps;
if code_rd_vma='1' and use_sram_rd='1' then
ns <= read_code_0;
elsif data_rd_vma='1' and use_sram_rd='1' then
ns <= read_data_0;
elsif data_rd_vma='1' and use_sram_rd='0' then
ns <= read_bram_data_0;
elsif byte_we/="0000" and use_sram_wr='1' then
ns <= write_0;
case cps is
when code_normal =>
if code_rd_vma='1' and code_miss='1' and read_pending='0' and write_pending='0' then
cns <= code_refill_bram_0; -- FIXME check memory area
else
ns <= ps;
cns <= cps;
end if;
 
when read_bram_data_0 =>
ns <= read_bram_data_1;
when code_refill_bram_0 =>
cns <= code_refill_bram_1;
 
when read_bram_data_1 =>
ns <= idle;
when code_refill_bram_1 =>
cns <= code_refill_bram_2;
 
when read_code_0 =>
ns <= read_code_1;
when read_code_1 =>
if data_rd_vma='1' and use_sram_rd='1' then
ns <= read_data_0;
elsif byte_we/="0000" and use_sram_wr='1' then
ns <= write_0;
when code_refill_bram_2 =>
if dps/=data_normal and read_pending='0' and write_pending='0' then
cns <= code_wait_for_dcache;
else
ns <= idle;
cns <= code_normal;
end if;
when read_data_0 =>
ns <= read_data_1;
when read_data_1 =>
if byte_we/="0000" and use_sram_wr='1' then
ns <= write_0;
when code_refill_bram_3 =>
cns <= code_normal;
when code_wait_for_dcache =>
-- if D-cache is busy, wait for it to become idle
if dps/=data_normal then
cns <= cps;
elsif code_miss='1' then
cns <= code_refill_bram_1; -- FIXME check memory area
else
ns <= idle;
cns <= code_normal;
end if;
 
when write_0 =>
ns <= write_1;
when write_1 =>
ns <= idle;
when code_bug =>
cns <= code_normal;
 
when others =>
-- BUG: should raise some debug signal
ns <= idle;
cns <= code_bug;
end case;
end process cache_state_machine_transitions;
end process code_state_machine_transitions;
 
sram_address(sram_address'high downto 2) <=
data_addr_reg(sram_address'high downto 2);
 
data_state_machine_transitions:
process(dps, write_pending, read_pending, data_rd_area, data_wr_area)
begin
case dps is
when data_normal =>
if write_pending='1' then
case data_wr_area is
when "00" => dns <= data_ignore_write; -- Write to BRAM ignored
when "01" => dns <= data_writethrough_sram_0;
when "10" => dns <= data_write_io_0;
when others => dns <= dps; -- Write to undecoded area ignored
end case;
elsif read_pending='1' then
case data_rd_area is
when "00" => dns <= data_refill_bram_0;
when "01" => dns <= data_refill_sram_0;
when "10" => dns <= data_read_io_0;
when others => dns <= dps; -- ignore read from undecoded area
-- FIXME should raise debug flag
end case;
else
dns <= dps;
end if;
 
with ps select sram_address(1) <=
'0' when read_data_0,
'1' when read_data_1,
'0' when read_code_0,
'1' when read_code_1,
'0' when write_0,
'1' when write_1,
'0' when others;
when data_write_io_0 =>
dns <= data_normal;
when data_read_io_0 =>
dns <= data_read_io_1;
when data_read_io_1 =>
dns <= data_normal;
 
with ps select sram_oe_n <=
'0' when read_data_0,
'0' when read_data_1,
'0' when read_code_0,
'0' when read_code_1,
'1' when others;
when data_refill_sram_0 =>
dns <= data_refill_sram_1;
 
with ps select sram_byte_we_n <=
not byte_we_reg(3 downto 2) when write_0,
not byte_we_reg(1 downto 0) when write_1,
"11" when others;
with ps select sram_databus <=
data_wr_reg(31 downto 16) when write_0,
data_wr_reg(15 downto 0) when write_1,
(others => 'Z') when others;
when data_refill_sram_1 =>
dns <= data_normal;
 
sdram_address_register:
when data_refill_bram_0 =>
dns <= data_refill_bram_1;
 
when data_refill_bram_1 =>
dns <= data_normal;
 
when data_writethrough_sram_0 =>
dns <= data_writethrough_sram_1;
 
when data_writethrough_sram_1 =>
dns <= data_normal;
 
when data_ignore_write =>
dns <= data_normal;
 
when data_bug =>
dns <= data_normal;
 
when others =>
dns <= data_bug;
end case;
end process data_state_machine_transitions;
 
 
--------------------------------------------------------------------------------
-- CPU interface registers and address decoding --------------------------------
 
 
-- Everything coming and going to the CPU is registered, so that the CPU has
-- some timing marging.
 
cpu_interface_registers:
process(clk)
begin
if clk'event and clk='1' then
if reset='1' then
data_addr_reg <= (others => '0');
write_pending <= '0';
read_pending <= '0';
byte_we_reg <= "0000";
else
-- Raise 'read_pending' at the 1st cycle of a read, clear it when
-- the read (and/or refill) operation has been done.
-- data_rd_addr_reg always has the addr of any pending read
if data_rd_vma='1' then
data_addr_reg <= data_rd_addr(sram_address'high downto 2);
elsif byte_we/="0000" then
data_addr_reg <= data_wr_addr(sram_address'high downto 2);
read_pending <= '1';
data_rd_addr_reg <= data_rd_addr(31 downto 2);
elsif dps=data_refill_sram_1 or
dps=data_refill_bram_1 or
dps=data_read_io_0 then
read_pending <= '0';
end if;
 
-- Raise 'write_pending' at the 1st cycle of a read, clear it when
-- the write (writethrough actually) operation has been done.
-- data_wr_addr_reg always has the addr of any pending write
if byte_we/="0000" and dps=data_normal then
byte_we_reg <= byte_we;
data_wr_reg <= data_wr;
data_wr_addr_reg <= data_wr_addr;
write_pending <= '1';
elsif dps=data_writethrough_sram_1 or
dps=data_write_io_0 or
dps=data_ignore_write then
write_pending <= '0';
byte_we_reg <= "0000";
end if;
 
-- Register code fetch addresses only when they are valid; so that
-- code_rd_addr_reg always holds the last fetch address.
if (cps=code_normal and code_rd_vma='1') or cps=code_refill_bram_2 then
code_rd_addr_reg <= code_rd_addr;
end if;
end if;
end if;
end process sdram_address_register;
end process cpu_interface_registers;
 
-- Address decoding ------------------------------------------------------------
 
data_input_register:
-- Decoding is done on the high bits of the address only, there'll be mirroring.
-- Write to areas not explicitly decoded will be silently ignored. Reads will
-- get undefined data.
 
code_rd_addr_mask <= code_rd_addr_reg(31 downto t_addr_decode'low);
data_rd_addr_mask <= data_rd_addr_reg(31 downto t_addr_decode'low);
data_wr_addr_mask <= data_wr_addr_reg(31 downto t_addr_decode'low);
 
 
with code_rd_addr_mask select code_rd_area <=
"00" when ADDR_BOOT,
"01" when ADDR_XRAM,
"11" when others;
 
with data_rd_addr_mask select data_rd_area <=
"00" when ADDR_BOOT,
"01" when ADDR_XRAM,
"10" when ADDR_IO,
"11" when others;
 
with data_wr_addr_mask select data_wr_area <=
"01" when ADDR_XRAM,
"10" when ADDR_IO,
"11" when others;
 
 
--------------------------------------------------------------------------------
-- Code cache
 
bram_rd_addr <= data_rd_addr_reg(bram_rd_addr'high downto 2)
when dps=data_refill_bram_0
else code_rd_addr_reg(bram_rd_addr'high downto 2) ;
 
code_rd <= code_cache_rd;
 
-- FIXME Actual 1-word cache functionality is unimplemented yet
code_miss <= '1'; --code_rd_vma;
 
 
-- Read cache code and tag from code store
code_cache_rd <= code_cache_store;
code_cache_tag <= code_cache_tag_store;
 
code_cache_memory:
process(clk)
begin
if clk'event and clk='1' then
 
 
if reset='1' then
data_input_reg <= (others => '0');
-- in the real hardware the tag store can't be reset and it's up
-- to the SW to initialize the cache.
code_cache_tag_store <= (others => '0');
code_cache_store <= (others => '0');
else
if ps=read_data_0 then
data_input_reg <= sram_databus;
-- Refill cache if necessary
if cps=code_refill_bram_1 then
code_cache_tag_store <=
"01" & code_rd_addr_reg(t_code_tag'high-2 downto t_code_tag'low);
code_cache_store <= bram_rd_data;
--elsif cps=code_refill_sram_2 then
-- code_cache_tag_store <=
-- "01" & code_rd_addr_reg(t_code_tag'high-2 downto t_code_tag'low);
-- code_cache_store <= sram_rd_data;
end if;
bram_rd_data_reg <= bram_rd_data;
if byte_we/="0000" then
byte_we_reg <= byte_we;
data_wr_reg <= data_wr;
end if;
end if;
end process code_cache_memory;
 
 
--------------------------------------------------------------------------------
-- Data cache
 
with dps select data_rd <=
io_rd_data when data_read_io_1,
data_cache_rd when others;
 
 
data_cache_rd <= data_cache_store;
data_cache_tag <= data_cache_tag_store;
 
data_cache_memory:
process(clk)
begin
if clk'event and clk='1' then
 
 
if reset='1' then
-- in the real hardware the tag store can't be reset and it's up
-- to the SW to initialize the cache.
data_cache_tag_store <= (others => '0');
data_cache_store <= (others => '0');
else
-- Refill data cache if necessary
if dps=data_refill_sram_1 then
data_cache_tag_store <=
"01" & data_rd_addr_reg(t_data_tag'high-2 downto t_data_tag'low);
data_cache_store <= sram_rd_data;
elsif dps=data_refill_bram_1 then
data_cache_tag_store <=
"01" & data_rd_addr_reg(t_data_tag'high-2 downto t_data_tag'low);
data_cache_store <= bram_rd_data;
end if;
end if;
end if;
end process data_input_register;
end process data_cache_memory;
 
with dps select sram_address(sram_address'high downto 2) <=
data_rd_addr_reg(sram_address'high downto 2) when data_refill_sram_0,
data_rd_addr_reg(sram_address'high downto 2) when data_refill_sram_1,
data_wr_addr_reg(sram_address'high downto 2) when others;
 
with ps select code_rd <=
data_input_reg & sram_databus when read_code_1,
bram_rd_data when others;
with dps select sram_address(1) <=
'0' when data_writethrough_sram_0,
'1' when data_writethrough_sram_1,
'0' when data_refill_sram_0,
'1' when data_refill_sram_1,
'0' when others;
 
with dps select sram_databus <=
data_wr_reg(31 downto 16) when data_writethrough_sram_0,
data_wr_reg(15 downto 0) when data_writethrough_sram_1,
(others => 'Z') when others;
 
data_rd <=
data_input_reg & sram_databus when ps=read_data_1 else
bram_rd_data_reg;
-- FIXME IO RD data missing
--io_rd_data when (ps=idle and use_io_rd='1') else
with dps select sram_byte_we_n <=
not byte_we_reg(3 downto 2) when data_writethrough_sram_0,
not byte_we_reg(1 downto 0) when data_writethrough_sram_1,
"11" when others;
 
mem_wait <= '1' when
ps=read_bram_data_0 or
ps=read_data_0 or
ps=write_0 or
(ps=idle and use_sram_wr='1' and byte_we/="0000")
else '0';
with dps select sram_oe_n <=
'0' when data_refill_sram_0,
'0' when data_refill_sram_1,
'1' when others;
 
use_sram_rd <= '1'
when (addr_decode(data_rd_addr,ADDR_XRAM)='1' and data_rd_vma='1') or
(addr_decode(code_rd_addr,ADDR_XRAM)='1' and code_rd_vma='1')
else '0';
sram_rd_data <= sram_rd_data_reg & sram_databus;
 
use_sram_wr <= '1'
when addr_decode(data_wr_addr,ADDR_XRAM)='1'
else '0';
process(clk)
begin
if clk'event and clk='1' then
--if ps=xxx then
sram_rd_data_reg <= sram_databus;
--end if;
end if;
end process;
 
use_io_rd <= '1'
when addr_decode(data_rd_addr,ADDR_IO)='1' and data_rd_vma='1'
else '0';
bram_data_rd_vma <= '1' when dps=data_refill_bram_1 else '0';
 
use_io_wr <= '1'
when addr_decode(data_wr_addr,ADDR_IO)='1' and byte_we/="0000"
else '0';
 
--------------------------------------------------------------------------------
 
bram_rd_addr <= data_rd_addr(bram_rd_addr'high downto 2) when
(ps=idle and use_sram_rd='0' and data_rd_vma='1')
else code_rd_addr(bram_rd_addr'high downto 2);
bram_wr_addr <= data_wr_addr(bram_wr_addr'high downto 2);
bram_byte_we <= byte_we when addr_decode(data_wr_addr,ADDR_BOOT)='1' else "0000";
io_byte_we <= byte_we_reg when dps=data_write_io_0 else "0000";
io_rd_addr <= data_rd_addr_reg;
io_wr_addr <= data_wr_addr_reg;
io_wr_data <= data_wr_reg;
io_rd_vma <= '1' when dps=data_read_io_0 else '0';
 
--------------------------------------------------------------------------------
 
io_wr_addr <= data_wr_addr;
io_rd_addr <= data_rd_addr(31 downto 2);
io_wr_data <= data_wr;
io_byte_we <= byte_we when addr_decode(data_wr_addr,ADDR_IO)='1' else "0000";
mem_wait <= (code_wait or data_wait) and not reset;
 
with cps select code_wait <=
'1' when code_refill_bram_0,
'1' when code_refill_bram_1,
'1' when code_refill_bram_2,
'1' when code_wait_for_dcache,
'0' when others;
 
with dps select data_wait <=
'1' when data_writethrough_sram_0,
'1' when data_writethrough_sram_1,
'1' when data_refill_sram_0,
'1' when data_refill_sram_1,
'1' when data_refill_bram_0,
'1' when data_refill_bram_1,
'1' when data_read_io_0,
'0' when others;
 
 
end architecture stub;
/ion/trunk/vhdl/mips_cpu.vhdl
21,7 → 21,7
-- # External interrupts
--
--### Things implemented but not tested
-- # Memory pause input
-- # Memory pause input -- not tested with a real cache
--
--### Things with provisional implementation
--
182,9 → 182,13
signal stall_pipeline : std_logic;
-- pipeline is stalled for any reason
signal pipeline_stalled : std_logic;
 
signal stalled_memwait : std_logic;
signal stalled_muldiv : std_logic;
-- pipeline is stalled because of a load instruction interlock
signal pipeline_interlocked:std_logic;
signal stalled_interlock : std_logic;
 
 
--------------------------------------------------------------------------------
-- CP0 registers and signals
 
246,8 → 250,8
 
-- bytes 2,3 come straight from input or are extended for LH,LHU
with p2_ld_upper_hword select p2_data_word_rd(31 downto 16) <=
(others => p2_data_word_ext) when '0',
data_rd(31 downto 16) when others;
(others => p2_data_word_ext) when '0',
data_rd(31 downto 16) when others;
 
-- Select which data is to be written back to the reg bank and where
p1_rbank_wr_addr <= p1_rd_num when p2_do_load='0' and p1_link='0' else
273,6 → 277,8
-- if the cache controller keeps the cpu stopped, do
-- not writeback
mem_wait='0' and
-- if stalled because of muldiv, block writeback
stalled_muldiv='0' and --@note1
-- on exception, abort next instruction (by preventing
-- regbank writeback).
p2_exception='0'
285,12 → 291,15
process(clk)
begin
if clk'event and clk='1' then
if p1_rbank_we='1' and
(pipeline_stalled='0' or pipeline_interlocked='1') then -- @note1
if p1_rbank_we='1' then
p1_rbank(conv_integer(p1_rbank_wr_addr)) <= p1_rbank_wr_data;
end if;
p1_rt_rbank <= p1_rbank(conv_integer(p0_rt_num));
p1_rs_rbank <= p1_rbank(conv_integer(p0_rs_num));
-- the rbank read port loads in the same conditions as the IR: don't
-- update Rs or Rt if the pipeline is frozen
if stall_pipeline='0' then
p1_rt_rbank <= p1_rbank(conv_integer(p0_rt_num));
p1_rs_rbank <= p1_rbank(conv_integer(p0_rs_num));
end if;
end if;
end process synchronous_reg_bank;
 
427,6 → 436,7
if clk'event and clk='1' then
if reset='1' then
-- reset to 0xffffffff so that 1st fetch addr is 0x00000000
-- FIXME reset vector is hardcoded
p0_pc_reg <= (others => '1');
else
-- p0_pc_reg holds the same value as external sync ram addr register
810,28 → 820,54
 
-- FIXME stall when needed: mem pause, mdiv pause and load interlock
 
 
-- FIXME make sure this combinational will not have bad glitches
stall_pipeline <= mem_wait or load_interlock or p1_muldiv_stall;
 
 
-- FIXME load interlock should happen only if the instruction following
-- the load actually uses the load target register. Something like this:
-- (p1_do_load='1' and (p1_rd_num=p0_rs_num or p1_rd_num=p0_rt_num))
load_interlock <= '1' when
p1_do_load='1' and -- this is a load instruction
pipeline_stalled='0' and -- not already stalled (i.e. assert for 1 cycle)
(p1_rs1_hazard='1' or p1_rs2_hazard='1')
else '0';
 
 
 
 
pipeline_stalled <= stalled_interlock or stalled_memwait or stalled_muldiv;
 
pipeline_stall_registers:
process(clk)
begin
if clk'event and clk='1' then
if reset='1' then
pipeline_stalled <= '0';
pipeline_interlocked <= '0';
stalled_interlock <= '0';
stalled_memwait <= '0';
stalled_muldiv <= '0';
else
if stall_pipeline='1' then
pipeline_stalled <= '1';
if mem_wait='1' then
stalled_memwait <= '1';
else
pipeline_stalled <= '0';
stalled_memwait <= '0';
end if;
if p1_muldiv_stall='1' then
stalled_muldiv <= '1';
else
stalled_muldiv <= '0';
end if;
-- stalls caused by mem_wait and load_interlock are independent and
-- must not overlap; so when mem_wait='1' the cache stall takes
-- precedence and the loa interlock must wait.
if mem_wait='0' then
if load_interlock='1' then
pipeline_interlocked <= '1';
stalled_interlock <= '1';
else
pipeline_interlocked <= '0';
stalled_interlock <= '0';
end if;
end if;
end if;
838,20 → 874,6
end if;
end process pipeline_stall_registers;
 
-- FIXME make sure this combinational will not have bad glitches
stall_pipeline <= mem_wait or load_interlock or p1_muldiv_stall;
 
 
-- FIXME load interlock should happen only if the instruction following
-- the load actually uses the load target register. Something like this:
-- (p1_do_load='1' and (p1_rd_num=p0_rs_num or p1_rd_num=p0_rt_num))
load_interlock <= '1' when
p1_do_load='1' and -- this is a load instruction
pipeline_stalled='0' and -- not already stalled (i.e. assert for 1 cycle)
(p1_rs1_hazard='1' or p1_rs2_hazard='1')
else '0';
 
p1_rs1_hazard <= '1'; --'1' when p0_uses_rs1='1' and p1_rd_num=p0_rs_num else '0';
p1_rs2_hazard <= '1'; --'1' when p0_uses_rs2='1' and p1_rd_num=p0_rt_num else '0';
 
976,7 → 998,7
-- @note1 :
--
-- This is the meaning of these two signals:
-- pipeline_stalled & pipeline_interlocked =>
-- pipeline_stalled & stalled_interlock =>
-- "00" => normal state
-- "01" => normal state (makes for easier decoding)
-- "10" => all stages of pipeline stalled, including rbank

powered by: WebSVN 2.1.0

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