|
| 1 | +-- This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | +-- License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| 3 | +-- You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4 | +-- |
| 5 | +-- Copyright (c) 2014, Lars Asplund lars.anders.asplund@gmail.com |
| 6 | + |
| 7 | +library ieee; |
| 8 | +use ieee.std_logic_1164.all; |
| 9 | +use ieee.numeric_std.all; |
| 10 | + |
| 11 | +library vunit_lib; |
| 12 | +context vunit_lib.vunit_context; |
| 13 | +use vunit_lib.array_pkg.all; |
| 14 | + |
| 15 | + |
| 16 | +library osvvm; |
| 17 | +use osvvm.RandomPkg.all; |
| 18 | + |
| 19 | +entity tb_sobel_x is |
| 20 | + generic ( |
| 21 | + runner_cfg : runner_cfg_t; |
| 22 | + data_width : natural := 14; |
| 23 | + output_path : string); |
| 24 | +end entity; |
| 25 | + |
| 26 | +architecture tb of tb_sobel_x is |
| 27 | + signal clk : std_logic := '0'; |
| 28 | + signal input_tvalid : std_logic := '0'; |
| 29 | + signal input_tlast : std_logic := '0'; |
| 30 | + signal input_tdata : unsigned(data_width-1 downto 0) := (others => '0'); |
| 31 | + signal output_tvalid : std_logic; |
| 32 | + signal output_tlast : std_logic; |
| 33 | + signal output_tdata : signed(input_tdata'length downto 0); |
| 34 | + |
| 35 | + shared variable image : array_t; |
| 36 | + shared variable reference_image : array_t; |
| 37 | + signal start, data_check_done, stimuli_done : boolean := false; |
| 38 | +begin |
| 39 | + |
| 40 | + main : process |
| 41 | + procedure sobel_x(variable image : inout array_t; |
| 42 | + variable result : inout array_t) is |
| 43 | + begin |
| 44 | + result.init_2d(width => image.width, |
| 45 | + height => image.height, |
| 46 | + bit_width => image.bit_width+1, |
| 47 | + is_signed => true); |
| 48 | + |
| 49 | + for y in 0 to image.height-1 loop |
| 50 | + for x in 0 to image.width-1 loop |
| 51 | + result.set(x, y, |
| 52 | + value => (image.get(minimum(x+1, image.width-1),y) - |
| 53 | + image.get(maximum(x-1, 0), y))); |
| 54 | + end loop; |
| 55 | + end loop; |
| 56 | + |
| 57 | + end procedure; |
| 58 | + |
| 59 | + variable rnd : RandomPType; |
| 60 | + |
| 61 | + procedure randomize(variable arr : inout array_t) is |
| 62 | + begin |
| 63 | + for idx in 0 to arr.length-1 loop |
| 64 | + arr.set(idx, value => rnd.RandInt(arr.lower_limit, arr.upper_limit)); |
| 65 | + end loop; |
| 66 | + end procedure; |
| 67 | + |
| 68 | + procedure test_one_image(width, height : natural) is |
| 69 | + begin |
| 70 | + image.init_2d(width => width, height => height, |
| 71 | + bit_width => input_tdata'length, |
| 72 | + is_signed => false); |
| 73 | + randomize(image); |
| 74 | + sobel_x(image, result => reference_image); |
| 75 | + |
| 76 | + wait until rising_edge(clk); |
| 77 | + start <= true; |
| 78 | + wait until rising_edge(clk); |
| 79 | + start <= false; |
| 80 | + |
| 81 | + wait until (stimuli_done and |
| 82 | + data_check_done and |
| 83 | + rising_edge(clk)); |
| 84 | + end procedure; |
| 85 | + |
| 86 | + begin |
| 87 | + test_runner_setup(runner, runner_cfg); |
| 88 | + rnd.InitSeed(rnd'instance_name); |
| 89 | + test_one_image(128, 64); |
| 90 | + test_one_image(1, 13); |
| 91 | + test_one_image(16, 1); |
| 92 | + test_one_image(1, 1); |
| 93 | + test_runner_cleanup(runner); |
| 94 | + wait; |
| 95 | + end process; |
| 96 | + |
| 97 | + stimuli_process : process |
| 98 | + begin |
| 99 | + wait until start and rising_edge(clk); |
| 100 | + stimuli_done <= false; |
| 101 | + |
| 102 | + report ("Sending image of size " & |
| 103 | + to_string(image.width) & "x" & |
| 104 | + to_string(image.height)); |
| 105 | + |
| 106 | + for y in 0 to image.height-1 loop |
| 107 | + for x in 0 to image.width-1 loop |
| 108 | + wait until rising_edge(clk); |
| 109 | + input_tvalid <= '1'; |
| 110 | + input_tlast <= '1' when x = image.width-1 else '0'; |
| 111 | + input_tdata <= to_unsigned(image.get(x,y), input_tdata'length); |
| 112 | + end loop; |
| 113 | + end loop; |
| 114 | + |
| 115 | + wait until rising_edge(clk); |
| 116 | + input_tvalid <= '0'; |
| 117 | + |
| 118 | + stimuli_done <= true; |
| 119 | + end process; |
| 120 | + |
| 121 | + data_check_process : process |
| 122 | + begin |
| 123 | + wait until start and rising_edge(clk); |
| 124 | + data_check_done <= false; |
| 125 | + for y in 0 to reference_image.height-1 loop |
| 126 | + for x in 0 to reference_image.width-1 loop |
| 127 | + wait until output_tvalid = '1' and rising_edge(clk); |
| 128 | + check_equal(output_tlast, x = reference_image.width-1); |
| 129 | + check_equal(output_tdata, reference_image.get(x, y), |
| 130 | + "x=" & to_string(x) & " y=" & to_string(y)); |
| 131 | + end loop; |
| 132 | + end loop; |
| 133 | + report ("Done checking image of size " & |
| 134 | + to_string(reference_image.width) & "x" & |
| 135 | + to_string(reference_image.height)); |
| 136 | + data_check_done <= true; |
| 137 | + end process; |
| 138 | + |
| 139 | + clk <= not clk after 1 ns; |
| 140 | + |
| 141 | + dut : entity work.sobel_x |
| 142 | + generic map ( |
| 143 | + data_width => input_tdata'length) |
| 144 | + port map ( |
| 145 | + clk => clk, |
| 146 | + input_tvalid => input_tvalid, |
| 147 | + input_tlast => input_tlast, |
| 148 | + input_tdata => input_tdata, |
| 149 | + output_tvalid => output_tvalid, |
| 150 | + output_tlast => output_tlast, |
| 151 | + output_tdata => output_tdata); |
| 152 | + |
| 153 | +end architecture; |
0 commit comments