diff --git a/lib/CPUs/JCpu/src/tb_cpu_irq.vhd b/lib/CPUs/JCpu/src/tb_cpu_irq.vhd new file mode 100644 index 0000000..8a19414 --- /dev/null +++ b/lib/CPUs/JCpu/src/tb_cpu_irq.vhd @@ -0,0 +1,205 @@ +------------------------------------------------------------------------- +-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL +-- This file: Formal test of correct function of 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; +use std.textio.all; -- Imports the standard textio package. + +library work; +use work.cpu_pkg.all; +use work.PCK_FIO.all; + +ENTITY tb_cpu IS +END tb_cpu; + +ARCHITECTURE behavior OF tb_cpu IS + + COMPONENT cpu + Generic ( + use_instr_register : boolean; + use_ctrl_rom : boolean + ); + Port ( + rst : in STD_LOGIC; + clk : in STD_LOGIC; + ce : in STD_LOGIC; + int_in : in STD_LOGIC; + int_ack : out STD_LOGIC; + xmem_we : out STD_LOGIC; + xmem_re : out STD_LOGIC; + instr_din : in unsigned (IMEM_DATA_WIDTH-1 downto 0); + instr_addr : out unsigned (IMEM_ADDR_WIDTH-1 downto 0); + xmem_din : in unsigned (DMEM_DATA_WIDTH-1 downto 0); + xmem_dout : out unsigned (DMEM_DATA_WIDTH-1 downto 0); + xmem_addr : out unsigned (DMEM_DATA_WIDTH-1 downto 0); + io_sel : out STD_LOGIC + + ); + END COMPONENT; + + COMPONENT irom + Port ( + clk : in STD_LOGIC; + ce : in STD_LOGIC; + addr : in inst_addr_t; + dout : out inst_t + ); + END COMPONENT; + + constant CLK_PERIOD : time := 10 ns; + type prom_t is array (integer range <>) of inst_t; + type sram_t is array (integer range <>) of dmem_data_t; + signal rst : std_logic := '1'; + signal clk : std_logic := '1'; + signal ce : std_logic := '0'; + signal int_in : std_logic := '0'; + signal int_ack : std_logic; + signal irom_data : unsigned (IMEM_DATA_WIDTH-1 downto 0) := (others => '-'); + signal irom_addr : unsigned (IMEM_ADDR_WIDTH-1 downto 0); + signal xmem_din : dmem_data_t := (others => '-'); + signal xmem_dout : dmem_data_t; + signal xmem_addr : unsigned (DMEM_DATA_WIDTH-1 downto 0); + signal xmem_we : std_logic; + signal xmem_re : std_logic; + signal io_sel : std_logic; + signal sram : sram_t(0 to 2**DMEM_DATA_WIDTH-1); + + type reg_t is record + revision : dmem_data_t; + testid : dmem_data_t; + interrupt : std_logic; + end record; + + signal reg : reg_t; + + +BEGIN + +uut: cpu + GENERIC MAP + ( + use_instr_register => false, + use_ctrl_rom => true + ) + PORT MAP( + rst => rst, + clk => clk, + ce => ce, + int_in => int_in, + int_ack => int_ack, + xmem_we => xmem_we, + xmem_re => xmem_re, + instr_din => irom_data, + instr_addr => irom_addr, + xmem_din => xmem_din, + xmem_dout => xmem_dout, + xmem_addr => xmem_addr, + io_sel => io_sel + ); + +the_irom: irom + PORT MAP( + clk => clk, + ce => ce, + addr => irom_addr, + dout => irom_data + ); + +CLK_GEN: process + begin + wait for CLK_PERIOD/2; + clk <= not clk; + end process; + +STIMULUS: process + file RESULT: text open write_mode is "../tools/opc.list"; + variable L: line; + + begin + + for i in 0 to instr_name_array'length-1 loop + fprint(RESULT, L,"%d %s\n", fo(i), instr_name_array(i)); + end loop; + + wait for 3*CLK_PERIOD; + rst <= '0'; + wait for 2*CLK_PERIOD; + + wait until rising_edge(clk); + ce <= '1'; + + wait for 1000*CLK_PERIOD; + + for i in 1 to 100 loop + wait until rising_edge(clk); + int_in <= '1'; + wait until rising_edge(clk) and int_ack = '1'; + int_in <= '0'; + wait for 300*CLK_PERIOD; + end loop; + + assert false report "Test finished" severity error; + wait; + + end process; + +SRAM_RW: process(rst, clk) + begin + if (rst = '1') then + reg.revision <= (others => '0'); + reg.testid <= (others => '0'); + elsif rising_edge(clk) then + if xmem_we = '1' then + if io_sel = '0' then + sram(to_integer(xmem_addr)) <= xmem_dout; + else + case xmem_addr is + when X"00" => + reg.revision <= xmem_dout; + when X"01" => + reg.testid <= xmem_dout; + when X"02" => + reg.interrupt <= xmem_dout(0); + when others => null; + end case; + end if; + else + if io_sel = '0' then + xmem_din <= to_01(sram(to_integer(xmem_addr))); + else + case xmem_addr is + when X"00" => + xmem_din <= reg.revision; + when X"01" => + xmem_din <= reg.testid; + when others => + xmem_din <= X"BC"; + end case; + end if; + end if; + end if; + end process; + +END;