------------------------------------------------------------------------- -- 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; ENTITY tb_mips_muldiv IS END tb_mips_muldiv; ARCHITECTURE behavior OF tb_mips_muldiv IS COMPONENT muldiv is Port ( rst : in std_logic; clk : in std_logic; hilo_we : in std_logic; din_hi : in word_t; din_lo : in word_t; mul_divn : in std_logic; s_un : in std_logic; start : in std_logic; hilo_sel : in std_logic; busy : out std_logic; dout : out word_t ); END COMPONENT; constant CLK_PERIOD : time := 10 ns; signal ENABLE_FAIL_REPORT : boolean := true; signal rst : std_logic := '1'; signal clk : std_logic := '1'; signal busy : std_logic; signal mul_divn : std_logic := '0'; signal s_un : std_logic := '1'; signal hilo_we : std_logic := '0'; signal start : std_logic := '0'; signal din_hi : word_t := (others => '-'); signal din_lo : word_t := (others => '-'); signal dout : word_t; signal hilo_sel : std_logic := '0'; signal md_result : unsigned (2*word_t'length-1 downto 0) := (others => '0'); signal ref_result : unsigned (2*word_t'length-1 downto 0); signal ref_hi : unsigned (word_t'length-1 downto 0); signal rtmp : unsigned (2*word_t'length-1 downto 0); signal tmp2 : unsigned (word_t'length-1 downto 0); signal check : std_logic; type word_array_t is array (natural range <>) of word_t; constant operands : word_array_t(0 to 63) := ( X"00000000", X"00000001", X"00000010", X"00000100", X"00001000", X"00010000", X"00100000", X"01000000", X"10000000", X"0000000F", X"000000FF", X"00000FFF", X"0000FFFF", X"000FFFFF", X"00FFFFFF", X"0FFFFFFF", X"12345678", X"23456789", X"7FFFFFFF", X"80000000", X"A541B3B9", X"80000001", X"80000010", X"80000100", X"80001000", X"80010000", X"80100000", X"81000000", X"87654321", X"98765432", X"FFFFFFFF", X"FFFFFFFE", X"FFFFFFFD", X"FFFFFFFB", X"FFFFFFF7", X"FFFFFFEF", X"FFFFFFDF", X"FFFFFFBF", X"FFFFFF7F", X"FFFFFEFF", X"FFFFFDFF", X"FFFFFBFF", X"FFFFF7FF", X"FFFFEFFF", X"FFFFDFFF", X"FFFFBFFF", X"FFFF7FFF", X"FFFEFFFF", X"FFFDFFFF", X"FFFBFFFF", X"FFF7FFFF", X"FFEFFFFF", X"FFDFFFFF", X"FFBFFFFF", X"FF7FFFFF", X"FEFFFFFF", X"FDFFFFFF", X"FBFFFFFF", X"F7FFFFFF", X"EFFFFFFF", X"DFFFFFFF", X"BFFFFFFF", X"CFFFFFFF", X"7FFFFFFF" ); BEGIN uut: muldiv PORT MAP( rst => rst, clk => clk, hilo_we => hilo_we, din_hi => din_hi, din_lo => din_lo, mul_divn => mul_divn, s_un => s_un, start => start, hilo_sel => hilo_sel, busy => busy, dout => dout ); CLK_GEN: process begin wait for CLK_PERIOD/2; clk <= not clk; end process; REF_GEN: process begin if mul_divn = '0' then wait until rising_edge(clk) and check = '1'; if s_un = '1' then rtmp <= unsigned(signed(md_result(31 downto 0)) * signed(din_lo)); wait until rising_edge(clk); tmp2 <= unsigned(signed(rtmp(31 downto 0)) + signed(md_result(63 downto 32))); wait until rising_edge(clk); ref_hi <= tmp2(31 downto 0); else rtmp <= md_result(31 downto 0) * din_lo; wait until rising_edge(clk); tmp2 <= rtmp(31 downto 0) + md_result(63 downto 32); wait until rising_edge(clk); ref_hi <= tmp2(31 downto 0); end if; wait until rising_edge(clk); if din_lo /= X"00000000" then if ENABLE_FAIL_REPORT then assert din_hi = ref_hi report "Error on divison" severity failure; end if; end if; else wait until rising_edge(clk) and check = '1'; if s_un = '1' then ref_result <= unsigned(signed(din_hi) * signed(din_lo)); else ref_result <= unsigned(din_hi) * unsigned(din_lo); end if; wait until rising_edge(clk); wait until rising_edge(clk); wait until rising_edge(clk); if ENABLE_FAIL_REPORT then assert ref_result = md_result report "Error on multiplication" severity failure; end if; end if; end process; STIMULUS: process begin wait for 3*CLK_PERIOD; wait until rising_edge(clk); rst <= '0'; wait for 2*CLK_PERIOD; mul_divn <= '0'; s_un <= '0'; for i in 0 to operands'length-1 loop for j in 0 to operands'length-1 loop check <= '0'; wait until rising_edge(clk) and busy = '0'; din_hi <= operands(i); din_lo <= operands(j); start <= '1'; wait until rising_edge(clk); start <= '0'; hilo_sel <= '0'; -- Read result wait until rising_edge(clk) and busy = '0'; wait until rising_edge(clk); md_result(31 downto 0) <= dout; wait until rising_edge(clk); hilo_sel <= '1'; wait until rising_edge(clk); md_result(63 downto 32) <= dout; check <= '1'; wait until rising_edge(clk); check <= '0'; wait for 8*CLK_PERIOD; end loop; end loop; s_un <= '1'; for i in 0 to operands'length-1 loop for j in 0 to operands'length-1 loop check <= '0'; wait until rising_edge(clk) and busy = '0'; din_hi <= operands(i); din_lo <= operands(j); start <= '1'; wait until rising_edge(clk); start <= '0'; hilo_sel <= '0'; -- Read result wait until rising_edge(clk) and busy = '0'; wait until rising_edge(clk); md_result(31 downto 0) <= dout; wait until rising_edge(clk); hilo_sel <= '1'; wait until rising_edge(clk); md_result(63 downto 32) <= dout; check <= '1'; wait until rising_edge(clk); check <= '0'; wait for 8*CLK_PERIOD; end loop; end loop; mul_divn <= '1'; s_un <= '0'; for i in 0 to operands'length-1 loop for j in 0 to operands'length-1 loop check <= '0'; wait until rising_edge(clk) and busy = '0'; din_hi <= operands(i); din_lo <= operands(j); start <= '1'; wait until rising_edge(clk); start <= '0'; hilo_sel <= '0'; -- Read result wait until rising_edge(clk) and busy = '0'; wait until rising_edge(clk); md_result(31 downto 0) <= dout; wait until rising_edge(clk); hilo_sel <= '1'; wait until rising_edge(clk); md_result(63 downto 32) <= dout; check <= '1'; wait until rising_edge(clk); check <= '0'; wait for 8*CLK_PERIOD; end loop; end loop; s_un <= '1'; for i in 0 to operands'length-1 loop for j in 0 to operands'length-1 loop check <= '0'; wait until rising_edge(clk) and busy = '0'; din_hi <= operands(i); din_lo <= operands(j); start <= '1'; wait until rising_edge(clk); start <= '0'; hilo_sel <= '0'; -- Read result wait until rising_edge(clk) and busy = '0'; wait until rising_edge(clk); md_result(31 downto 0) <= dout; wait until rising_edge(clk); hilo_sel <= '1'; wait until rising_edge(clk); md_result(63 downto 32) <= dout; check <= '1'; wait until rising_edge(clk); check <= '0'; wait for 8*CLK_PERIOD; end loop; end loop; wait; end process; END;