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 |