Add VHDL testbench and makefile for simulation with GHDL.
This commit is contained in:
parent
3bdea4b312
commit
73c857b92d
|
@ -0,0 +1,32 @@
|
|||
|
||||
GHDL = ghdl
|
||||
|
||||
TESTS = smul_4_4 smul_7_8 smul_8_8 smul_10_11 smul_4_12 smul_18_18 smul_19_24
|
||||
|
||||
tb: tb.o smul_lib.o $(patsubst %,%.o,$(TESTS))
|
||||
$(GHDL) -e tb
|
||||
|
||||
tb.o: tb.vhdl smul_lib.o $(patsubst %,%.o,$(TESTS))
|
||||
|
||||
smul_%.o: smul_%.vhdl smul_lib.o
|
||||
|
||||
%.o: %.vhdl
|
||||
$(GHDL) -a $<
|
||||
|
||||
smul_lib.vhdl: ../genmul.py
|
||||
python ../genmul.py --lang=vhdl --lib > smul_lib.vhdl
|
||||
|
||||
$(patsubst %,%.vhdl,$(TESTS)): ../genmul.py
|
||||
python ../genmul.py --lang=vhdl --nolib 4 4 0 > smul_4_4.vhdl
|
||||
python ../genmul.py --lang=vhdl --nolib 7 8 0 > smul_7_8.vhdl
|
||||
python ../genmul.py --lang=vhdl --nolib 8 8 0 > smul_8_8.vhdl
|
||||
python ../genmul.py --lang=vhdl --nolib 10 11 0 > smul_10_11.vhdl
|
||||
python ../genmul.py --lang=vhdl --nolib 4 12 1 > smul_4_12.vhdl
|
||||
python ../genmul.py --lang=vhdl --nolib 18 18 2 > smul_18_18.vhdl
|
||||
python ../genmul.py --lang=vhdl --nolib 19 24 1 > smul_19_24.vhdl
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(GHDL) --clean
|
||||
$(RM) -- work-obj93.cf
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
--
|
||||
-- Test bench for signed multiplier.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity tb is
|
||||
end entity;
|
||||
|
||||
architecture arch of tb is
|
||||
|
||||
procedure test_mul(constant xbits: in integer;
|
||||
constant ybits: in integer;
|
||||
constant npipe: in integer;
|
||||
signal clk: out std_ulogic;
|
||||
signal xin: out std_logic_vector;
|
||||
signal yin: out std_logic_vector;
|
||||
signal zout: in std_logic_vector) is
|
||||
variable all_x: boolean;
|
||||
variable all_y: boolean;
|
||||
variable num_x: integer;
|
||||
variable num_y: integer;
|
||||
variable x: integer;
|
||||
variable y: integer;
|
||||
variable i: integer;
|
||||
type pipe_type is array (0 to npipe) of integer;
|
||||
variable px, py: pipe_type;
|
||||
begin
|
||||
|
||||
-- Test all X inputs if xbits <= 11; otherwise test a subset.
|
||||
all_x := (xbits <= 11);
|
||||
if all_x then
|
||||
num_x := 2**xbits;
|
||||
else
|
||||
num_x := (xbits-8) * 2 * 256;
|
||||
end if;
|
||||
|
||||
-- Test all Y inputs if ybits <= 11; otherwise test a subset.
|
||||
all_y := (ybits <= 11);
|
||||
if all_y then
|
||||
num_y := 2**ybits;
|
||||
else
|
||||
num_y := (ybits-8) * 2 * 256;
|
||||
end if;
|
||||
|
||||
i := 0;
|
||||
|
||||
for kx in 0 to num_x-1 loop
|
||||
|
||||
if all_x then
|
||||
x := kx - 2**(xbits-1);
|
||||
else
|
||||
x := (kx mod 512 - 256) * 2**(kx/512);
|
||||
end if;
|
||||
|
||||
for ky in 0 to num_y-1 loop
|
||||
|
||||
if all_y then
|
||||
y := ky - 2**(ybits-1);
|
||||
else
|
||||
y := (ky mod 512 - 256) * (2**(ky/512));
|
||||
end if;
|
||||
|
||||
clk <= '0';
|
||||
xin <= std_logic_vector(to_signed(x, xbits));
|
||||
yin <= std_logic_vector(to_signed(y, ybits));
|
||||
wait for 5 ns;
|
||||
|
||||
px(1 to npipe) := px(0 to npipe-1);
|
||||
py(1 to npipe) := py(0 to npipe-1);
|
||||
px(0) := x;
|
||||
py(0) := y;
|
||||
|
||||
if i >= npipe then
|
||||
assert zout =
|
||||
std_logic_vector(to_signed(px(npipe), xbits) *
|
||||
to_signed(py(npipe), ybits));
|
||||
end if;
|
||||
|
||||
clk <= '1';
|
||||
wait for 5 ns;
|
||||
|
||||
i := i + 1;
|
||||
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
xin(xin'high downto xin'low) <= (others => 'U');
|
||||
yin(yin'high downto yin'low) <= (others => 'U');
|
||||
|
||||
for i in 1 to npipe loop
|
||||
|
||||
px(1 to npipe) := px(0 to npipe-1);
|
||||
py(1 to npipe) := py(0 to npipe-1);
|
||||
assert zout = std_logic_vector(to_signed(px(npipe), xbits) *
|
||||
to_signed(py(npipe), ybits));
|
||||
|
||||
clk <= '0';
|
||||
wait for 5 ns;
|
||||
clk <= '1';
|
||||
wait for 5 ns;
|
||||
|
||||
end loop;
|
||||
|
||||
clk <= '0';
|
||||
|
||||
end procedure;
|
||||
|
||||
signal s1_clk: std_ulogic;
|
||||
signal s1_xin: std_logic_vector(3 downto 0);
|
||||
signal s1_yin: std_logic_vector(3 downto 0);
|
||||
signal s1_zout: std_logic_vector(7 downto 0);
|
||||
signal s2_clk: std_ulogic;
|
||||
signal s2_xin: std_logic_vector(6 downto 0);
|
||||
signal s2_yin: std_logic_vector(7 downto 0);
|
||||
signal s2_zout: std_logic_vector(14 downto 0);
|
||||
signal s3_clk: std_ulogic;
|
||||
signal s3_xin: std_logic_vector(7 downto 0);
|
||||
signal s3_yin: std_logic_vector(7 downto 0);
|
||||
signal s3_zout: std_logic_vector(15 downto 0);
|
||||
signal s4_clk: std_ulogic;
|
||||
signal s4_xin: std_logic_vector(9 downto 0);
|
||||
signal s4_yin: std_logic_vector(10 downto 0);
|
||||
signal s4_zout: std_logic_vector(20 downto 0);
|
||||
signal s5_clk: std_ulogic;
|
||||
signal s5_xin: std_logic_vector(3 downto 0);
|
||||
signal s5_yin: std_logic_vector(11 downto 0);
|
||||
signal s5_zout: std_logic_vector(15 downto 0);
|
||||
signal s6_clk: std_ulogic;
|
||||
signal s6_xin: std_logic_vector(17 downto 0);
|
||||
signal s6_yin: std_logic_vector(17 downto 0);
|
||||
signal s6_zout: std_logic_vector(35 downto 0);
|
||||
signal s7_clk: std_ulogic;
|
||||
signal s7_xin: std_logic_vector(18 downto 0);
|
||||
signal s7_yin: std_logic_vector(23 downto 0);
|
||||
signal s7_zout: std_logic_vector(42 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- Signed 4x4 multiplier, latency 0 clocks.
|
||||
u1: entity work.smul_4_4
|
||||
port map ( clk => s1_clk,
|
||||
clken => '1',
|
||||
xin => s1_xin,
|
||||
yin => s1_yin,
|
||||
zout => s1_zout );
|
||||
|
||||
-- Signed 7x8 multiplier, latency 0 clocks.
|
||||
u2: entity work.smul_7_8
|
||||
port map ( clk => s2_clk,
|
||||
clken => '1',
|
||||
xin => s2_xin,
|
||||
yin => s2_yin,
|
||||
zout => s2_zout );
|
||||
|
||||
-- Signex 8x8 multiplier, latency 0 clocks.
|
||||
u3: entity work.smul_8_8
|
||||
port map ( clk => s3_clk,
|
||||
clken => '1',
|
||||
xin => s3_xin,
|
||||
yin => s3_yin,
|
||||
zout => s3_zout );
|
||||
|
||||
-- Signex 10x11 multiplier, latency 0 clocks.
|
||||
u4: entity work.smul_10_11
|
||||
port map ( clk => s4_clk,
|
||||
clken => '1',
|
||||
xin => s4_xin,
|
||||
yin => s4_yin,
|
||||
zout => s4_zout );
|
||||
|
||||
-- Signex 4x12 multiplier, latency 1 clock.
|
||||
u5: entity work.smul_4_12
|
||||
port map ( clk => s5_clk,
|
||||
clken => '1',
|
||||
xin => s5_xin,
|
||||
yin => s5_yin,
|
||||
zout => s5_zout );
|
||||
|
||||
-- Signex 18x18 multiplier, latency 2 clocks.
|
||||
u6: entity work.smul_18_18
|
||||
port map ( clk => s6_clk,
|
||||
clken => '1',
|
||||
xin => s6_xin,
|
||||
yin => s6_yin,
|
||||
zout => s6_zout );
|
||||
|
||||
-- Signex 19x24 multiplier, latency 1 clock.
|
||||
u7: entity work.smul_19_24
|
||||
port map ( clk => s7_clk,
|
||||
clken => '1',
|
||||
xin => s7_xin,
|
||||
yin => s7_yin,
|
||||
zout => s7_zout );
|
||||
|
||||
process is
|
||||
begin
|
||||
|
||||
report "Start test bench";
|
||||
|
||||
report "Testing 4x4 multiplier, latency 0";
|
||||
test_mul(4, 4, 0, s1_clk, s1_xin, s1_yin, s1_zout);
|
||||
|
||||
report "Testing 7x8 multiplier, latency 0";
|
||||
test_mul(7, 8, 0, s2_clk, s2_xin, s2_yin, s2_zout);
|
||||
|
||||
report "Testing 8x8 multiplier, latency 0";
|
||||
test_mul(8, 8, 0, s3_clk, s3_xin, s3_yin, s3_zout);
|
||||
|
||||
report "Testing 10x11 multiplier, latency 0";
|
||||
test_mul(10, 11, 0, s4_clk, s4_xin, s4_yin, s4_zout);
|
||||
|
||||
report "Testing 4x12 multiplier, latency 1 (subset of inputs)";
|
||||
test_mul(4, 12, 1, s5_clk, s5_xin, s5_yin, s5_zout);
|
||||
|
||||
report "Testing 18x18 multiplier, latency 2 (subset of inputs)";
|
||||
test_mul(18, 18, 2, s6_clk, s6_xin, s6_yin, s6_zout);
|
||||
|
||||
report "Testing 19x24 multiplier, latency 1 (subset of inputs)";
|
||||
test_mul(19, 24, 1, s7_clk, s7_xin, s7_yin, s7_zout);
|
||||
|
||||
report "End test bench";
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
end architecture;
|
Loading…
Reference in New Issue