Files
vhdl/lib/CPUs/MIPS/src/tb_mips_muldiv.vhd
T
jens 529658b710 - fixed some bugs
git-svn-id: http://moon:8086/svn/vhdl/trunk@128 cc03376c-175c-47c8-b038-4cd826a8556b
2008-10-26 23:17:57 +00:00

333 lines
7.9 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;
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;