git-svn-id: http://moon:8086/svn/vhdl/trunk@128 cc03376c-175c-47c8-b038-4cd826a8556b
333 lines
7.9 KiB
VHDL
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;
|