From 836e446d8bfbdd7ac55eb2e8876d96678e2de392 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Fri, 27 Nov 2009 08:30:51 +0000 Subject: [PATCH] Initial version Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@688 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/dist/tmpl/tb_mips_top.vhd | 453 ++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 lib/CPUs/MIPS/dist/tmpl/tb_mips_top.vhd diff --git a/lib/CPUs/MIPS/dist/tmpl/tb_mips_top.vhd b/lib/CPUs/MIPS/dist/tmpl/tb_mips_top.vhd new file mode 100644 index 0000000..fd4d6f4 --- /dev/null +++ b/lib/CPUs/MIPS/dist/tmpl/tb_mips_top.vhd @@ -0,0 +1,453 @@ +------------------------------------------------------------------------- +-- 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 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 gpo0 : unsigned(31 downto 0); + signal gpo1 : unsigned(31 downto 0); + signal gpi0 : unsigned(31 downto 0) := (others => '0'); + signal gpi1 : unsigned(31 downto 0) := (others => '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, + 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, + 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_gpo0 => gpo0, + sys_gpo1 => gpo1, + sys_gpi0 => gpi0, + sys_gpi1 => gpi1 + ); + +inst_flash_port : entity work.async_port_wb + GENERIC MAP + ( + 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 + ( + 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 + 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 "hello.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 + + + 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;