------------------------------------------------------------------------- -- 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 . -- -- 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;