git-svn-id: http://moon:8086/svn/vhdl/trunk@1037 cc03376c-175c-47c8-b038-4cd826a8556b
461 lines
12 KiB
VHDL
461 lines
12 KiB
VHDL
-------------------------------------------------------------------------
|
|
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
|
-- This file: Testbench for JCPU
|
|
-- also writes 'opc.lst' for JASM-assembler
|
|
--
|
|
-- Copyright (C) 2007 J. Ahrensfeld
|
|
--
|
|
-- This program is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- This program is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
--
|
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
--
|
|
--------------------------------------------------------------------------
|
|
|
|
LIBRARY ieee;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
USE ieee.numeric_std.ALL;
|
|
|
|
library work;
|
|
use work.mips_types.all;
|
|
use work.mips_instr.all;
|
|
use work.async_types.all;
|
|
use work.async_defs.all;
|
|
|
|
ENTITY tb_mips_top IS
|
|
END tb_mips_top;
|
|
|
|
ARCHITECTURE behavior OF tb_mips_top IS
|
|
|
|
constant SYS_FREQ : real := 100.0;
|
|
constant CLK_PERIOD : time := 10 ns;
|
|
constant SRAM_ADDR_WIDTH : integer := 17; -- bits
|
|
constant FLASH_ADDR_WIDTH : integer := 17; -- bits
|
|
|
|
signal debug : unsigned(1 downto 0);
|
|
|
|
-- Master
|
|
signal nmi : STD_LOGIC := '0';
|
|
signal rst : STD_LOGIC := '1';
|
|
signal clk : STD_LOGIC := '0';
|
|
signal eb : STD_LOGIC := '1';
|
|
signal ACK_I : STD_LOGIC := '0';
|
|
signal SRDY_I : STD_LOGIC := '0';
|
|
signal ADDR_O : unsigned(31 downto 0);
|
|
signal DAT_I : unsigned(31 downto 0) := (others => '0');
|
|
signal DAT_O : unsigned(31 downto 0);
|
|
signal WE_O : STD_LOGIC;
|
|
signal SEL_O : unsigned(3 downto 0);
|
|
signal CYC_O : STD_LOGIC;
|
|
signal STB_O : STD_LOGIC;
|
|
signal MRDY_O : STD_LOGIC;
|
|
signal INT : unsigned (5 downto 0) := (others => '0');
|
|
|
|
-- Slaves
|
|
signal CYC_I_rom : std_logic;
|
|
signal ACK_O_rom : std_logic;
|
|
signal SRDY_O_rom : std_logic;
|
|
signal DAT_O_rom : unsigned(31 downto 0);
|
|
|
|
signal CYC_I_flash : std_logic;
|
|
signal ACK_O_flash : std_logic;
|
|
signal SRDY_O_flash : std_logic;
|
|
signal DAT_O_flash : unsigned(31 downto 0);
|
|
|
|
signal CYC_I_sram : std_logic;
|
|
signal ACK_O_sram : std_logic;
|
|
signal SRDY_O_sram : std_logic;
|
|
signal DAT_O_sram : unsigned(31 downto 0);
|
|
|
|
signal CYC_I_gpio : std_logic;
|
|
signal ACK_O_gpio : std_logic;
|
|
signal SRDY_O_gpio : std_logic;
|
|
signal DAT_O_gpio : unsigned(31 downto 0);
|
|
|
|
signal CYC_I_uart : std_logic;
|
|
signal ACK_O_uart : std_logic;
|
|
signal SRDY_O_uart : std_logic;
|
|
signal DAT_O_uart : unsigned(31 downto 0);
|
|
|
|
signal flash_cs_n : std_logic;
|
|
signal flash_we_n : std_logic;
|
|
signal flash_oe_n : std_logic;
|
|
signal flash_be_n : unsigned(3 downto 0);
|
|
signal sram_cs_n : std_logic;
|
|
signal sram_be_n : unsigned(3 downto 0);
|
|
signal sram_wr_n : std_logic;
|
|
signal sram_oe_n : std_logic;
|
|
signal sram_a : unsigned(SRAM_ADDR_WIDTH-1 downto 0);
|
|
signal sram_d : unsigned(31 downto 0);
|
|
signal flash_a : unsigned(FLASH_ADDR_WIDTH-1 downto 0);
|
|
signal flash_d : unsigned(31 downto 0);
|
|
signal flash_page_mode_en : std_logic;
|
|
|
|
signal gpi_0 : unsigned(31 downto 0);
|
|
signal gpo_0 : unsigned(31 downto 0);
|
|
|
|
signal int_timer : std_logic;
|
|
signal int_uart : std_logic;
|
|
signal rx : std_logic := '1';
|
|
signal tx : std_logic;
|
|
|
|
type mem_area_t is (mem_dead, mem_flash, mem_sram, mem_rom, mem_gpio, mem_uart);
|
|
signal mem_area : mem_area_t;
|
|
|
|
type word_array_t is array (natural range <>) of unsigned(31 downto 0);
|
|
signal sram_data : word_array_t(0 to 2**SRAM_ADDR_WIDTH-1);
|
|
signal flash_data : word_array_t(0 to 2**FLASH_ADDR_WIDTH-1);
|
|
|
|
BEGIN
|
|
|
|
------------------------------------------------------------------
|
|
CLK_GEN: process
|
|
begin
|
|
wait for CLK_PERIOD/2;
|
|
clk <= not clk;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
-- Memory mux
|
|
------------------------------------------------------------------
|
|
mem_mux:
|
|
process(ADDR_O)
|
|
begin
|
|
mem_area <= mem_dead;
|
|
flash_page_mode_en <= '0';
|
|
if ADDR_O(31 downto 28) = X"0" then
|
|
mem_area <= mem_flash;
|
|
flash_page_mode_en <= '1';
|
|
elsif ADDR_O(31 downto 28) = X"A" then
|
|
if ADDR_O(27 downto 26) = "00" then
|
|
if ADDR_O(18 downto 16) = "000" then
|
|
mem_area <= mem_gpio;
|
|
elsif ADDR_O(18 downto 16) = "001" then
|
|
mem_area <= mem_uart;
|
|
end if;
|
|
elsif ADDR_O(27 downto 26) = "01" then
|
|
mem_area <= mem_flash;
|
|
end if;
|
|
elsif (ADDR_O(31 downto 28) = X"B" and ADDR_O(15) = '0') then
|
|
mem_area <= mem_rom;
|
|
elsif (ADDR_O(31 downto 28) = X"8" or ADDR_O(30) = '1') then
|
|
mem_area <= mem_sram;
|
|
end if;
|
|
end process;
|
|
|
|
signal_mux:
|
|
process(mem_area, CYC_O)
|
|
begin
|
|
|
|
CYC_I_uart <= '0';
|
|
CYC_I_gpio <= '0';
|
|
CYC_I_flash <= '0';
|
|
CYC_I_rom <= '0';
|
|
CYC_I_sram <= '0';
|
|
|
|
case mem_area is
|
|
|
|
when mem_gpio =>
|
|
CYC_I_gpio <= CYC_O;
|
|
|
|
when mem_uart =>
|
|
CYC_I_uart <= CYC_O;
|
|
|
|
when mem_flash =>
|
|
CYC_I_flash <= CYC_O;
|
|
|
|
when mem_rom =>
|
|
CYC_I_rom <= CYC_O;
|
|
|
|
when mem_sram =>
|
|
CYC_I_sram <= CYC_O;
|
|
|
|
when others => null;
|
|
|
|
end case;
|
|
|
|
end process;
|
|
|
|
SRDY_I <= SRDY_O_flash or SRDY_O_sram or SRDY_O_rom or SRDY_O_uart or SRDY_O_gpio;
|
|
ACK_I <= ACK_O_flash or ACK_O_sram or ACK_O_rom or ACK_O_uart or ACK_O_gpio;
|
|
DAT_I <= DAT_O_sram when CYC_I_sram = '1' else
|
|
DAT_O_rom when CYC_I_rom = '1' else
|
|
DAT_O_flash when CYC_I_flash = '1' else
|
|
DAT_O_uart when CYC_I_uart = '1' else
|
|
DAT_O_gpio when CYC_I_gpio = '1' else X"DEADBEEF";
|
|
|
|
|
|
------------------------------------------------------------------
|
|
uut: entity work.mips_top
|
|
GENERIC MAP
|
|
(
|
|
icache_size => 1024, -- words
|
|
dcache_size => 1024 -- words
|
|
)
|
|
PORT MAP
|
|
(
|
|
debug => debug,
|
|
eb => eb,
|
|
cpu_clk => clk,
|
|
RST_I => rst,
|
|
CLK_I => clk,
|
|
ACK_I => ACK_I,
|
|
SRDY_I => SRDY_I,
|
|
ADDR_O => ADDR_O,
|
|
DAT_I => DAT_I,
|
|
DAT_O => DAT_O,
|
|
WE_O => WE_O,
|
|
SEL_O => SEL_O,
|
|
CYC_O => CYC_O,
|
|
STB_O => STB_O,
|
|
MRDY_O => MRDY_O,
|
|
INT => INT,
|
|
nmi => nmi
|
|
);
|
|
INT(1) <= int_uart;
|
|
INT(5) <= int_timer;
|
|
|
|
inst_rom : entity work.rom_wb
|
|
PORT MAP
|
|
(
|
|
CLK_I => clk,
|
|
RST_I => rst,
|
|
CYC_I => CYC_I_rom,
|
|
STB_I => STB_O,
|
|
WE_I => WE_O,
|
|
ACK_O => ACK_O_rom,
|
|
MRDY_I => MRDY_O,
|
|
SRDY_O => SRDY_O_rom,
|
|
ADDR_I => ADDR_O,
|
|
DAT_O => DAT_O_rom
|
|
);
|
|
|
|
inst_gpio : entity work.gpio_wb
|
|
PORT MAP
|
|
(
|
|
CLK_I => clk,
|
|
RST_I => rst,
|
|
CYC_I => CYC_I_gpio,
|
|
STB_I => STB_O,
|
|
SEL_I => SEL_O,
|
|
WE_I => WE_O,
|
|
ACK_O => ACK_O_gpio,
|
|
SRDY_O => SRDY_O_gpio,
|
|
MRDY_I => MRDY_O,
|
|
ADDR_I => ADDR_O,
|
|
DAT_I => DAT_O,
|
|
DAT_O => DAT_O_gpio,
|
|
INT_TIM_O => int_timer,
|
|
|
|
sys_gpi_0 => gpi_0,
|
|
sys_gpo_0 => gpo_0
|
|
);
|
|
|
|
inst_flash_port : entity work.async_port_wb
|
|
GENERIC MAP
|
|
(
|
|
f_sysclk => SYS_FREQ,
|
|
addr_width => FLASH_ADDR_WIDTH,
|
|
data_width => 32,
|
|
byte_sel_width => 4,
|
|
async_timespec => ts_flash
|
|
)
|
|
PORT MAP
|
|
(
|
|
CLK_I => clk,
|
|
RST_I => rst,
|
|
CYC_I => CYC_I_flash,
|
|
STB_I => STB_O,
|
|
WE_I => WE_O,
|
|
ACK_O => ACK_O_flash,
|
|
SRDY_O => SRDY_O_flash,
|
|
MRDY_I => MRDY_O,
|
|
SEL_I => SEL_O,
|
|
ADDR_I => ADDR_O,
|
|
DAT_I => DAT_O,
|
|
DAT_O => DAT_O_flash,
|
|
page_mode_en => flash_page_mode_en,
|
|
async_a => flash_a,
|
|
async_d => flash_d,
|
|
async_cs => flash_cs_n,
|
|
async_wr => flash_we_n,
|
|
async_rd => flash_oe_n,
|
|
async_be => flash_be_n,
|
|
async_rst => open
|
|
);
|
|
|
|
inst_sram_port : entity work.async_port_wb
|
|
GENERIC MAP
|
|
(
|
|
f_sysclk => SYS_FREQ,
|
|
addr_width => SRAM_ADDR_WIDTH,
|
|
data_width => 32,
|
|
byte_sel_width => 4,
|
|
async_timespec => ts_sram
|
|
)
|
|
PORT MAP
|
|
(
|
|
CLK_I => clk,
|
|
RST_I => rst,
|
|
CYC_I => CYC_I_sram,
|
|
STB_I => STB_O,
|
|
WE_I => WE_O,
|
|
ACK_O => ACK_O_sram,
|
|
SRDY_O => SRDY_O_sram,
|
|
MRDY_I => MRDY_O,
|
|
SEL_I => SEL_O,
|
|
ADDR_I => ADDR_O,
|
|
DAT_I => DAT_O,
|
|
DAT_O => DAT_O_sram,
|
|
page_mode_en => '0',
|
|
async_a => sram_a,
|
|
async_d => sram_d,
|
|
async_cs => sram_cs_n,
|
|
async_wr => sram_wr_n,
|
|
async_rd => sram_oe_n,
|
|
async_be => sram_be_n,
|
|
async_rst => open
|
|
);
|
|
|
|
inst_uart : entity work.uart_wb
|
|
GENERIC MAP
|
|
(
|
|
simulate_tx => true
|
|
)
|
|
PORT MAP
|
|
(
|
|
CLK_I => clk,
|
|
RST_I => rst,
|
|
CYC_I => CYC_I_uart,
|
|
STB_I => STB_O,
|
|
SEL_I => SEL_O,
|
|
WE_I => WE_O,
|
|
ACK_O => ACK_O_uart,
|
|
SRDY_O => SRDY_O_uart,
|
|
MRDY_I => MRDY_O,
|
|
ADDR_I => ADDR_O,
|
|
DAT_I => DAT_O,
|
|
DAT_O => DAT_O_uart,
|
|
INT_O => int_uart,
|
|
ser_rx => rx,
|
|
ser_tx => tx
|
|
);
|
|
|
|
------------------------------------------------------------------
|
|
SRAM_READ:
|
|
process(sram_a, sram_cs_n, sram_oe_n, sram_be_n)
|
|
begin
|
|
sram_d <= (others => 'Z') after 10 ns;
|
|
if sram_oe_n = '0' then
|
|
if sram_cs_n = '0' then
|
|
if sram_be_n(0) = '0' then
|
|
sram_d(7 downto 0) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) after 10 ns;
|
|
end if;
|
|
if sram_be_n(1) = '0' then
|
|
sram_d(15 downto 8) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) after 10 ns;
|
|
end if;
|
|
if sram_be_n(2) = '0' then
|
|
sram_d(23 downto 16) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) after 10 ns;
|
|
end if;
|
|
if sram_be_n(3) = '0' then
|
|
sram_d(31 downto 24) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) after 10 ns;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
SRAM_WRITE:
|
|
process(sram_wr_n)
|
|
begin
|
|
if rising_edge(sram_wr_n) then
|
|
if sram_cs_n = '0' then
|
|
if sram_be_n(0) = '0' then
|
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) <= sram_d(7 downto 0);
|
|
end if;
|
|
if sram_be_n(1) = '0' then
|
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) <= sram_d(15 downto 8);
|
|
end if;
|
|
if sram_be_n(2) = '0' then
|
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) <= sram_d(23 downto 16);
|
|
end if;
|
|
if sram_be_n(3) = '0' then
|
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) <= sram_d(31 downto 24);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
FLASH_READ:
|
|
process(rst, flash_cs_n, flash_oe_n, flash_a)
|
|
type file_t is file of integer;
|
|
-- file load_flash : file_t open read_mode is "ucb.elf.flash.bin";
|
|
file load_flash : file_t open read_mode is "test_timer.elf.flash.bin";
|
|
-- file load_flash : file_t open read_mode is "test_dcache.flash.bin";
|
|
variable instr : integer;
|
|
variable index : natural;
|
|
variable temp : signed(31 downto 0);
|
|
constant tpd : time := 25 ns;
|
|
begin
|
|
if rst = '1' then
|
|
index := 0;
|
|
while not endfile(load_flash) loop
|
|
read(load_flash, instr);
|
|
temp := to_signed(instr, word_t'length);
|
|
flash_data(index) <= unsigned(temp);
|
|
index := index + 1;
|
|
end loop;
|
|
else
|
|
flash_d <= (others => 'Z') after tpd;
|
|
index := to_integer(flash_a(FLASH_ADDR_WIDTH-1 downto 2));
|
|
if flash_oe_n = '0' then
|
|
if flash_cs_n = '0' then
|
|
if flash_be_n(0) = '0' then
|
|
flash_d(7 downto 0) <= flash_data(index)(7 downto 0) after tpd;
|
|
end if;
|
|
if flash_be_n(1) = '0' then
|
|
flash_d(15 downto 8) <= flash_data(index)(15 downto 8) after tpd;
|
|
end if;
|
|
if flash_be_n(2) = '0' then
|
|
flash_d(23 downto 16) <= flash_data(index)(23 downto 16) after tpd;
|
|
end if;
|
|
if flash_be_n(3) = '0' then
|
|
flash_d(31 downto 24) <= flash_data(index)(31 downto 24) after tpd;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------
|
|
STIMULUS: process
|
|
|
|
begin
|
|
|
|
gpi_0 <= X"00000000";
|
|
wait for 3*CLK_PERIOD;
|
|
wait until rising_edge(clk);
|
|
rst <= '0';
|
|
wait for 778254*CLK_PERIOD;
|
|
wait until rising_edge(clk);
|
|
nmi <= '0';
|
|
wait for 3000*CLK_PERIOD;
|
|
wait until rising_edge(clk);
|
|
nmi <= '0';
|
|
|
|
wait;
|
|
|
|
end process;
|
|
|
|
END;
|