diff --git a/docs/verification_components/user_guide.rst b/docs/verification_components/user_guide.rst index 8dc67ee0c..81a56c036 100644 --- a/docs/verification_components/user_guide.rst +++ b/docs/verification_components/user_guide.rst @@ -107,6 +107,4 @@ and the VC-developers. :maxdepth: 1 :hidden: - vci/bus_master - vci/stream - vci/sync + vci/vci diff --git a/docs/verification_components/vci/bus_master.rst b/docs/verification_components/vci/bus_master.rst deleted file mode 100644 index cbc359631..000000000 --- a/docs/verification_components/vci/bus_master.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _bus_master_vci: - -Bus Master VCI -============== - -.. literalinclude:: ../../../vunit/vhdl/verification_components/src/bus_master_pkg.vhd - :caption: Bus master verification component interface - :language: vhdl - :lines: 7- diff --git a/docs/verification_components/vci/stream.rst b/docs/verification_components/vci/stream.rst deleted file mode 100644 index f8a0a273b..000000000 --- a/docs/verification_components/vci/stream.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _stream_vci: - -Stream Master VCI -================= - -.. literalinclude:: ../../../vunit/vhdl/verification_components/src/stream_master_pkg.vhd - :caption: Stream master verification component interface - :language: vhdl - :lines: 7- - -Stream Slave VCI -================ - -.. literalinclude:: ../../../vunit/vhdl/verification_components/src/stream_slave_pkg.vhd - :caption: Stream slave verification component interface - :language: vhdl - :lines: 7- diff --git a/docs/verification_components/vci/sync.rst b/docs/verification_components/vci/sync.rst deleted file mode 100644 index 6cc0a0e81..000000000 --- a/docs/verification_components/vci/sync.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _sync_vci: - -Synchronization VCI -=================== - -.. literalinclude:: ../../../vunit/vhdl/verification_components/src/sync_pkg.vhd - :caption: Synchronization verification component interface - :language: vhdl - :lines: 7- diff --git a/docs/verification_components/vci/vci.rst b/docs/verification_components/vci/vci.rst new file mode 100644 index 000000000..0b14bd9ad --- /dev/null +++ b/docs/verification_components/vci/vci.rst @@ -0,0 +1,37 @@ +.. _bus_master_vci: + +Bus Master VCI +============== + +.. literalinclude:: ../../../vunit/vhdl/verification_components/src/bus_master_pkg.vhd + :caption: Bus master verification component interface + :language: vhdl + :lines: 7- + +.. _stream_vci: + +Stream Master VCI +================= + +.. literalinclude:: ../../../vunit/vhdl/verification_components/src/stream_master_pkg.vhd + :caption: Stream master verification component interface + :language: vhdl + :lines: 7- + +Stream Slave VCI +================ + +.. literalinclude:: ../../../vunit/vhdl/verification_components/src/stream_slave_pkg.vhd + :caption: Stream slave verification component interface + :language: vhdl + :lines: 7- + +.. _sync_vci: + +Synchronization VCI +=================== + +.. literalinclude:: ../../../vunit/vhdl/verification_components/src/sync_pkg.vhd + :caption: Synchronization verification component interface + :language: vhdl + :lines: 7- diff --git a/examples/vhdl/array_axis_vcs/run.py b/examples/vhdl/array_axis_vcs/run.py deleted file mode 100644 index 8c4d45776..000000000 --- a/examples/vhdl/array_axis_vcs/run.py +++ /dev/null @@ -1,39 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. -# -# Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -""" -Array and AXI4 Stream Verification Components ---------------------------------------------- - -Demonstrates ``array_t``, ``axi_stream_master_t`` and ``axi_stream_slave_t`` -data types of ``array_pkg.vhd``, ``stream_master_pkg`` and ``stream_slave_pkg``, -respectively. Also, ``push_axi_stream`` of ``axi_stream_pkg`` is used. A CSV file -is read, the content is sent in a row-major order to an AXI Stream buffer (FIFO) -and it is received back to be saved in a different file. Further information can -be found in the :ref:`verification component library user guide `, -in subsection :ref:`Stream ` and in -:vunit_file:`vhdl/verification_components/test/tb_axi_stream.vhd `. -""" - -from os.path import join, dirname -from vunit import VUnit - -vu = VUnit.from_argv() - -vu.add_osvvm() -vu.add_array_util() -vu.add_verification_components() - -src_path = join(dirname(__file__), "src") - -vu.add_library("lib").add_source_files([ - join(src_path, "*.vhd"), - join(src_path, "**", "*.vhd") -]) - -# vu.set_sim_option('modelsim.init_files.after_load',['runall_addwave.do']) - -vu.main() diff --git a/examples/vhdl/array_axis_vcs/runall_addwave.do b/examples/vhdl/array_axis_vcs/runall_addwave.do deleted file mode 100644 index a267d3f0c..000000000 --- a/examples/vhdl/array_axis_vcs/runall_addwave.do +++ /dev/null @@ -1,5 +0,0 @@ -echo "Running DO File" -foreach v "vunit_axism vunit_axiss uut uut/fifo" { - add wave -group "$v" -position insertpoint sim:/tb_axis_loop/$v/* -} -run -all; diff --git a/examples/vhdl/array_axis_vcs/src/axis_buffer.vhd b/examples/vhdl/array_axis_vcs/src/axis_buffer.vhd deleted file mode 100644 index 63145d14d..000000000 --- a/examples/vhdl/array_axis_vcs/src/axis_buffer.vhd +++ /dev/null @@ -1,86 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -context ieee.ieee_std_context; - -entity axis_buffer is - generic ( - data_width : integer := 32; - fifo_depth : integer := 0 -- ceiling of the log base 2 of the desired FIFO length - ); - port ( - s_axis_clk : in std_logic; - s_axis_rstn : in std_logic; - s_axis_rdy : out std_logic; - s_axis_data : in std_logic_vector(data_width-1 downto 0); - s_axis_valid : in std_logic; - s_axis_strb : in std_logic_vector((data_width/8)-1 downto 0); - s_axis_last : in std_logic; - - m_axis_clk : in std_logic; - m_axis_rstn : in std_logic; - m_axis_valid : out std_logic; - m_axis_data : out std_logic_vector(data_width-1 downto 0); - m_axis_rdy : in std_logic; - m_axis_strb : out std_logic_vector((data_width/8)-1 downto 0); - m_axis_last : out std_logic - ); -end axis_buffer; - -architecture arch of axis_buffer is - - signal r, e, f, wr, rd, valid : std_logic; - signal d, q : std_logic_vector(data_width+data_width/8 downto 0); - -begin - - r <= (s_axis_rstn nand m_axis_rstn); - - fifo: entity work.fifo - generic map ( - fifo_depth => fifo_depth, - data_width => data_width+data_width/8+1 - ) - port map ( - CLKW => s_axis_clk, - CLKR => m_axis_clk, - RST => r, - WR => wr, - RD => rd, - E => e, - F => f, - D => d, - Q => q - ); - --- AXI4 Stream Slave logic - - wr <= s_axis_valid and (not f); - d <= s_axis_last & s_axis_strb & s_axis_data; - - s_axis_rdy <= not f; - --- AXI4 Stream Master logic - - rd <= (not e) and (valid nand (not m_axis_rdy)); - - process(m_axis_clk) begin - if rising_edge(m_axis_clk) then - if ((not m_axis_rstn) or ((valid and E) and m_axis_rdy))='1' then - valid <= '0'; - elsif rd then - valid <= '1'; - end if; - end if; - end process; - - m_axis_valid <= valid; - m_axis_last <= q(d'left); - m_axis_strb <= q(q'left-1 downto data_width); - m_axis_data <= q(data_width-1 downto 0); - -end architecture; diff --git a/examples/vhdl/array_axis_vcs/src/fifo.vhd b/examples/vhdl/array_axis_vcs/src/fifo.vhd deleted file mode 100644 index 5e835b4fa..000000000 --- a/examples/vhdl/array_axis_vcs/src/fifo.vhd +++ /dev/null @@ -1,104 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -context ieee.ieee_std_context; - -entity fifo is - generic ( - data_width : positive := 8; - fifo_depth : positive := 8 - ); - port ( - clkw : in std_logic; - clkr : in std_logic; - rst : in std_logic; - wr : in std_logic; - rd : in std_logic; - d : in std_logic_vector(data_width-1 downto 0); - e : out std_logic; - f : out std_logic; - q : out std_logic_vector(data_width-1 downto 0) - ); -end fifo; - -architecture arch of fifo is - - type fifo_t is array (0 to 2**fifo_depth-1) - of std_logic_vector(data_width-1 downto 0); - signal mem : fifo_t; - - signal rdp, wrp : unsigned(fifo_depth downto 0); - -begin - --- Assertions - process(clkw, clkr) - constant dx : std_logic_vector(d'left downto 0) := (others => 'X'); - constant du : std_logic_vector(d'left downto 0) := (others => 'U'); - begin - if rising_edge(clkw) then - if ( wr and ( d?=dx or d?=du ) ) then - assert false report "wrote X|U to fIfO" severity failure; - end if; - if (f and wr) then - assert false report "wrote to fIfO while full" severity failure; - end if; - end if; - if rising_edge(clkr) then - if (e and rd) then - assert false report "Read from fIfO while empty" severity failure; - end if; - end if; - end process; - --- - - process(clkw) begin - if rising_edge(clkw) then - if wr then - mem(to_integer(wrp(fifo_depth-1 downto 0))) <= d; - end if; - end if; - end process; - - process(clkw) begin - if rising_edge(clkw) then - if rst then - wrp <= (others => '0'); - else - if wr then - wrp <= wrp+1; - end if; - end if; - end if; - end process; - - f <= rdp(fifo_depth-1 downto 0)?=wrp(fifo_depth-1 downto 0) - and (rdp(fifo_depth) xor wrp(fifo_depth)); - e <= rdp ?= wrp; - - process(clkr) begin - if rising_edge(clkr) then - if rst then - q <= (others => '0'); - elsif rd then - q <= mem(to_integer(rdp(fifo_depth-1 downto 0))); - end if; - end if; - end process; - - process(clkr) begin - if rising_edge(clkr) then - if rst then - rdp <= (others => '0'); - else - if rd then rdp <= rdp+1; end if; - end if; - end if; - end process; - -end arch; diff --git a/examples/vhdl/array_axis_vcs/src/test/data/in.csv b/examples/vhdl/array_axis_vcs/src/test/data/in.csv deleted file mode 100644 index 8d2a3fdfd..000000000 --- a/examples/vhdl/array_axis_vcs/src/test/data/in.csv +++ /dev/null @@ -1,10 +0,0 @@ -0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 -256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275 -512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531 -768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787 -1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043 -1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299 -1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555 -1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811 -2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067 -2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323 diff --git a/examples/vhdl/array_axis_vcs/src/test/tb_axis_loop.vhd b/examples/vhdl/array_axis_vcs/src/test/tb_axis_loop.vhd deleted file mode 100644 index 5919f4f82..000000000 --- a/examples/vhdl/array_axis_vcs/src/test/tb_axis_loop.vhd +++ /dev/null @@ -1,186 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - --- This testbench is a Minimum Working Example (MWE) of VUnit's resources to read/write CSV files and to verify --- AXI4-Stream components. A CSV file that contains comma separated integers is read from `data_path & csv_i`, and it is --- sent row by row to an AXI4-Stream Slave. The AXI4-Stream Slave is expected to be connected to an AXI4-Stream Master --- either directly or (preferredly) through a FIFO, thus composing a loopback. Therefore, as data is pushed to the --- AXI4-Stream Slave interface, the output is read from the AXI4-Stream Master interface and it is saved to --- `data_path & csv_o`. - -library ieee; -context ieee.ieee_std_context; - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.vc_context; -use vunit_lib.array_pkg.all; - -entity tb_axis_loop is - generic ( - runner_cfg : string; - tb_path : string; - csv_i : string := "data/in.csv"; - csv_o : string := "data/out.csv" - ); -end entity; - -architecture tb of tb_axis_loop is - - -- Simulation constants - - constant clk_period : time := 20 ns; - constant data_width : natural := 32; - - -- AXI4Stream Verification Components - - constant master_axi_stream : axi_stream_master_t := new_axi_stream_master(data_length => data_width); - constant slave_axi_stream : axi_stream_slave_t := new_axi_stream_slave(data_length => data_width); - - -- Signals to/from the UUT from/to the verification components - - signal m_valid, m_ready, m_last, s_valid, s_ready, s_last : std_logic; - signal m_data, s_data : std_logic_vector(data_length(master_axi_stream)-1 downto 0); - - -- tb signals and variables - - signal clk, rst, rstn : std_logic := '0'; - shared variable m_I, m_O : array_t; - signal start, done, saved : boolean := false; - -begin - - clk <= not clk after clk_period/2; - rstn <= not rst; - - main: process - procedure run_test is begin - info("Init test"); - wait until rising_edge(clk); start <= true; - wait until rising_edge(clk); start <= false; - wait until (done and saved and rising_edge(clk)); - info("Test done"); - end procedure; - begin - test_runner_setup(runner, runner_cfg); - while test_suite loop - if run("test") then - rst <= '1'; - wait for 15*clk_period; - rst <= '0'; - run_test; - end if; - end loop; - test_runner_cleanup(runner); - wait; - end process; - - stimuli: process - variable last : std_logic; - begin - wait until start and rising_edge(clk); - done <= false; - wait until rising_edge(clk); - - m_I.load_csv(tb_path & csv_i); - - info("Sending m_I of size " & to_string(m_I.height) & "x" & to_string(m_I.width) & " to UUT..."); - - for y in 0 to m_I.height-1 loop - for x in 0 to m_I.width-1 loop - wait until rising_edge(clk); - if x = m_I.width-1 then last := '1'; else last := '0'; end if; - push_axi_stream(net, master_axi_stream, std_logic_vector(to_signed(m_I.get(x,y), data_width)) , tlast => last); - end loop; - end loop; - - info("m_I sent!"); - - wait until rising_edge(clk); - done <= true; - end process; - - save: process - variable o : std_logic_vector(31 downto 0); - variable last : std_logic:='0'; - begin - wait until start and rising_edge(clk); - saved <= false; - wait for 50*clk_period; - - m_O.init_2d(m_I.width, m_I.height, o'length, true); - - info("Receiving m_O of size " & to_string(m_O.height) & "x" & to_string(m_O.width) & " from UUT..."); - - for y in 0 to m_O.height-1 loop - for x in 0 to m_O.width-1 loop - pop_axi_stream(net, slave_axi_stream, tdata => o, tlast => last); - if (x = m_O.width-1) and (last='0') then - error("Something went wrong. Last misaligned!"); - end if; - m_O.set(x,y,to_integer(signed(o))); - end loop; - end loop; - - info("m_O read!"); - - wait until rising_edge(clk); - m_O.save_csv(tb_path & csv_o); - - info("m_O saved!"); - - wait until rising_edge(clk); - saved <= true; - end process; - --- - - vunit_axism: entity vunit_lib.axi_stream_master - generic map ( - master => master_axi_stream) - port map ( - aclk => clk, - tvalid => m_valid, - tready => m_ready, - tdata => m_data, - tlast => m_last); - - vunit_axiss: entity vunit_lib.axi_stream_slave - generic map ( - slave => slave_axi_stream) - port map ( - aclk => clk, - tvalid => s_valid, - tready => s_ready, - tdata => s_data, - tlast => s_last); - --- - - uut: entity work.axis_buffer - generic map ( - data_width => data_width, - fifo_depth => 4 - ) - port map ( - s_axis_clk => clk, - s_axis_rstn => rstn, - s_axis_rdy => m_ready, - s_axis_data => m_data, - s_axis_valid => m_valid, - s_axis_strb => "1111", - s_axis_last => m_last, - - m_axis_clk => clk, - m_axis_rstn => rstn, - m_axis_valid => s_valid, - m_axis_data => s_data, - m_axis_rdy => s_ready, - m_axis_strb => open, - m_axis_last => s_last - ); - -end architecture; diff --git a/examples/vhdl/axi_dma/run.py b/examples/vhdl/axi_dma/run.py deleted file mode 100644 index 58a964c05..000000000 --- a/examples/vhdl/axi_dma/run.py +++ /dev/null @@ -1,32 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. -# -# Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -""" -AXI DMA -------- - -Demonstrates the AXI read and write slave verification components as -well as the AXI-lite master verification component. An AXI DMA is -verified which uses an AXI master port to read and write data from -external memory. The AXI DMA also has a control register interface -via AXI-lite. -""" - -from os.path import join, dirname -from vunit import VUnit - -vu = VUnit.from_argv() -vu.add_osvvm() -vu.add_verification_components() - -src_path = join(dirname(__file__), "src") - -vu.add_library("axi_dma_lib").add_source_files([ - join(src_path, "*.vhd"), - join(src_path, "test", "*.vhd") -]) - -vu.main() diff --git a/examples/vhdl/axi_dma/src/axi_burst_gen.vhd b/examples/vhdl/axi_dma/src/axi_burst_gen.vhd deleted file mode 100644 index 0fb66057a..000000000 --- a/examples/vhdl/axi_dma/src/axi_burst_gen.vhd +++ /dev/null @@ -1,102 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - - -entity axi_burst_gen is - generic ( - max_burst_length : natural range 1 to 256; - bytes_per_beat : natural - ); - port ( - clk : in std_logic; - - -- Start pulse - start : in std_logic; - start_addr : in std_logic_vector(31 downto 0); - num_bytes : in std_logic_vector(31 downto 0); - - -- Output burst stream - burst_valid : out std_logic := '0'; - burst_ready : in std_logic; - burst_addr : out std_logic_vector(31 downto 0) := (others => '0'); - burst_length : out natural range 1 to max_burst_length := 1; - burst_last : out std_logic := '0'); -end entity; - - -architecture a of axi_burst_gen is - constant c4kbyte : natural := 4096; - - type state_t is (idle, - compute_burst_length0, - compute_burst_length1, - compute_is_last, - await_accept); - signal state : state_t := idle; - signal addr, remaining_bytes : unsigned(start_addr'range); -begin - main : process - begin - wait until rising_edge(clk); - - case state is - when idle => - if start = '1' then - addr <= unsigned(start_addr); - remaining_bytes <= unsigned(num_bytes); - state <= compute_burst_length0; - end if; - - when compute_burst_length0 => - if max_burst_length <= to_integer(remaining_bytes) / bytes_per_beat then - burst_length <= max_burst_length; - else - burst_length <= to_integer(remaining_bytes) / bytes_per_beat; - end if; - - state <= compute_burst_length1; - - when compute_burst_length1 => - if (to_integer(addr)/c4kbyte) /= (to_integer(addr) + burst_length * bytes_per_beat - 1)/c4kbyte then - burst_length <= (-(to_integer(addr)/bytes_per_beat)) mod (c4kbyte/bytes_per_beat); - end if; - - state <= compute_is_last; - - when compute_is_last => - burst_valid <= '1'; - - if remaining_bytes = burst_length * bytes_per_beat then - burst_last <= '1'; - else - burst_last <= '0'; - end if; - - state <= await_accept; - - when await_accept => - if burst_ready = '1' then - burst_valid <= '0'; - addr <= addr + burst_length * bytes_per_beat; - remaining_bytes <= remaining_bytes - burst_length * bytes_per_beat; - if burst_last = '1' then - state <= idle; - else - state <= compute_burst_length0; - end if; - end if; - - end case; - - end process; - - burst_addr <= std_logic_vector(addr); - -end; diff --git a/examples/vhdl/axi_dma/src/axi_dma.vhd b/examples/vhdl/axi_dma/src/axi_dma.vhd deleted file mode 100644 index b59959647..000000000 --- a/examples/vhdl/axi_dma/src/axi_dma.vhd +++ /dev/null @@ -1,316 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.axil_pkg.all; -use work.axi_pkg.all; -use work.util_pkg.clog2; -use work.util_pkg.is_power_of_two; - -entity axi_dma is - generic ( - max_burst_length : natural range 0 to 256 - ); - port ( - clk : in std_logic; - - -- Control register bus - axils_m2s : in axil_m2s_t; - axils_s2m : out axil_s2m_t := axil_s2m_init; - - -- Read data bus - axi_rd_m2s : out axi_rd_m2s_t := axi_rd_m2s_init; - axi_rd_s2m : in axi_rd_s2m_t; - - -- Write data bus - axi_wr_m2s : out axi_wr_m2s_t := axi_wr_m2s_init; - axi_wr_s2m : in axi_wr_s2m_t - ); - -end entity; - -architecture a of axi_dma is - constant bytes_per_beat : natural := axi_rd_s2m.r.data'length/8; - constant c4kbyte : natural := 4096; - - signal start_transfer : std_logic; - signal transfer_done : std_logic := '0'; - signal src_address : std_logic_vector(31 downto 0); - signal dst_address : std_logic_vector(31 downto 0); - signal num_bytes : std_logic_vector(31 downto 0); - - signal last_beat_written : boolean := false; - - constant max_num_burst_buffered : natural := 2; - constant max_num_beats_buffered : natural := max_num_burst_buffered * max_burst_length; - - -- The maximum difference between two counters can only be - -- max_num_beats_buffered + max_burst_length - -- Thus it is enough to compare counters MOD max_num_beats_buffered - -- We round up to nearest power of two to avoid non power of two MOD - constant max_counter_value : natural := 2**clog2(max_num_beats_buffered + max_burst_length); - - signal num_beats_read : natural range 0 to max_counter_value-1; - signal num_beats_written : natural range 0 to max_counter_value-1; - - constant max_outstanding_write_responses : natural := 7; - signal outstanding_write_responses : natural; - -begin - - ctrl_block : block - type state_t is (idle, wait_for_transfer_done); - signal state : state_t := idle; - begin - main : process - begin - wait until rising_edge(clk); - - - case state is - when idle => - if start_transfer = '1' then - transfer_done <= '0'; - state <= wait_for_transfer_done; - end if; - - when wait_for_transfer_done => - if last_beat_written and outstanding_write_responses = 0 then - transfer_done <= '1'; - state <= idle; - end if; - end case; - - end process; - end block; - - assert is_power_of_two(max_burst_length) - report "max_burst_length shall be a power of two to generate efficient logic" - severity failure; - - read_block : block - type state_t is (wait_for_burst, - wait_for_space, - wait_for_accept); - signal state : state_t := wait_for_burst; - - signal burst_valid : std_logic; - signal burst_ready : std_logic := '0'; - signal burst_length : natural range 1 to max_burst_length; - - signal num_read_beats_ordered : natural range 0 to max_counter_value-1; - begin - - axi_burst_gen_inst: entity work.axi_burst_gen - generic map ( - max_burst_length => max_burst_length, - bytes_per_beat => bytes_per_beat) - port map ( - clk => clk, - start => start_transfer, - start_addr => src_address, - num_bytes => num_bytes, - burst_valid => burst_valid, - burst_ready => burst_ready, - burst_addr => axi_rd_m2s.ar.addr, - burst_length => burst_length, - burst_last => open); - - main : process - begin - wait until rising_edge(clk); - - if start_transfer = '1' then - num_read_beats_ordered <= 0; - end if; - - case state is - when wait_for_burst => - if burst_valid = '1' then - num_read_beats_ordered <= (num_read_beats_ordered + burst_length) mod max_counter_value; - state <= wait_for_space; - end if; - - when wait_for_space => - if (num_read_beats_ordered - num_beats_written) mod max_counter_value < max_num_beats_buffered then - axi_rd_m2s.ar.valid <= '1'; - state <= wait_for_accept; - end if; - - when wait_for_accept => - if axi_rd_m2s.ar.valid = '1' and axi_rd_s2m.ar.ready = '1' then - axi_rd_m2s.ar.valid <= '0'; - state <= wait_for_burst; - end if; - end case; - end process; - - burst_ready <= axi_rd_m2s.ar.valid and axi_rd_s2m.ar.ready; - axi_rd_m2s.ar.id <= (others => '0'); - axi_rd_m2s.ar.burst <= axi_burst_incr; - axi_rd_m2s.ar.len <= std_logic_vector(to_unsigned(burst_length-1, - axi_rd_m2s.ar.len'length)); - axi_rd_m2s.ar.size <= std_logic_vector(to_unsigned(clog2(bytes_per_beat), - axi_rd_m2s.ar.size'length)); - - end block; - - data_buffer : block - type mem_t is array (natural range <>) of std_logic_vector(axi_rd_s2m.r.data'range); - signal mem : mem_t(0 to max_num_beats_buffered - 1) := (others => (others => '0')); - begin - main : process - begin - wait until rising_edge(clk); - - if start_transfer = '1' then - num_beats_read <= 0; - num_beats_written <= 0; - end if; - - if axi_rd_s2m.r.valid = '1' then - mem(num_beats_read mod max_num_beats_buffered) <= axi_rd_s2m.r.data; - num_beats_read <= (num_beats_read + 1) mod max_counter_value; - end if; - - if axi_wr_m2s.w.valid = '1' and axi_wr_s2m.w.ready = '1' then - num_beats_written <= (num_beats_written + 1) mod max_counter_value; - end if; - end process; - - axi_wr_m2s.w.data <= mem(num_beats_written mod max_num_beats_buffered); - axi_wr_m2s.w.strb <= (others => '1'); - axi_rd_m2s.r.ready <= '1'; - end block; - - write_block : block - type state_t is (wait_for_burst, - wait_for_read_data, - wait_for_accept); - signal state : state_t := wait_for_burst; - - signal burst_valid : std_logic; - signal burst_ready : std_logic := '0'; - signal burst_last : std_logic; - signal burst_length : natural range 1 to max_burst_length; - - impure function next_outstanding_write_responses return natural is - variable inc, dec : boolean; - begin - inc := axi_wr_m2s.aw.valid = '1' and axi_wr_s2m.aw.ready = '1'; - dec := axi_wr_s2m.b.valid = '1' and axi_wr_m2s.b.ready = '1'; - - if inc and dec then - return outstanding_write_responses; - elsif inc then - return outstanding_write_responses + 1; - elsif dec then - return outstanding_write_responses - 1; - else - return outstanding_write_responses; - end if; - end; - - signal num_write_beats_ordered : natural range 0 to max_counter_value-1; - signal beat_count : natural range 1 to max_burst_length; - begin - - main : process - begin - wait until rising_edge(clk); - outstanding_write_responses <= next_outstanding_write_responses; - - burst_ready <= '0'; - - if start_transfer = '1' then - num_write_beats_ordered <= max_num_beats_buffered; - outstanding_write_responses <= 0; - last_beat_written <= false; - end if; - - case state is - when wait_for_burst => - if burst_valid = '1' and burst_ready = '0' then - num_write_beats_ordered <= (num_write_beats_ordered + burst_length) mod max_counter_value; - beat_count <= burst_length; - state <= wait_for_read_data; - end if; - - when wait_for_read_data => - if (num_beats_read - num_write_beats_ordered) mod max_counter_value >= max_num_beats_buffered then - if outstanding_write_responses /= max_outstanding_write_responses then - axi_wr_m2s.aw.valid <= '1'; - axi_wr_m2s.w.valid <= '1'; - state <= wait_for_accept; - end if; - end if; - - when wait_for_accept => - if axi_wr_m2s.aw.valid = '1' and axi_wr_s2m.aw.ready = '1' then - axi_wr_m2s.aw.valid <= '0'; - end if; - - if axi_wr_m2s.w.valid = '1' and axi_wr_s2m.w.ready = '1' then - if axi_wr_m2s.w.last = '1' then - axi_wr_m2s.w.valid <= '0'; - else - beat_count <= beat_count - 1; - end if; - end if; - - if axi_wr_m2s.aw.valid = '0' and axi_wr_m2s.w.valid = '0' then - if burst_last = '1' then - last_beat_written <= true; - end if; - burst_ready <= '1'; - state <= wait_for_burst; - end if; - - end case; - end process; - - axi_wr_m2s.w.last <= '1' when beat_count = 1 else '0'; - - axi_burst_gen_inst: entity work.axi_burst_gen - generic map ( - max_burst_length => max_burst_length, - bytes_per_beat => bytes_per_beat) - port map ( - clk => clk, - start => start_transfer, - start_addr => dst_address, - num_bytes => num_bytes, - burst_valid => burst_valid, - burst_ready => burst_ready, - burst_addr => axi_wr_m2s.aw.addr, - burst_length => burst_length, - burst_last => burst_last); - - axi_wr_m2s.b.ready <= '1'; - - axi_wr_m2s.aw.id <= (others => '0'); - axi_wr_m2s.aw.burst <= axi_burst_incr; - axi_wr_m2s.aw.len <= std_logic_vector(to_unsigned(burst_length-1, - axi_wr_m2s.aw.len'length)); - axi_wr_m2s.aw.size <= std_logic_vector(to_unsigned(clog2(bytes_per_beat), - axi_wr_m2s.aw.size'length)); - - end block; - - axi_dma_regs_inst: entity work.axi_dma_regs - port map ( - clk => clk, - axils_m2s => axils_m2s, - axils_s2m => axils_s2m, - start_transfer => start_transfer, - transfer_done => transfer_done, - src_address => src_address, - dst_address => dst_address, - num_bytes => num_bytes); -end; diff --git a/examples/vhdl/axi_dma/src/axi_dma_regs.vhd b/examples/vhdl/axi_dma/src/axi_dma_regs.vhd deleted file mode 100644 index 224ba6652..000000000 --- a/examples/vhdl/axi_dma/src/axi_dma_regs.vhd +++ /dev/null @@ -1,123 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.axil_pkg.all; -use work.axi_pkg.axi_response_ok; -use work.axi_pkg.axi_response_decerr; -use work.axi_dma_regs_pkg.all; - -entity axi_dma_regs is - port ( - clk : in std_logic; - - axils_m2s : in axil_m2s_t; - axils_s2m : out axil_s2m_t := axil_s2m_init; - - start_transfer : out std_logic := '0'; - transfer_done : in std_logic; - - src_address : out std_logic_vector(31 downto 0); - dst_address : out std_logic_vector(31 downto 0); - num_bytes : out std_logic_vector(31 downto 0) -); - -end entity; - -architecture a of axi_dma_regs is - type state_t is (idle, - writing, - write_response, - reading); - signal state : state_t := idle; - - signal addr : std_logic_vector(axils_m2s.ar.addr'range); - - -- Compare addresses of 32-bit words discarding byte address - function cmp_word_address(byte_addr : std_logic_vector; - word_addr : natural) return boolean is - begin - return to_integer(unsigned(byte_addr(byte_addr'left downto 2))) = word_addr/4; - end; - -begin - - main : process - begin - wait until rising_edge(clk); - - axils_s2m.ar.ready <= '0'; - axils_s2m.aw.ready <= '0'; - axils_s2m.w.ready <= '0'; - axils_s2m.r.valid <= '0'; - axils_s2m.r.data <= (others => '0'); - - start_transfer <= '0'; - - case state is - when idle => - - if axils_m2s.ar.valid = '1' then - axils_s2m.ar.ready <= '1'; - addr <= axils_m2s.ar.addr; - state <= reading; - - elsif axils_m2s.aw.valid = '1' then - axils_s2m.aw.ready <= '1'; - addr <= axils_m2s.aw.addr; - state <= writing; - end if; - - when writing => - if axils_m2s.w.valid = '1' then - axils_s2m.w.ready <= '1'; - - axils_s2m.b.valid <= '1'; - axils_s2m.b.resp <= axi_response_ok; - - state <= write_response; - - -- Ignore byte write enable - if cmp_word_address(addr, command_reg_addr) then - start_transfer <= axils_m2s.w.data(start_transfer_command_bit); - elsif cmp_word_address(addr, src_address_reg_addr) then - src_address <= axils_m2s.w.data; - elsif cmp_word_address(addr, dst_address_reg_addr) then - dst_address <= axils_m2s.w.data; - elsif cmp_word_address(addr, num_bytes_reg_addr) then - num_bytes <= axils_m2s.w.data; - else - axils_s2m.b.resp <= axi_response_decerr; - end if; - end if; - - when write_response => - if axils_m2s.b.ready = '1' then - axils_s2m.b.valid <= '0'; - state <= idle; - end if; - - when reading => - if axils_s2m.r.valid = '0' then - axils_s2m.r.valid <= '1'; - axils_s2m.r.resp <= axi_response_ok; - - if cmp_word_address(addr, status_reg_addr) then - axils_s2m.r.data(transfer_done_status_bit) <= transfer_done; - else - axils_s2m.r.resp <= axi_response_decerr; - end if; - - elsif axils_m2s.r.ready = '1' then - state <= idle; - end if; - end case; - - end process; -end; diff --git a/examples/vhdl/axi_dma/src/axi_dma_regs_pkg.vhd b/examples/vhdl/axi_dma/src/axi_dma_regs_pkg.vhd deleted file mode 100644 index d5e44df14..000000000 --- a/examples/vhdl/axi_dma/src/axi_dma_regs_pkg.vhd +++ /dev/null @@ -1,26 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -package axi_dma_regs_pkg is - constant command_reg_addr : natural := 0; - constant status_reg_addr : natural := 4; - constant src_address_reg_addr : natural := 8; - constant dst_address_reg_addr : natural := 12; - constant num_bytes_reg_addr : natural := 16; - - constant start_transfer_command_bit : natural := 0; - constant start_transfer_command : std_logic_vector(31 downto 0) := ( - start_transfer_command_bit => '1', - others => '0'); - - constant transfer_done_status_bit : natural := 0; - constant transfer_done_status : std_logic_vector(31 downto 0) := ( - transfer_done_status_bit => '1', - others => '0'); -end package; diff --git a/examples/vhdl/axi_dma/src/axi_pkg.vhd b/examples/vhdl/axi_dma/src/axi_pkg.vhd deleted file mode 100644 index 605b0433e..000000000 --- a/examples/vhdl/axi_dma/src/axi_pkg.vhd +++ /dev/null @@ -1,116 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -package axi_pkg is - - type axi_addr_m2s_t is record - valid : std_logic; - id : std_logic_vector(1 downto 0); - addr : std_logic_vector(32-1 downto 0); - len : std_logic_vector(7 downto 0); - size : std_logic_vector(2 downto 0); - burst : std_logic_vector(1 downto 0); - end record; - constant axi_addr_m2s_init : axi_addr_m2s_t := (valid => '0', - id => (others => '0'), - addr => (others => '0'), - len => (others => '0'), - size => (others => '0'), - burst => (others => '0')); - - type axi_addr_s2m_t is record - ready : std_logic; - end record; - constant axi_addr_s2m_init : axi_addr_s2m_t := (ready => '0'); - - type axi_read_m2s_t is record - ready : std_logic; - end record; - constant axi_read_m2s_init : axi_read_m2s_t := (ready => '0'); - - type axi_read_s2m_t is record - valid : std_logic; - id : std_logic_vector(1 downto 0); - data : std_logic_vector(128-1 downto 0); - resp : std_logic_vector(1 downto 0); - last : std_logic; - end record; - constant axi_read_s2m_init : axi_read_s2m_t := (valid => '0', - id => (others => '0'), - data => (others => '0'), - resp => (others => '0'), - last => '0'); - - type axi_write_m2s_t is record - valid : std_logic; - data : std_logic_vector(128-1 downto 0); - strb : std_logic_vector(16-1 downto 0); - last : std_logic; - end record; - constant axi_write_m2s_init : axi_write_m2s_t := (valid => '0', - data => (others => '0'), - strb => (others => '0'), - last => '0'); - - type axi_write_s2m_t is record - ready : std_logic; - end record; - constant axi_write_s2m_init : axi_write_s2m_t := (ready => '0'); - - type axi_wresp_m2s_t is record - ready : std_logic; - end record; - constant axi_wresp_m2s_init : axi_wresp_m2s_t := (ready => '0'); - - type axi_wresp_s2m_t is record - valid : std_logic; - id : std_logic_vector(1 downto 0); - resp : std_logic_vector(1 downto 0); - end record; - constant axi_wresp_s2m_init : axi_wresp_s2m_t := (valid => '0', - id => (others => '0'), - resp => (others => '0')); - - type axi_rd_m2s_t is record - ar : axi_addr_m2s_t; - r : axi_read_m2s_t; - end record; - constant axi_rd_m2s_init : axi_rd_m2s_t := (ar => axi_addr_m2s_init, - r => axi_read_m2s_init); - - type axi_rd_s2m_t is record - ar : axi_addr_s2m_t; - r : axi_read_s2m_t; - end record; - constant axi_rd_s2m_init : axi_rd_s2m_t := (ar => axi_addr_s2m_init, - r => axi_read_s2m_init); - - type axi_wr_m2s_t is record - aw : axi_addr_m2s_t; - w : axi_write_m2s_t; - b : axi_wresp_m2s_t; - end record; - constant axi_wr_m2s_init : axi_wr_m2s_t := (aw => axi_addr_m2s_init, - w => axi_write_m2s_init, - b => axi_wresp_m2s_init); - - type axi_wr_s2m_t is record - aw : axi_addr_s2m_t; - w : axi_write_s2m_t; - b : axi_wresp_s2m_t; - end record; - constant axi_wr_s2m_init : axi_wr_s2m_t := (aw => axi_addr_s2m_init, - w => axi_write_s2m_init, - b => axi_wresp_s2m_init); - - constant axi_response_ok : std_logic_vector(1 downto 0) := "00"; - constant axi_response_decerr : std_logic_vector(1 downto 0) := "11"; - constant axi_burst_incr : std_logic_vector(1 downto 0) := "01"; - -end package; diff --git a/examples/vhdl/axi_dma/src/axil_pkg.vhd b/examples/vhdl/axi_dma/src/axil_pkg.vhd deleted file mode 100644 index 66ffee27d..000000000 --- a/examples/vhdl/axi_dma/src/axil_pkg.vhd +++ /dev/null @@ -1,91 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - --- Defines AXI4-lite data bus types - -library ieee; -use ieee.std_logic_1164.all; - -package axil_pkg is - - type axil_addr_m2s_t is record - valid : std_logic; - addr : std_logic_vector(32-1 downto 0); - end record; - constant axil_addr_m2s_init : axil_addr_m2s_t := (valid => '0', - addr => (others => '0')); - - type axil_addr_s2m_t is record - ready : std_logic; - end record; - constant axil_addr_s2m_init : axil_addr_s2m_t := (ready => '0'); - - type axil_read_m2s_t is record - ready : std_logic; - end record; - constant axil_read_m2s_init : axil_read_m2s_t := (ready => '0'); - - type axil_read_s2m_t is record - valid : std_logic; - data : std_logic_vector(32-1 downto 0); - resp : std_logic_vector(1 downto 0); - end record; - constant axil_read_s2m_init : axil_read_s2m_t := (valid => '0', - data => (others => '0'), - resp => (others => '0')); - - type axil_write_m2s_t is record - valid : std_logic; - data : std_logic_vector(32-1 downto 0); - strb : std_logic_vector(4-1 downto 0); - end record; - constant axil_write_m2s_init : axil_write_m2s_t := (valid => '0', - data => (others => '0'), - strb => (others => '0')); - - type axil_write_s2m_t is record - ready : std_logic; - end record; - constant axil_write_s2m_init : axil_write_s2m_t := (ready => '0'); - - type axil_wresp_m2s_t is record - ready : std_logic; - end record; - constant axil_wresp_m2s_init : axil_wresp_m2s_t := (ready => '0'); - - type axil_wresp_s2m_t is record - valid : std_logic; - resp : std_logic_vector(1 downto 0); - end record; - constant axil_wresp_s2m_init : axil_wresp_s2m_t := (valid => '0', - resp => (others => '0')); - - type axil_m2s_t is record - ar : axil_addr_m2s_t; - aw : axil_addr_m2s_t; - r : axil_read_m2s_t; - w : axil_write_m2s_t; - b : axil_wresp_m2s_t; - end record; - constant axil_m2s_init : axil_m2s_t := (ar => axil_addr_m2s_init, - aw => axil_addr_m2s_init, - r => axil_read_m2s_init, - w => axil_write_m2s_init, - b => axil_wresp_m2s_init); - - type axil_s2m_t is record - ar : axil_addr_s2m_t; - aw : axil_addr_s2m_t; - r : axil_read_s2m_t; - w : axil_write_s2m_t; - b : axil_wresp_s2m_t; - end record; - constant axil_s2m_init : axil_s2m_t := (ar => axil_addr_s2m_init, - aw => axil_addr_s2m_init, - r => axil_read_s2m_init, - w => axil_write_s2m_init, - b => axil_wresp_s2m_init); -end package; diff --git a/examples/vhdl/axi_dma/src/test/tb_axi_dma.vhd b/examples/vhdl/axi_dma/src/test/tb_axi_dma.vhd deleted file mode 100644 index 83883dca3..000000000 --- a/examples/vhdl/axi_dma/src/test/tb_axi_dma.vhd +++ /dev/null @@ -1,337 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.vc_context; - -library osvvm; -use osvvm.RandomPkg.all; - -use work.axil_pkg.all; -use work.axi_pkg.all; -use work.axi_dma_regs_pkg.all; - -entity tb_axi_dma is - generic (runner_cfg : string); -end entity; - -architecture tb of tb_axi_dma is - constant clk_period : time := 1 ns; - - constant axil_bus : bus_master_t := new_bus(data_length => 32, - address_length => 32, - logger => get_logger("axil_bus")); - - constant memory : memory_t := new_memory; - constant axi_rd_slave : axi_slave_t := new_axi_slave(memory => memory, - logger => get_logger("axi_rd_slave")); - - constant axi_wr_slave : axi_slave_t := new_axi_slave(memory => memory, - logger => get_logger("axi_wr_slave")); - - signal clk : std_logic := '0'; - signal axil_m2s : axil_m2s_t := axil_m2s_init; - signal axil_s2m : axil_s2m_t; - - signal axi_rd_m2s : axi_rd_m2s_t; - signal axi_rd_s2m : axi_rd_s2m_t := axi_rd_s2m_init; - - signal axi_wr_m2s : axi_wr_m2s_t; - signal axi_wr_s2m : axi_wr_s2m_t := axi_wr_s2m_init; - - constant max_burst_length : natural := 256; - constant bytes_per_beat : natural := axi_rd_s2m.r.data'length / 8; - - impure function to_reg_data(value : natural) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(value, data_length(axil_bus))); - end; -begin - - main : process - variable rnd : RandomPType; - - procedure perform_transfer(rbuffer, wbuffer : buffer_t; - reg_sample_period : delay_length := 100 * clk_period) is - variable rdata : std_logic_vector(axil_s2m.r.data'range); - variable byte : natural; - begin - info("perform_transfer(num_bytes => " & to_string(num_bytes(rbuffer)) & ")"); - assert num_bytes(rbuffer) = num_bytes(wbuffer) report "buffer size must be equal"; - - -- Provide random stimuli to read data buffer - -- Set expected data on write data buffer - for i in 0 to num_bytes(rbuffer)-1 loop - byte := rnd.RandInt(0, 255); - write_byte(memory, base_address(rbuffer) + i, byte); - set_expected_byte(memory, base_address(wbuffer) + i, byte); - end loop; - - write_bus(net, axil_bus, src_address_reg_addr, to_reg_data(base_address(rbuffer))); - write_bus(net, axil_bus, dst_address_reg_addr, to_reg_data(base_address(wbuffer))); - write_bus(net, axil_bus, num_bytes_reg_addr, to_reg_data(num_bytes(rbuffer))); - write_bus(net, axil_bus, command_reg_addr, start_transfer_command); - - loop - read_bus(net, axil_bus, status_reg_addr, rdata); - exit when rdata(transfer_done_status_bit) = '1'; - wait for reg_sample_period; - end loop; - - -- This checks that all data has been correctly written to the write - -- buffer at this point - check_expected_was_written(wbuffer); - end; - - procedure perform_transfer(num_bytes : natural; - reg_sample_period : delay_length := 100 * clk_period) is - variable rbuffer, wbuffer : buffer_t; - begin - rbuffer := allocate(memory, - num_bytes => num_bytes, - name => rbuffer'simple_name, - permissions => read_only, - alignment => 4096); - wbuffer := allocate(memory, - num_bytes => num_bytes, - name => wbuffer'simple_name, - permissions => write_only, - alignment => 4096); - perform_transfer(rbuffer, wbuffer, reg_sample_period); - end; - - variable stat : axi_statistics_t; - variable unnused_buffer, rbuffer, wbuffer : buffer_t; - begin - test_runner_setup(runner, runner_cfg); - rnd.InitSeed(rnd'instance_name); - show(display_handler, debug); - - if run("Perform simple transfers") then - -- Perform transfer that are a multiple of the max_burst_length and - -- do not cross 4k boundaries - perform_transfer(num_bytes => max_burst_length * bytes_per_beat); - perform_transfer(num_bytes => 10 * max_burst_length * bytes_per_beat); - - elsif run("Perform split transfers") then - -- Perform transfers where the max_burst_length cannot be used for the - -- entire transfer - perform_transfer(num_bytes => bytes_per_beat); - get_statistics(net, axi_rd_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, 1), 1); - check_equal(num_bursts(stat), 1); - get_statistics(net, axi_wr_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, 1), 1); - check_equal(num_bursts(stat), 1); - - clear(memory); - perform_transfer(num_bytes => (max_burst_length - 1) * bytes_per_beat); - get_statistics(net, axi_rd_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, max_burst_length - 1), 1); - check_equal(num_bursts(stat), 1); - get_statistics(net, axi_wr_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, max_burst_length - 1), 1); - check_equal(num_bursts(stat), 1); - - clear(memory); - perform_transfer(num_bytes => (max_burst_length + 1) * bytes_per_beat); - get_statistics(net, axi_rd_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, max_burst_length), 1); - check_equal(get_num_burst_with_length(stat, 1), 1); - check_equal(num_bursts(stat), 2); - get_statistics(net, axi_wr_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, max_burst_length), 1); - check_equal(get_num_burst_with_length(stat, 1), 1); - check_equal(num_bursts(stat), 2); - - clear(memory); - perform_transfer(num_bytes => (2*max_burst_length - 1) * bytes_per_beat); - get_statistics(net, axi_rd_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, max_burst_length), 1); - check_equal(get_num_burst_with_length(stat, max_burst_length - 1), 1); - check_equal(num_bursts(stat), 2); - get_statistics(net, axi_wr_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, max_burst_length), 1); - check_equal(get_num_burst_with_length(stat, max_burst_length - 1), 1); - check_equal(num_bursts(stat), 2); - - elsif run("Check transfer done comes after write response") then - -- Set a very large response latency to ensure that the - -- dut does not signal transfer_done until the write reponse has been received - set_response_latency(net, axi_wr_slave, 100 * clk_period); - perform_transfer(num_bytes => max_burst_length * bytes_per_beat, - reg_sample_period => 10 * clk_period); - - elsif run("Check read burst is split on 4KByte boundary") then - for i in 1 to 5 loop - clear(memory); - unnused_buffer := allocate(memory, num_bytes => 4096 - i * bytes_per_beat); - rbuffer := allocate(memory, - num_bytes => 1024, - name => rbuffer'simple_name, - permissions => read_only); - info("base_address(rbuffer) = " & to_string(base_address(rbuffer))); - check_equal(base_address(rbuffer), 4096 - i * bytes_per_beat); - wbuffer := allocate(memory, - num_bytes => 1024, - name => wbuffer'simple_name, - permissions => write_only, - alignment => 4096); - perform_transfer(rbuffer, wbuffer); - end loop; - - elsif run("Check write burst is split on 4KByte boundary") then - for i in 1 to 5 loop - clear(memory); - unnused_buffer := allocate(memory, num_bytes => 4096 - i * bytes_per_beat); - wbuffer := allocate(memory, - num_bytes => 1024, - name => wbuffer'simple_name, - permissions => write_only); - info("base_address(wbuffer) = " & to_string(base_address(wbuffer))); - check_equal(base_address(wbuffer), 4096 - i * bytes_per_beat); - rbuffer := allocate(memory, - num_bytes => 1024, - name => rbuffer'simple_name, - permissions => read_only, - alignment => 4096); - perform_transfer(rbuffer, wbuffer); - end loop; - - - elsif run("Slow data read") then - set_address_fifo_depth(net, axi_rd_slave, 16); - set_address_stall_probability(net, axi_rd_slave, 0.99); - set_data_stall_probability(net, axi_rd_slave, 0.95); - for i in 0 to 15 loop - perform_transfer(num_bytes => rnd.RandInt(1, 3 * max_burst_length) * bytes_per_beat); - end loop; - - elsif run("Slow data write") then - set_address_fifo_depth(net, axi_wr_slave, 16); - set_address_stall_probability(net, axi_wr_slave, 0.99); - set_data_stall_probability(net, axi_wr_slave, 0.95); - for i in 0 to 15 loop - perform_transfer(num_bytes => rnd.RandInt(1, 3 * max_burst_length) * bytes_per_beat); - end loop; - - elsif run("Random AXI configuration") then - for idx in 0 to 15 loop - set_address_fifo_depth(net, axi_wr_slave, rnd.RandInt(1, 16)); - set_address_stall_probability(net, axi_wr_slave, rnd.Uniform(0.0, 0.99)); - set_data_stall_probability(net, axi_wr_slave, rnd.Uniform(0.0, 0.95)); - set_write_response_fifo_depth(net, axi_wr_slave, rnd.RandInt(1, 16)); - set_write_response_stall_probability(net, axi_wr_slave, rnd.Uniform(0.0, 0.99)); - set_response_latency(net, axi_wr_slave, rnd.Uniform(1.0, 100.0) * 1 ns); - - set_address_fifo_depth(net, axi_rd_slave, rnd.RandInt(1, 16)); - set_address_stall_probability(net, axi_rd_slave, rnd.Uniform(0.0, 0.99)); - set_data_stall_probability(net, axi_rd_slave, rnd.Uniform(0.0, 0.95)); - set_response_latency(net, axi_rd_slave, rnd.Uniform(1.0, 100.0) * 1 ns); - for i in 0 to 3 loop - clear(memory); - perform_transfer(num_bytes => rnd.RandInt(1, 3 * max_burst_length) * bytes_per_beat); - end loop; - end loop; - end if; - - test_runner_cleanup(runner); - end process; - - test_runner_watchdog(runner, 10 ms); - - - dut: entity work.axi_dma - generic map ( - max_burst_length => max_burst_length - ) - port map ( - clk => clk, - - axils_m2s => axil_m2s, - axils_s2m => axil_s2m, - - axi_rd_m2s => axi_rd_m2s, - axi_rd_s2m => axi_rd_s2m, - - axi_wr_m2s => axi_wr_m2s, - axi_wr_s2m => axi_wr_s2m); - - clk <= not clk after clk_period/2; - - axi_lite_master_inst: entity vunit_lib.axi_lite_master - generic map ( - bus_handle => axil_bus) - port map ( - aclk => clk, - arready => axil_s2m.ar.ready, - arvalid => axil_m2s.ar.valid, - araddr => axil_m2s.ar.addr, - rready => axil_m2s.r.ready, - rvalid => axil_s2m.r.valid, - rdata => axil_s2m.r.data, - rresp => axil_s2m.r.resp, - awready => axil_s2m.aw.ready, - awvalid => axil_m2s.aw.valid, - awaddr => axil_m2s.aw.addr, - wready => axil_s2m.w.ready, - wvalid => axil_m2s.w.valid, - wdata => axil_m2s.w.data, - wstrb => axil_m2s.w.strb, - bvalid => axil_s2m.b.valid, - bready => axil_m2s.b.ready, - bresp => axil_s2m.b.resp); - - axi_read_slave_inst: entity vunit_lib.axi_read_slave - generic map ( - axi_slave => axi_rd_slave) - port map ( - aclk => clk, - arvalid => axi_rd_m2s.ar.valid, - arready => axi_rd_s2m.ar.ready, - arid => axi_rd_m2s.ar.id, - araddr => axi_rd_m2s.ar.addr, - arlen => axi_rd_m2s.ar.len, - arsize => axi_rd_m2s.ar.size, - arburst => axi_rd_m2s.ar.burst, - rvalid => axi_rd_s2m.r.valid, - rready => axi_rd_m2s.r.ready, - rid => axi_rd_s2m.r.id, - rdata => axi_rd_s2m.r.data, - rresp => axi_rd_s2m.r.resp, - rlast => axi_rd_s2m.r.last); - - axi_write_slave_inst: entity vunit_lib.axi_write_slave - generic map ( - axi_slave => axi_wr_slave) - port map ( - aclk => clk, - awvalid => axi_wr_m2s.aw.valid, - awready => axi_wr_s2m.aw.ready, - awid => axi_wr_m2s.aw.id, - awaddr => axi_wr_m2s.aw.addr, - awlen => axi_wr_m2s.aw.len, - awsize => axi_wr_m2s.aw.size, - awburst => axi_wr_m2s.aw.burst, - - wvalid => axi_wr_m2s.w.valid, - wready => axi_wr_s2m.w.ready, - wdata => axi_wr_m2s.w.data, - wstrb => axi_wr_m2s.w.strb, - wlast => axi_wr_m2s.w.last, - - bvalid => axi_wr_s2m.b.valid, - bready => axi_wr_m2s.b.ready, - bid => axi_wr_s2m.b.id, - bresp => axi_wr_s2m.b.resp); - - -end architecture; diff --git a/examples/vhdl/axi_dma/src/test/tb_axi_dma_regs.vhd b/examples/vhdl/axi_dma/src/test/tb_axi_dma_regs.vhd deleted file mode 100644 index 66621fc00..000000000 --- a/examples/vhdl/axi_dma/src/test/tb_axi_dma_regs.vhd +++ /dev/null @@ -1,170 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.vc_context; -use vunit_lib.signal_checker_pkg.all; - -use work.axil_pkg.all; -use work.axi_dma_regs_pkg.all; - -library osvvm; -use osvvm.RandomPkg.all; - -entity tb_axi_dma_regs is - generic (runner_cfg : string); -end entity; - -architecture tb of tb_axi_dma_regs is - constant axil_bus : bus_master_t := new_bus(data_length => 32, address_length => 32); - - constant clk_period : time := 1 ns; - - signal clk : std_logic := '1'; - signal axil_m2s : axil_m2s_t := axil_m2s_init; - signal axil_s2m : axil_s2m_t; - - signal start_transfer : std_logic; - signal transfer_done : std_logic := '0'; - signal src_address : std_logic_vector(31 downto 0); - signal dst_address : std_logic_vector(31 downto 0); - signal num_bytes : std_logic_vector(31 downto 0); - - constant src_address_checker : signal_checker_t := new_signal_checker( - logger => get_logger("src_address_checker")); - - constant dst_address_checker : signal_checker_t := new_signal_checker( - logger => get_logger("dst_address_checker")); - - constant num_bytes_checker : signal_checker_t := new_signal_checker( - logger => get_logger("num_bytes_checker")); - - constant start_transfer_checker : signal_checker_t := new_signal_checker( - logger => get_logger("start_transfer_checker")); - -begin - - main : process - variable rnd : RandomPType; - variable nbytes, src_addr, dst_addr, rdata : std_logic_vector(axil_s2m.r.data'range); - begin - test_runner_setup(runner, runner_cfg); - rnd.InitSeed(rnd'instance_name); - - if run("Test source address") then - src_addr := rnd.RandSlv(src_addr'length); - expect(net, src_address_checker, src_addr, now + 3 * clk_period); - write_bus(net, axil_bus, src_address_reg_addr, src_addr); - wait_until_idle(net, axil_bus); - wait_until_idle(net, src_address_checker); - - elsif run("Test destination address") then - dst_addr := rnd.RandSlv(dst_addr'length); - expect(net, dst_address_checker, dst_addr, now + 3 * clk_period); - write_bus(net, axil_bus, dst_address_reg_addr, dst_addr); - wait_until_idle(net, axil_bus); - wait_until_idle(net, dst_address_checker); - - elsif run("Test num bytes") then - nbytes := rnd.RandSlv(nbytes'length); - expect(net, num_bytes_checker, nbytes, now + 3 * clk_period); - write_bus(net, axil_bus, num_bytes_reg_addr, nbytes); - wait_until_idle(net, axil_bus); - wait_until_idle(net, num_bytes_checker); - - elsif run("Test start transfer command") then - expect(net, start_transfer_checker, "1", now + 3 * clk_period); - expect(net, start_transfer_checker, "0", now + 4 * clk_period); - write_bus(net, axil_bus, command_reg_addr, start_transfer_command); - wait_until_idle(net, axil_bus); - wait_until_idle(net, start_transfer_checker); - - elsif run("Test status register") then - check_bus(net, axil_bus, status_reg_addr, (transfer_done_status'range => '0'), - msg => "Transfer done low initially"); - transfer_done <= '1'; - wait for 0 ns; - check_bus(net, axil_bus, status_reg_addr, transfer_done_status, - msg => "Transfer done high when set"); - transfer_done <= '0'; - wait for 0 ns; - check_bus(net, axil_bus, status_reg_addr, (transfer_done_status'range => '0'), - msg => "Transfer done low when cleared"); - end if; - - -- Avoid unexpected change of data after test - wait for 100 * clk_period; - - test_runner_cleanup(runner); - end process; - - test_runner_watchdog(runner, 1 ms); - - dut: entity work.axi_dma_regs - port map ( - clk => clk, - axils_m2s => axil_m2s, - axils_s2m => axil_s2m, - start_transfer => start_transfer, - transfer_done => transfer_done, - src_address => src_address, - dst_address => dst_address, - num_bytes => num_bytes); - - clk <= not clk after clk_period / 2; - - axi_lite_master_inst: entity vunit_lib.axi_lite_master - generic map ( - bus_handle => axil_bus) - port map ( - aclk => clk, - arready => axil_s2m.ar.ready, - arvalid => axil_m2s.ar.valid, - araddr => axil_m2s.ar.addr, - rready => axil_m2s.r.ready, - rvalid => axil_s2m.r.valid, - rdata => axil_s2m.r.data, - rresp => axil_s2m.r.resp, - awready => axil_s2m.aw.ready, - awvalid => axil_m2s.aw.valid, - awaddr => axil_m2s.aw.addr, - wready => axil_s2m.w.ready, - wvalid => axil_m2s.w.valid, - wdata => axil_m2s.w.data, - wstrb => axil_m2s.w.strb, - bvalid => axil_s2m.b.valid, - bready => axil_m2s.b.ready, - bresp => axil_s2m.b.resp); - - src_address_checker_inst: entity vunit_lib.std_logic_checker - generic map ( - signal_checker => src_address_checker) - port map ( - value => src_address); - - dst_address_checker_inst: entity vunit_lib.std_logic_checker - generic map ( - signal_checker => dst_address_checker) - port map ( - value => dst_address); - - num_bytes_checker_inst: entity vunit_lib.std_logic_checker - generic map ( - signal_checker => num_bytes_checker) - port map ( - value => num_bytes); - - start_transfer_checker_inst: entity vunit_lib.std_logic_checker - generic map ( - signal_checker => start_transfer_checker) - port map ( - value(0) => start_transfer); - -end architecture; diff --git a/examples/vhdl/axi_dma/src/test/tb_util_pkg.vhd b/examples/vhdl/axi_dma/src/test/tb_util_pkg.vhd deleted file mode 100644 index c6f564cd5..000000000 --- a/examples/vhdl/axi_dma/src/test/tb_util_pkg.vhd +++ /dev/null @@ -1,49 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - --- vunit: run_all_in_same_sim - -library vunit_lib; -context vunit_lib.vunit_context; - -use work.util_pkg.all; - -entity tb_util_pkg is - generic (runner_cfg : string); -end entity; - -architecture tb of tb_util_pkg is -begin - main : process - begin - test_runner_setup(runner, runner_cfg); - show(display_handler, pass); - while test_suite loop - if run("test clog2") then - check_equal(clog2(1), 0); - check_equal(clog2(2), 1); - check_equal(clog2(3), 2); - check_equal(clog2(4), 2); - check_equal(clog2(5), 3); - check_equal(clog2(8), 3); - check_equal(clog2(127), 7); - check_equal(clog2(128), 7); - check_equal(clog2(129), 8); - check_equal(clog2(2**30), 30); - elsif run("test is_power_of_two") then - check(is_power_of_two(1)); - check(is_power_of_two(2)); - check(is_power_of_two(4)); - check(is_power_of_two(2**30)); - check_false(is_power_of_two(3)); - check_false(is_power_of_two(2**30-1)); - check_false(is_power_of_two(2**30+1)); - check_false(is_power_of_two(integer'high)); - end if; - end loop; - test_runner_cleanup(runner); - end process; -end; diff --git a/examples/vhdl/axi_dma/src/util_pkg.vhd b/examples/vhdl/axi_dma/src/util_pkg.vhd deleted file mode 100644 index b4f1fe66a..000000000 --- a/examples/vhdl/axi_dma/src/util_pkg.vhd +++ /dev/null @@ -1,33 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.math_real.all; - -package util_pkg is - -- ceiling of 2:s logarithm of value - function clog2(value : natural) return natural; - - -- return true if value is an exact power of two - function is_power_of_two(value : natural) return boolean; -end package; - -package body util_pkg is - function clog2(value : natural) return natural is - begin - return integer(ceil(log2(real(value)))); - end; - - function log2(value : natural) return natural is - begin - return integer(trunc(log2(real(value)))); - end; - - function is_power_of_two(value : natural) return boolean is - begin - return clog2(value) = log2(value); - end; -end package body; diff --git a/examples/vhdl/uart/run.py b/examples/vhdl/uart/run.py deleted file mode 100644 index 4fff1a480..000000000 --- a/examples/vhdl/uart/run.py +++ /dev/null @@ -1,27 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. -# -# Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -""" -VHDL UART ---------- - -A more realistic test bench of an UART to show VUnit VHDL usage on a -typical module. -""" - -from os.path import join, dirname -from vunit import VUnit - -vu = VUnit.from_argv() -vu.add_osvvm() -vu.add_verification_components() - -src_path = join(dirname(__file__), "src") - -vu.add_library("uart_lib").add_source_files(join(src_path, "*.vhd")) -vu.add_library("tb_uart_lib").add_source_files(join(src_path, "test", "*.vhd")) - -vu.main() diff --git a/examples/vhdl/uart/src/test/tb_uart_rx.vhd b/examples/vhdl/uart/src/test/tb_uart_rx.vhd deleted file mode 100644 index 5044860b6..000000000 --- a/examples/vhdl/uart/src/test/tb_uart_rx.vhd +++ /dev/null @@ -1,114 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.vc_context; - -library uart_lib; - -entity tb_uart_rx is - generic ( - runner_cfg : string); -end entity; - -architecture tb of tb_uart_rx is - constant baud_rate : integer := 115200; -- bits / s - constant clk_period : integer := 20; -- ns - constant cycles_per_bit : integer := 50 * 10**6 / baud_rate; - - signal clk : std_logic := '0'; - signal rx : std_logic := '1'; - signal overflow : std_logic; - signal tready : std_logic; - signal tvalid : std_Logic; - signal tdata : std_logic_vector(7 downto 0); - - signal num_overflows : integer := 0; - - constant uart_bfm : uart_master_t := new_uart_master(initial_baud_rate => baud_rate); - constant uart_stream : stream_master_t := as_stream(uart_bfm); - - constant axi_stream_bfm : axi_stream_slave_t := new_axi_stream_slave(data_length => tdata'length); - constant axi_stream : stream_slave_t := as_stream(axi_stream_bfm); -begin - - main : process - begin - test_runner_setup(runner, runner_cfg); - - while test_suite loop - reset_checker_stat; - if run("test_tvalid_low_at_start") then - wait until tvalid = '1' for 1 ms; - check_equal(tvalid, '0'); - - elsif run("test_receives_one_byte") then - push_stream(net, uart_stream, x"77"); - check_stream(net, axi_stream, x"77",true); - wait until rising_edge(clk); - check_equal(tvalid, '0'); - check_equal(num_overflows, 0); - - elsif run("test_two_bytes_casues_overflow") then - push_stream(net, uart_stream, x"77"); - wait until tvalid = '1' and rising_edge(clk); - check_equal(num_overflows, 0); - wait for 1 ms; - push_stream(net, uart_stream, x"77"); - wait for 1 ms; - wait until num_overflows = 1 and rising_edge(clk); - end if; - end loop; - - test_runner_cleanup(runner); - wait; - end process; - test_runner_watchdog(runner, 10 ms); - - overflow_counter : process (clk) - begin - if rising_edge(clk) then - if overflow = '1' then - warning("Overflow"); - num_overflows <= num_overflows + 1; - end if; - end if; - end process; - - clk <= not clk after (clk_period/2) * 1 ns; - - dut : entity uart_lib.uart_rx - generic map ( - cycles_per_bit => cycles_per_bit) - port map ( - clk => clk, - rx => rx, - overflow => overflow, - tready => tready, - tvalid => tvalid, - tdata => tdata); - - uart_master_bfm : entity vunit_lib.uart_master - generic map ( - uart => uart_bfm) - port map ( - tx => rx); - - axi_stream_slave_bfm: entity vunit_lib.axi_stream_slave - generic map ( - slave => axi_stream_bfm) - port map ( - aclk => clk, - tvalid => tvalid, - tready => tready, - tdata => tdata); - -end architecture; diff --git a/examples/vhdl/uart/src/test/tb_uart_tx.vhd b/examples/vhdl/uart/src/test/tb_uart_tx.vhd deleted file mode 100644 index 14a218bdf..000000000 --- a/examples/vhdl/uart/src/test/tb_uart_tx.vhd +++ /dev/null @@ -1,104 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.vc_context; - -library osvvm; -use osvvm.RandomPkg.all; - -library uart_lib; - -entity tb_uart_tx is - generic ( - runner_cfg : string); -end entity; - -architecture tb of tb_uart_tx is - constant baud_rate : integer := 115200; -- bits / s - constant clk_period : integer := 20; -- ns - constant cycles_per_bit : integer := 50 * 10**6 / baud_rate; - - signal clk : std_logic := '0'; - signal tx : std_logic; - signal tready : std_logic; - signal tvalid : std_Logic; - signal tdata : std_logic_vector(7 downto 0); - - shared variable rnd_stimuli, rnd_expected : RandomPType; - constant uart_bfm : uart_slave_t := new_uart_slave(initial_baud_rate => baud_rate, - data_length => tdata'length); - constant uart_stream : stream_slave_t := as_stream(uart_bfm); - - constant axi_stream_bfm : axi_stream_master_t := new_axi_stream_master(data_length => tdata'length); - constant axi_stream : stream_master_t := as_stream(axi_stream_bfm); - -begin - - main : process - begin - test_runner_setup(runner, runner_cfg); - - -- Initialize to same seed to get same sequence - rnd_stimuli.InitSeed(rnd_stimuli'instance_name); - rnd_expected.InitSeed(rnd_stimuli'instance_name); - - while test_suite loop - if run("test_send_one_byte") then - push_stream(net, axi_stream, rnd_stimuli.RandSlv(tdata'length)); - check_stream(net, uart_stream, rnd_expected.RandSlv(tdata'length)); - elsif run("test_send_two_bytes") then - push_stream(net, axi_stream, rnd_stimuli.RandSlv(tdata'length)); - check_stream(net, uart_stream, rnd_expected.RandSlv(tdata'length)); - push_stream(net, axi_stream, rnd_stimuli.RandSlv(tdata'length)); - check_stream(net, uart_stream, rnd_expected.RandSlv(tdata'length)); - elsif run("test_send_many_bytes") then - for i in 0 to 7 loop - push_stream(net, axi_stream, rnd_stimuli.RandSlv(tdata'length)); - end loop; - for i in 0 to 7 loop - check_stream(net, uart_stream, rnd_expected.RandSlv(tdata'length)); - end loop; - end if; - end loop; - - test_runner_cleanup(runner); - wait; - end process; - test_runner_watchdog(runner, 10 ms); - - clk <= not clk after (clk_period/2) * 1 ns; - - dut : entity uart_lib.uart_tx - generic map ( - cycles_per_bit => cycles_per_bit) - port map ( - clk => clk, - tx => tx, - tready => tready, - tvalid => tvalid, - tdata => tdata); - - uart_slave_bfm : entity vunit_lib.uart_slave - generic map ( - uart => uart_bfm) - port map ( - rx => tx); - - axi_stream_master_bfm: entity vunit_lib.axi_stream_master - generic map ( - master => axi_stream_bfm) - port map ( - aclk => clk, - tvalid => tvalid, - tready => tready, - tdata => tdata); -end architecture; diff --git a/examples/vhdl/uart/src/uart_rx.vhd b/examples/vhdl/uart/src/uart_rx.vhd deleted file mode 100644 index 5884a4bd5..000000000 --- a/examples/vhdl/uart/src/uart_rx.vhd +++ /dev/null @@ -1,105 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; --- pragma translate_off -library vunit_lib; -use vunit_lib.check_pkg.all; -use vunit_lib.logger_pkg.all; --- pragma translate_on - -entity uart_rx is - generic ( - cycles_per_bit : natural := 434); - port ( - clk : in std_logic; - - -- Serial input bit - rx : in std_logic; - - overflow : out std_logic := '0'; - - -- AXI stream for output bytes - tready : in std_logic; - tvalid : out std_Logic := '0'; - tdata : out std_logic_vector(7 downto 0)); -begin - -- pragma translate_off - check_stable(clk, check_enabled, tvalid, tready, tdata, "tdata must be stable until tready is active"); - check_stable(clk, check_enabled, tvalid, tready, tvalid, "tvalid must be active until tready is active"); - check_not_unknown(clk, check_enabled, tvalid, "tvalid must never be unknown"); - check_not_unknown(clk, check_enabled, tready, "tready must never be unknown"); - check_not_unknown(clk, check_enabled, rx, "rx must never be unknown"); - traffic_logger: process (clk) is - begin - if tvalid = '1' and tready = '1' and rising_edge(clk) then - debug("Received " & to_string(to_integer(unsigned(tdata)))); - end if; - end process traffic_logger; - -- pragma translate_on -end entity; - -architecture a of uart_rx is - signal tvalid_int : std_logic := '0'; -begin - main : process (clk) - type state_t is (idle, receiving, done); - variable state : state_t := idle; - variable cycles : natural range 0 to cycles_per_bit-1 := 0; - variable data : std_logic_vector(7 downto 0); - variable index : natural range 0 to data'length-1 := 0; - begin - if rising_edge(clk) then - overflow <= '0'; - - case state is - when idle => - if rx = '0' then - if cycles = cycles_per_bit/2 - 1 then - state := receiving; - cycles := 0; - index := 0; - else - cycles := cycles + 1; - end if; - else - cycles := 0; - end if; - - when receiving => - if cycles = cycles_per_bit - 1 then - data := rx & data(data'length-1 downto 1); - cycles := 0; - - if index = data'length - 1 then - state := done; - else - index := index + 1; - end if; - else - cycles := cycles + 1; - end if; - - when done => - -- New output overwrites old output - overflow <= tvalid_int and not tready; - tvalid_int <= '1'; - tdata <= data; - state := idle; - end case; - - -- output was read - if tvalid_int = '1' and tready = '1' then - tvalid_int <= '0'; - end if; - - end if; - end process; - - tvalid <= tvalid_int; -end architecture; diff --git a/examples/vhdl/uart/src/uart_tx.vhd b/examples/vhdl/uart/src/uart_tx.vhd deleted file mode 100644 index 5678edc30..000000000 --- a/examples/vhdl/uart/src/uart_tx.vhd +++ /dev/null @@ -1,90 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; --- pragma translate_off -library vunit_lib; -use vunit_lib.check_pkg.all; -use vunit_lib.logger_pkg.all; --- pragma translate_on - -entity uart_tx is - generic ( - cycles_per_bit : natural := 434); - port ( - clk : in std_logic; - - -- Serial output bit - tx : out std_logic := '1'; - - -- AXI stream for input bytes - tready : out std_logic := '0'; - tvalid : in std_Logic; - tdata : in std_logic_vector(7 downto 0)); -begin - -- pragma translate_off - check_stable(clk, check_enabled, tvalid, tready, tdata, "tdata must be stable until tready is active"); - check_stable(clk, check_enabled, tvalid, tready, tvalid, "tvalid must be active until tready is active"); - check_not_unknown(clk, check_enabled, tvalid, "tvalid must never be unknown"); - check_not_unknown(clk, check_enabled, tready, "tready must never be unknown"); - check_not_unknown(clk, check_enabled, tx, "tx must never be unknown"); - traffic_logger: process (clk) is - begin - if tvalid = '1' and tready = '1' and rising_edge(clk) then - debug("Sending " & to_string(to_integer(unsigned(tdata)))); - end if; - end process traffic_logger; - -- pragma translate_on -end entity; - -architecture a of uart_tx is - signal tready_int : std_logic := '0'; -begin - main : process (clk) - type state_t is (idle, sending); - variable state : state_t := idle; - variable cycles : natural range 0 to cycles_per_bit-1 := 0; - variable data : std_logic_vector(9 downto 0); - variable index : natural range 0 to data'length-1 := 0; - begin - if rising_edge(clk) then - case state is - when idle => - tx <= '1'; - if tvalid = '1' and tready_int = '1' then - state := sending; - cycles := 0; - index := 0; - data := '1' & tdata & '0'; - end if; - when sending => - tx <= data(0); - - if cycles = cycles_per_bit - 1 then - if index = data'length-1 then - state := idle; - else - index := index + 1; - end if; - data := '0' & data(data'left downto 1); - cycles := 0; - else - cycles := cycles + 1; - end if; - end case; - - if state = idle then - tready_int <= '1'; - else - tready_int <= '0'; - end if; - end if; - end process; - - tready <= tready_int; -end architecture; diff --git a/vunit/test/acceptance/test_external_run_scripts.py b/vunit/test/acceptance/test_external_run_scripts.py index f2c19911d..77d340620 100644 --- a/vunit/test/acceptance/test_external_run_scripts.py +++ b/vunit/test/acceptance/test_external_run_scripts.py @@ -33,9 +33,6 @@ class TestExternalRunScripts(unittest.TestCase): Verify that example projects run correctly """ - def test_vhdl_uart_example_project(self): - self.check(join(ROOT, "examples", "vhdl", "uart", "run.py")) - @unittest.skipUnless(simulator_supports_verilog(), "Verilog") def test_verilog_uart_example_project(self): self.check(join(ROOT, "examples", "verilog", "uart", "run.py")) @@ -111,12 +108,6 @@ def test_vhdl_json4vhdl_example_project(self): def test_vhdl_array_example_project(self): self.check(join(ROOT, "examples", "vhdl", "array", "run.py")) - def test_vhdl_array_axis_vcs_example_project(self): - self.check(join(ROOT, "examples", "vhdl", "array_axis_vcs", "run.py")) - - def test_vhdl_axi_dma_example_project(self): - self.check(join(ROOT, "examples", "vhdl", "axi_dma", "run.py")) - def test_vhdl_user_guide_example_project(self): self.check(join(ROOT, "examples", "vhdl", "user_guide", "run.py"), exit_code=1) check_report(self.report_file, diff --git a/vunit/vhdl/verification_components/run.py b/vunit/vhdl/verification_components/run.py index 4521da942..5e1c7ccb7 100644 --- a/vunit/vhdl/verification_components/run.py +++ b/vunit/vhdl/verification_components/run.py @@ -86,20 +86,4 @@ def gen_avalon_master_tests(obj, *args): for test in tb_wishbone_master.get_tests(): gen_wb_tests(test, [8, 32], [1, 64], [0.3, 1.0], [0.3, 1.0], [0.4, 0.0]) -tb_axi_stream_protocol_checker = lib.test_bench("tb_axi_stream_protocol_checker") - -for data_length in [0, 8]: - for test in tb_axi_stream_protocol_checker.get_tests("*passing*tdata*"): - test.add_config(name="data_length=%d" % data_length, generics=dict(data_length=data_length)) - -for test in tb_axi_stream_protocol_checker.get_tests("*failing*tid width*"): - test.add_config(name="dest_length=25", generics=dict(dest_length=25)) - test.add_config(name="id_length=8 dest_length=17", generics=dict(id_length=8, dest_length=17)) - -test_failing_max_waits = tb_axi_stream_protocol_checker.test( - "Test failing check of that tready comes within max_waits after valid") -for max_waits in [0, 8]: - test_failing_max_waits.add_config(name="max_waits=%d" % max_waits, generics=dict(max_waits=max_waits)) - - ui.main() diff --git a/vunit/vhdl/verification_components/src/axi_lite_master.vhd b/vunit/vhdl/verification_components/src/axi_lite_master.vhd deleted file mode 100644 index 9c11e2b27..000000000 --- a/vunit/vhdl/verification_components/src/axi_lite_master.vhd +++ /dev/null @@ -1,154 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - - -library ieee; -use ieee.std_logic_1164.all; - -use work.queue_pkg.all; -use work.bus_master_pkg.all; -use work.sync_pkg.all; -use work.axi_pkg.all; -use work.axi_slave_pkg.all; -use work.axi_slave_private_pkg.all; -use work.axi_lite_master_pkg.all; -context work.com_context; -context work.vunit_context; - -entity axi_lite_master is - generic( - bus_handle : bus_master_t - ); - port( - aclk : in std_logic; - - arready : in std_logic; - arvalid : out std_logic := '0'; - araddr : out std_logic_vector(address_length(bus_handle) - 1 downto 0) := (others => '0'); - - rready : out std_logic := '0'; - rvalid : in std_logic; - rdata : in std_logic_vector(data_length(bus_handle) - 1 downto 0); - rresp : in axi_resp_t; - - awready : in std_logic; - awvalid : out std_logic := '0'; - awaddr : out std_logic_vector(address_length(bus_handle) - 1 downto 0) := (others => '0'); - - wready : in std_logic; - wvalid : out std_logic := '0'; - wdata : out std_logic_vector(data_length(bus_handle) - 1 downto 0) := (others => '0'); - wstrb : out std_logic_vector(byte_enable_length(bus_handle) - 1 downto 0) := (others => '0'); - - bvalid : in std_logic; - bready : out std_logic := '0'; - bresp : in axi_resp_t := axi_resp_okay); -end entity; - -architecture a of axi_lite_master is - constant reply_queue, message_queue : queue_t := new_queue; -begin - main : process - variable request_msg : msg_t; - variable msg_type : msg_type_t; - begin - receive(net, bus_handle.p_actor, request_msg); - msg_type := message_type(request_msg); - - if is_read(msg_type) or is_write(msg_type) then - push(message_queue, request_msg); - elsif msg_type = wait_until_idle_msg then - wait until ((bvalid and bready) = '1' or (rvalid and rready) = '1') and is_empty(message_queue) and rising_edge(aclk); - handle_wait_until_idle(net, msg_type, request_msg); - else - unexpected_msg_type(msg_type); - end if; - end process; - - -- Use separate process to always align to rising edge of clock - bus_process : process - variable request_msg : msg_t; - variable msg_type : msg_type_t; - variable w_done, aw_done : boolean; - variable expected_resp : axi_resp_t; - begin - wait until rising_edge(aclk) and not is_empty(message_queue); - - request_msg := pop(message_queue); - msg_type := message_type(request_msg); - - if is_read(msg_type) then - araddr <= pop_std_ulogic_vector(request_msg); - expected_resp := pop_std_ulogic_vector(request_msg) when is_axi_lite_msg(msg_type) else axi_resp_okay; - push(reply_queue, request_msg); - - arvalid <= '1'; - wait until (arvalid and arready) = '1' and rising_edge(aclk); - arvalid <= '0'; - - rready <= '1'; - wait until (rvalid and rready) = '1' and rising_edge(aclk); - rready <= '0'; - check_axi_resp(bus_handle, rresp, expected_resp, "rresp"); - - if is_visible(bus_handle.p_logger, debug) then - debug(bus_handle.p_logger, - "Read 0x" & to_hstring(rdata) & - " from address 0x" & to_hstring(araddr)); - end if; - - elsif is_write(msg_type) then - awaddr <= pop_std_ulogic_vector(request_msg); - wdata <= pop_std_ulogic_vector(request_msg); - wstrb <= pop_std_ulogic_vector(request_msg); - expected_resp := pop_std_ulogic_vector(request_msg) when is_axi_lite_msg(msg_type) else axi_resp_okay; - delete(request_msg); - - wvalid <= '1'; - awvalid <= '1'; - - w_done := false; - aw_done := false; - while not (w_done and aw_done) loop - wait until ((awvalid and awready) = '1' or (wvalid and wready) = '1') and rising_edge(aclk); - - if (awvalid and awready) = '1' then - awvalid <= '0'; - aw_done := true; - end if; - - if (wvalid and wready) = '1' then - wvalid <= '0'; - w_done := true; - end if; - end loop; - - bready <= '1'; - wait until (bvalid and bready) = '1' and rising_edge(aclk); - bready <= '0'; - check_axi_resp(bus_handle, bresp, expected_resp, "bresp"); - - if is_visible(bus_handle.p_logger, debug) then - debug(bus_handle.p_logger, - "Wrote 0x" & to_hstring(wdata) & - " to address 0x" & to_hstring(awaddr)); - end if; - end if; - end process; - - -- Reply in separate process do not destroy alignment with the clock - read_reply : process - variable request_msg, reply_msg : msg_t; - begin - wait until (rvalid and rready) = '1' and rising_edge(aclk); - request_msg := pop(reply_queue); - reply_msg := new_msg; - push_std_ulogic_vector(reply_msg, rdata); - reply(net, request_msg, reply_msg); - delete(request_msg); - end process; - -end architecture; diff --git a/vunit/vhdl/verification_components/src/axi_lite_master_pkg.vhd b/vunit/vhdl/verification_components/src/axi_lite_master_pkg.vhd deleted file mode 100644 index 4ef8cc5c3..000000000 --- a/vunit/vhdl/verification_components/src/axi_lite_master_pkg.vhd +++ /dev/null @@ -1,164 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.axi_pkg.all; -use work.bus_master_pkg.all; -context work.com_context; -context work.vunit_context; - -package axi_lite_master_pkg is - - constant axi_lite_read_msg : msg_type_t := new_msg_type("read axi lite"); - constant axi_lite_write_msg : msg_type_t := new_msg_type("write axi lite"); - - -- Blocking: Write the bus - procedure write_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant data : std_logic_vector; - constant expected_bresp : axi_resp_t := axi_resp_okay; - -- default byte enable is all bytes - constant byte_enable : std_logic_vector := ""); - - -- Non blocking: Read the bus returning a reference to the future reply - procedure read_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant expected_rresp : axi_resp_t := axi_resp_okay; - variable reference : inout bus_reference_t); - - -- Blocking: read bus with immediate reply - procedure read_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant expected_rresp : axi_resp_t := axi_resp_okay; - variable data : inout std_logic_vector); - - -- Blocking: Read bus and check result against expected data - procedure check_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant expected_rresp : axi_resp_t := axi_resp_okay; - constant expected : std_logic_vector; - constant msg : string := ""); - - function is_read(msg_type : msg_type_t) return boolean; - function is_write(msg_type : msg_type_t) return boolean; - function is_axi_lite_msg(msg_type : msg_type_t) return boolean; - -end package; - -package body axi_lite_master_pkg is - - procedure write_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant data : std_logic_vector; - constant expected_bresp : axi_resp_t := axi_resp_okay; - -- default byte enable is all bytes - constant byte_enable : std_logic_vector := "") is - variable request_msg : msg_t := new_msg(axi_lite_write_msg); - variable full_data : std_logic_vector(bus_handle.p_data_length - 1 downto 0) := (others => '0'); - variable full_address : std_logic_vector(bus_handle.p_address_length - 1 downto 0) := (others => '0'); - variable full_byte_enable : std_logic_vector(byte_enable_length(bus_handle) - 1 downto 0); - begin - full_address(address'length - 1 downto 0) := address; - push_std_ulogic_vector(request_msg, full_address); - - full_data(data'length - 1 downto 0) := data; - push_std_ulogic_vector(request_msg, full_data); - - if byte_enable = "" then - full_byte_enable := (others => '1'); - else - full_byte_enable(byte_enable'length - 1 downto 0) := byte_enable; - end if; - push_std_ulogic_vector(request_msg, full_byte_enable); - - push_std_ulogic_vector(request_msg, expected_bresp); - - send(net, bus_handle.p_actor, request_msg); - end procedure; - - procedure read_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant expected_rresp : axi_resp_t := axi_resp_okay; - variable reference : inout bus_reference_t) is - variable full_address : std_logic_vector(bus_handle.p_address_length - 1 downto 0) := (others => '0'); - alias request_msg : msg_t is reference; - begin - request_msg := new_msg(axi_lite_read_msg); - full_address(address'length - 1 downto 0) := address; - push_std_ulogic_vector(request_msg, full_address); - push_std_ulogic_vector(request_msg, expected_rresp); - send(net, bus_handle.p_actor, request_msg); - end procedure; - - procedure read_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant expected_rresp : axi_resp_t := axi_resp_okay; - variable data : inout std_logic_vector) is - variable reference : bus_reference_t; - begin - read_axi_lite(net, bus_handle, address, expected_rresp, reference); - await_read_bus_reply(net, reference, data); - end procedure; - - procedure check_axi_lite(signal net : inout network_t; - constant bus_handle : bus_master_t; - constant address : std_logic_vector; - constant expected_rresp : axi_resp_t := axi_resp_okay; - constant expected : std_logic_vector; - constant msg : string := "") is - variable data : std_logic_vector(bus_handle.p_data_length - 1 downto 0); - variable edata : std_logic_vector(data'range) := (others => '0'); - - impure function error_prefix return string is - begin - if msg = "" then - return "check_bus(x""" & to_hstring(address) & """)"; - else - return msg; - end if; - end; - - impure function base_error return string is - begin - return error_prefix & " - Got x""" & to_hstring(data) & """ expected x""" & to_hstring(edata) & """"; - end; - begin - - edata(expected'length - 1 downto 0) := expected; - - read_axi_lite(net, bus_handle, address, expected_rresp, data); - if not std_match(data, edata) then - failure(bus_handle.p_logger, base_error); - end if; - end procedure; - - function is_read(msg_type : msg_type_t) return boolean is - begin - return msg_type = bus_read_msg or msg_type = axi_lite_read_msg; - end function; - - function is_write(msg_type : msg_type_t) return boolean is - begin - return msg_type = bus_write_msg or msg_type = axi_lite_write_msg; - end function; - - function is_axi_lite_msg(msg_type : msg_type_t) return boolean is - begin - return msg_type = axi_lite_read_msg or msg_type = axi_lite_write_msg; - end function; - -end package body; diff --git a/vunit/vhdl/verification_components/src/axi_pkg.vhd b/vunit/vhdl/verification_components/src/axi_pkg.vhd deleted file mode 100644 index 0c1265c8c..000000000 --- a/vunit/vhdl/verification_components/src/axi_pkg.vhd +++ /dev/null @@ -1,25 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -package axi_pkg is - subtype axi_resp_t is std_logic_vector(1 downto 0); - constant axi_resp_okay : axi_resp_t := "00"; - constant axi_resp_exokay : axi_resp_t := "01"; - constant axi_resp_slverr : axi_resp_t := "10"; - constant axi_resp_decerr : axi_resp_t := "11"; - - subtype axi_burst_type_t is std_logic_vector(1 downto 0); - constant axi_burst_type_fixed : axi_burst_type_t := "00"; - constant axi_burst_type_incr : axi_burst_type_t := "01"; - constant axi_burst_type_wrap : axi_burst_type_t := "10"; - - subtype axi4_len_t is std_logic_vector(7 downto 0); - constant max_axi4_burst_length : natural := 2**axi4_len_t'length; - subtype axi4_size_t is std_logic_vector(2 downto 0); -end package; diff --git a/vunit/vhdl/verification_components/src/axi_read_slave.vhd b/vunit/vhdl/verification_components/src/axi_read_slave.vhd deleted file mode 100644 index 233d905ee..000000000 --- a/vunit/vhdl/verification_components/src/axi_read_slave.vhd +++ /dev/null @@ -1,166 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.axi_pkg.all; -use work.axi_slave_private_pkg.all; -use work.queue_pkg.all; -context work.com_context; -context work.vc_context; - -entity axi_read_slave is - generic ( - axi_slave : axi_slave_t); - port ( - aclk : in std_logic; - - arvalid : in std_logic; - arready : out std_logic := '0'; - arid : in std_logic_vector; - araddr : in std_logic_vector; - arlen : in std_logic_vector; - arsize : in std_logic_vector; - arburst : in axi_burst_type_t; - - rvalid : out std_logic := '0'; - rready : in std_logic; - rid : out std_logic_vector; - rdata : out std_logic_vector; - rresp : out axi_resp_t; - rlast : out std_logic - ); -end entity; - -architecture a of axi_read_slave is - shared variable self : axi_slave_private_t; - signal initialized : boolean := false; -begin - - control_process : process - begin - self.init(axi_slave, read_slave, 2**arid'length-1, rdata); - initialized <= true; - main_loop(self, net); - wait; - end process; - - axi_process : process - variable input_burst, burst : axi_burst_t; - variable address : integer; - variable idx : integer; - variable beats : natural := 0; - - variable response_time : time; - variable has_response_time : boolean := false; - begin - assert arid'length = rid'length report "arid vs rid data width mismatch"; - -- Initialization - rid <= (rid'range => '0'); - rdata <= (rdata'range => '0'); - rresp <= (rresp'range => '0'); - rlast <= '0'; - - wait on initialized until initialized; - - loop - if (rready and rvalid) = '1' then - rvalid <= '0'; - beats := beats - 1; - end if; - - if (arvalid and arready) = '1' then - input_burst := self.create_burst(arid, araddr, arlen, arsize, arburst); - self.push_random_response_time; - self.push_burst(input_burst); - end if; - - if not self.burst_queue_empty and beats = 0 then - if not has_response_time then - has_response_time := true; - response_time := self.pop_response_time; - end if; - - if has_response_time and response_time <= now then - has_response_time := false; - burst := self.pop_burst; - beats := burst.length; - rid <= std_logic_vector(to_unsigned(burst.id, rid'length)); - rresp <= axi_resp_okay; - address := burst.address; - end if; - end if; - - if beats > 0 and (rvalid = '0' or rready = '1') and not self.should_stall_data then - rvalid <= '1'; - for j in 0 to burst.size-1 loop - idx := (address + j) mod self.data_size; - rdata(8*idx+7 downto 8*idx) <= std_logic_vector(to_unsigned(read_byte(axi_slave.p_memory, address+j), 8)); - end loop; - - if burst.burst_type = axi_burst_type_incr then - address := address + burst.size; - end if; - - if beats = 1 then - self.finish_burst(burst); - rlast <= '1'; - else - rlast <= '0'; - end if; - end if; - - if self.should_stall_address or self.burst_queue_full then - arready <= '0'; - else - arready <= '1'; - end if; - - wait until rising_edge(aclk); - end loop; - end process; - - well_behaved_check : process - variable size, len : natural; - variable num_beats : integer := 0; - variable num_beats_now : integer; - begin - wait on initialized until initialized; - loop - - num_beats_now := num_beats; - - if arvalid = '1' then - len := to_integer(unsigned(arlen)); - num_beats_now := num_beats + len + 1; - end if; - - -- Always keep track of num_beats such that the well behaved check can be enabled at any time - if (arvalid and arready) = '1' then - size := 2**to_integer(unsigned(arsize)); - num_beats := num_beats_now; - - if self.should_check_well_behaved and size /= self.data_size and len /= 0 then - self.fail("Burst not well behaved, axi size = " & to_string(size) & " but bus data width allows " & to_string(self.data_size)); - end if; - end if; - - if self.should_check_well_behaved and num_beats_now > 0 and rready /= '1' then - self.fail("Burst not well behaved, rready was not high during active burst"); - end if; - - if (rready and rvalid) = '1' then - num_beats := -1; - end if; - - wait until rising_edge(aclk); - end loop; - wait; - end process; - -end architecture; diff --git a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd b/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd deleted file mode 100644 index 8cdf148a0..000000000 --- a/vunit/vhdl/verification_components/src/axi_slave_pkg.vhd +++ /dev/null @@ -1,298 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -use work.queue_pkg.all; -use work.logger_pkg.all; -use work.memory_pkg.all; -context work.com_context; -use work.axi_statistics_pkg.all; - -package axi_slave_pkg is - subtype probability_t is real range 0.0 to 1.0; - - type axi_slave_t is record - -- Private - p_initial_address_fifo_depth : positive; - p_initial_write_response_fifo_depth : positive; - p_initial_check_4kbyte_boundary : boolean; - p_initial_address_stall_probability : probability_t; - p_initial_data_stall_probability : probability_t; - p_initial_write_response_stall_probability : probability_t; - p_initial_min_response_latency : delay_length; - p_initial_max_response_latency : delay_length; - p_actor : actor_t; - p_memory : memory_t; - p_logger : logger_t; - end record; - - constant axi_slave_logger : logger_t := get_logger("vunit_lib:axi_slave_pkg"); - impure function new_axi_slave(memory : memory_t; - address_fifo_depth : positive := 1; - write_response_fifo_depth : positive := 1; - check_4kbyte_boundary : boolean := true; - address_stall_probability : probability_t := 0.0; - data_stall_probability : probability_t := 0.0; - write_response_stall_probability : probability_t := 0.0; - min_response_latency : delay_length := 0 ns; - max_response_latency : delay_length := 0 ns; - logger : logger_t := axi_slave_logger) return axi_slave_t; - - -- Get the logger used by the axi_slave - function get_logger(axi_slave : axi_slave_t) return logger_t; - - -- Set the maximum number address channel tokens that can be queued - procedure set_address_fifo_depth(signal net : inout network_t; - axi_slave : axi_slave_t; - depth : positive); - - -- Set the maximum number write responses that can be queued - procedure set_write_response_fifo_depth(signal net : inout network_t; - axi_slave : axi_slave_t; - depth : positive); - - -- Set the address channel stall probability - procedure set_address_stall_probability(signal net : inout network_t; - axi_slave : axi_slave_t; - probability : probability_t); - - -- Set the data channel stall probability - procedure set_data_stall_probability(signal net : inout network_t; - axi_slave : axi_slave_t; - probability : probability_t); - - -- Set the write response stall probability - procedure set_write_response_stall_probability(signal net : inout network_t; - axi_slave : axi_slave_t; - probability : probability_t); - - -- Set the response latency - -- - -- For a write slave this is the time between the last write data - -- and providing the write reponse. All write data is written to the - -- memory model right before providing write response. - -- Data address and expected value is still checked as soons as it arrives to - -- the axi slave and is not delayed until the write response time. - -- - -- For a read slave this is the time between the read burst arrival and the - -- first provided read data - -- - -- The response latency is randomly choosen in the uniform interval: - -- [min_latency, max_latency] - procedure set_response_latency(signal net : inout network_t; - axi_slave : axi_slave_t; - min_latency, max_latency : delay_length); - - -- Short hand for set_response_latency when min and max are the same - procedure set_response_latency(signal net : inout network_t; - axi_slave : axi_slave_t; - latency : delay_length); - - procedure enable_4kbyte_boundary_check(signal net : inout network_t; - axi_slave : axi_slave_t); - procedure disable_4kbyte_boundary_check(signal net : inout network_t; - axi_slave : axi_slave_t); - - -- Get statistics object from axi slave - -- Dynamically allocates new statistics object which must he deallocated when - -- used - -- This procedure will automatically deallocate the input statistics object - -- if it is not null - procedure get_statistics(signal net : inout network_t; - axi_slave : axi_slave_t; - variable stat : inout axi_statistics_t; - clear : boolean := false); - - -- Check that bursts are well behaved, that is that data channel traffic is - -- as compact as possible - - -- For write: - -- 1. awvalid never high without wvalid - -- 2. wvalid never goes low during active burst - -- 3. uses max awsize supported by data width - -- 4. bready never low during active burst - - -- For read: - -- 1. rready never low during active burst - -- 2. uses max arsize supported by data width - procedure enable_well_behaved_check(signal net : inout network_t; axi_slave : axi_slave_t); - - -- Private constants - constant axi_slave_set_address_fifo_depth_msg : msg_type_t := new_msg_type("axi slave set address channel fifo depth"); - constant axi_slave_set_write_response_fifo_depth_msg : msg_type_t := new_msg_type("set write response fifo depth"); - constant axi_slave_set_address_stall_probability_msg : msg_type_t := new_msg_type("axi slave set address channel stall probability"); - constant axi_slave_set_data_stall_probability_msg : msg_type_t := new_msg_type("axi slave set data stall probability"); - constant axi_slave_set_write_response_stall_probability_msg : msg_type_t := new_msg_type("axi slave set write response stall probability"); - constant axi_slave_set_response_latency_msg : msg_type_t := new_msg_type("axi slave response latency probability"); - constant axi_slave_configure_4kbyte_boundary_check_msg : msg_type_t := new_msg_type("axi slave configure 4kbyte boundary check"); - constant axi_slave_get_statistics_msg : msg_type_t := new_msg_type("axi slave get statistics"); - constant axi_slave_enable_well_behaved_check_msg : msg_type_t := new_msg_type("axi slave enable well behaved check"); - -end package; - -package body axi_slave_pkg is - impure function new_axi_slave(memory : memory_t; - address_fifo_depth : positive := 1; - write_response_fifo_depth : positive := 1; - check_4kbyte_boundary : boolean := true; - address_stall_probability : probability_t := 0.0; - data_stall_probability : probability_t := 0.0; - write_response_stall_probability : probability_t := 0.0; - min_response_latency : delay_length := 0 ns; - max_response_latency : delay_length := 0 ns; - logger : logger_t := axi_slave_logger) return axi_slave_t is - begin - return (p_actor => new_actor, - p_initial_address_fifo_depth => address_fifo_depth, - p_initial_write_response_fifo_depth => write_response_fifo_depth, - p_initial_check_4kbyte_boundary => check_4kbyte_boundary, - p_initial_address_stall_probability => address_stall_probability, - p_initial_data_stall_probability => data_stall_probability, - p_initial_write_response_stall_probability => write_response_stall_probability, - p_initial_min_response_latency => min_response_latency, - p_initial_max_response_latency => max_response_latency, - p_memory => to_vc_interface(memory, logger), - p_logger => logger); - end; - - function get_logger(axi_slave : axi_slave_t) return logger_t is - begin - return axi_slave.p_logger; - end; - - procedure set_address_fifo_depth(signal net : inout network_t; - axi_slave : axi_slave_t; - depth : positive) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_set_address_fifo_depth_msg); - push(request_msg, depth); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on set_address_fifo_depth command"; - end; - - procedure set_write_response_fifo_depth(signal net : inout network_t; - axi_slave : axi_slave_t; - depth : positive) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_set_write_response_fifo_depth_msg); - push(request_msg, depth); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on set_write_response_fifo_depth command"; - end; - - procedure set_address_stall_probability(signal net : inout network_t; - axi_slave : axi_slave_t; - probability : probability_t) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_set_address_stall_probability_msg); - push_real(request_msg, probability); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on set_address_stall_probability command"; - end; - - procedure set_data_stall_probability(signal net : inout network_t; - axi_slave : axi_slave_t; - probability : probability_t) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_set_data_stall_probability_msg); - push_real(request_msg, probability); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on set_data_stall_probability command"; - end; - - procedure set_write_response_stall_probability(signal net : inout network_t; axi_slave : axi_slave_t; - probability : probability_t) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_set_write_response_stall_probability_msg); - push_real(request_msg, probability); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on set_write_response_stall_probability command"; - end; - - procedure configure_4kbyte_boundary_check(signal net : inout network_t; - axi_slave : axi_slave_t; - value : boolean) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_configure_4kbyte_boundary_check_msg); - push_boolean(request_msg, value); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on configure_4kbyte_boundary_check command"; - end; - - procedure set_response_latency(signal net : inout network_t; - axi_slave : axi_slave_t; - min_latency, max_latency : delay_length) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_set_response_latency_msg); - push_time(request_msg, min_latency); - push_time(request_msg, max_latency); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on set_response_latency command"; - end; - - -- Short hand for set_response_latency when min and max are the same - procedure set_response_latency(signal net : inout network_t; - axi_slave : axi_slave_t; - latency : delay_length) is - begin - set_response_latency(net, axi_slave, latency, latency); - end; - - procedure enable_4kbyte_boundary_check(signal net : inout network_t; - axi_slave : axi_slave_t) is - begin - configure_4kbyte_boundary_check(net, axi_slave, true); - end; - - procedure disable_4kbyte_boundary_check(signal net : inout network_t; - axi_slave : axi_slave_t) is - begin - configure_4kbyte_boundary_check(net, axi_slave, false); - end; - - - procedure get_statistics(signal net : inout network_t; - axi_slave : axi_slave_t; - variable stat : inout axi_statistics_t; - clear : boolean := false) is - variable request_msg, reply_msg : msg_t; - begin - deallocate(stat); - request_msg := new_msg(axi_slave_get_statistics_msg); - push_boolean(request_msg, clear); - send(net, axi_slave.p_actor, request_msg); - receive_reply(net, request_msg, reply_msg); - stat := (p_count_by_burst_length => pop_integer_vector_ptr_ref(reply_msg)); - delete(request_msg); - delete(reply_msg); - end; - - procedure enable_well_behaved_check(signal net : inout network_t; - axi_slave : axi_slave_t) is - variable request_msg : msg_t; - variable ack : boolean; - begin - request_msg := new_msg(axi_slave_enable_well_behaved_check_msg); - request(net, axi_slave.p_actor, request_msg, ack); - assert ack report "Failed on msg_enable_well_behaved_check command"; - end; -end package body; diff --git a/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd b/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd deleted file mode 100644 index bbc8ee26b..000000000 --- a/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd +++ /dev/null @@ -1,580 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - --- Private support package for axi_{read, write}_slave.vhd - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use std.textio.all; - -use work.axi_pkg.all; -use work.queue_pkg.all; -use work.integer_vector_ptr_pkg.all; -context work.vunit_context; -context work.com_context; -context work.vc_context; - -library osvvm; -use osvvm.RandomPkg.all; - -package axi_slave_private_pkg is - - type axi_burst_t is record - id : integer; - address : integer; - length : integer; - size : integer; - burst_type : axi_burst_type_t; - - -- A running counter for each processed burst - -- Referring to this index for all burst related debug prints - index : natural; - end record; - - impure function describe_burst(burst : axi_burst_t) return string; - - type axi_slave_type_t is (write_slave, - read_slave); - - type axi_slave_private_t is protected - procedure init(axi_slave : axi_slave_t; - axi_slave_type : axi_slave_type_t; - max_id : natural; - data : std_logic_vector); - impure function get_actor return actor_t; - - procedure set_address_fifo_depth(depth : positive); - procedure set_write_response_fifo_depth(depth : positive); - procedure set_address_stall_probability(probability : probability_t); - procedure set_data_stall_probability(probability : probability_t); - procedure set_write_response_stall_probability(probability : probability_t); - procedure set_min_response_latency(latency : delay_length); - procedure set_max_response_latency(latency : delay_length); - procedure set_check_4kbyte_boundary(value : boolean); - procedure enable_well_behaved_check; - impure function should_check_well_behaved return boolean; - impure function should_stall_address return boolean; - impure function should_stall_data return boolean; - impure function should_stall_write_response return boolean; - - impure function create_burst(axid : std_logic_vector; - axaddr : std_logic_vector; - axlen : std_logic_vector; - axsize : std_logic_vector; - axburst : axi_burst_type_t) return axi_burst_t; - - procedure push_burst(burst : axi_burst_t); - impure function pop_burst return axi_burst_t; - impure function burst_queue_full return boolean; - impure function burst_queue_empty return boolean; - impure function burst_queue_length return natural; - - impure function resp_queue_full return boolean; - impure function resp_queue_empty return boolean; - impure function resp_queue_length return natural; - procedure push_resp(burst : axi_burst_t); - impure function pop_resp return axi_burst_t; - - procedure finish_burst(burst : axi_burst_t); - - procedure push_random_response_time; - impure function pop_response_time return time; - - procedure fail(msg : string); - procedure check_4kbyte_boundary(burst : axi_burst_t); - impure function data_size return integer; - - impure function get_statistics return axi_statistics_t; - procedure clear_statistics; - end protected; - - procedure main_loop(variable self : inout axi_slave_private_t; - signal net : inout network_t); - - procedure check_axi_resp(bus_handle : bus_master_t; got, expected : axi_resp_t; msg : string); -end package; - - -package body axi_slave_private_pkg is - - impure function describe_burst(burst : axi_burst_t) return string is - begin - return "#" & to_string(burst.index) & " for id " & to_string(burst.id); - end; - - procedure push_axi_burst(queue : queue_t; burst : axi_burst_t); - impure function pop_axi_burst(queue : queue_t) return axi_burst_t; - - type axi_slave_private_t is protected body - variable p_axi_slave : axi_slave_t; - variable p_axi_slave_type : axi_slave_type_t; - variable p_data_size : integer; - variable p_max_id : natural; - variable p_id_indexes : integer_vector_ptr_t; - variable p_burst_queue_max_length : natural; - variable p_burst_queue : queue_t; - variable p_burst_queue_length : natural; - variable p_resp_queue_max_length : natural; - variable p_resp_queue : queue_t; - variable p_resp_queue_length : natural; - variable p_check_4kbyte_boundary : boolean; - variable p_rnd : RandomPType; - variable p_addr_stall_prob : probability_t; - variable p_data_stall_prob : probability_t; - variable p_wresp_stall_prob : probability_t; - variable p_min_response_latency : delay_length; - variable p_max_response_latency : delay_length; - variable p_response_time_queue : queue_t; - variable p_check_well_behaved : boolean; - variable p_statistics : axi_statistics_t; - - procedure init(axi_slave : axi_slave_t; - axi_slave_type : axi_slave_type_t; - max_id : natural; - data : std_logic_vector) is - begin - p_axi_slave := axi_slave; - p_axi_slave_type := axi_slave_type; - p_data_size := data'length/8; - p_max_id := max_id; - p_id_indexes := new_integer_vector_ptr(length => max_id+1, value => 0); - p_burst_queue_max_length := axi_slave.p_initial_address_fifo_depth; - p_burst_queue := new_queue; - p_burst_queue_length := 0; - p_resp_queue_max_length := axi_slave.p_initial_write_response_fifo_depth; - p_resp_queue := new_queue; - p_resp_queue_length := 0; - p_check_4kbyte_boundary := axi_slave.p_initial_check_4kbyte_boundary; - p_check_well_behaved := false; - set_address_stall_probability(axi_slave.p_initial_address_stall_probability); - set_data_stall_probability(axi_slave.p_initial_data_stall_probability); - set_write_response_stall_probability(axi_slave.p_initial_write_response_stall_probability); - p_response_time_queue := new_queue; - set_min_response_latency(axi_slave.p_initial_min_response_latency); - set_max_response_latency(axi_slave.p_initial_max_response_latency); - p_statistics := new_axi_statistics; - end; - - impure function get_actor return actor_t is - begin - return p_axi_slave.p_actor; - end; - - procedure set_address_fifo_depth(depth : positive) is - begin - if burst_queue_length > depth then - fail("New address fifo depth " & to_string(depth) & - " is smaller than current content size " & to_string(burst_queue_length)); - else - p_burst_queue_max_length := depth; - end if; - end procedure; - - procedure set_write_response_fifo_depth(depth : positive) is - begin - if resp_queue_length > depth then - fail("New write response fifo depth " & to_string(depth) & - " is smaller than current content size " & to_string(resp_queue_length)); - else - p_resp_queue_max_length := depth; - end if; - end procedure; - - procedure set_address_stall_probability(probability : probability_t) is - begin - p_addr_stall_prob := probability; - end; - - procedure set_data_stall_probability(probability : probability_t) is - begin - p_data_stall_prob := probability; - end; - - procedure set_write_response_stall_probability(probability : probability_t) is - begin - p_wresp_stall_prob := probability; - end; - - procedure set_min_response_latency(latency : delay_length) is - begin - p_min_response_latency := latency; - end; - - procedure set_max_response_latency(latency : delay_length) is - begin - p_max_response_latency := latency; - end; - - procedure set_check_4kbyte_boundary(value : boolean) is - begin - p_check_4kbyte_boundary := value; - end; - - procedure enable_well_behaved_check is - begin - p_check_well_behaved := true; - end; - - impure function should_check_well_behaved return boolean is - begin - return p_check_well_behaved; - end; - - impure function should_stall(prob : probability_t) return boolean is - begin - -- Enhance performance when prob = 0.0 - return prob /= 0.0 and p_rnd.Uniform(0.0, 1.0) < prob; - end; - - impure function should_stall_address return boolean is - begin - return should_stall(p_addr_stall_prob); - end; - - impure function should_stall_data return boolean is - begin - return should_stall(p_data_stall_prob); - end; - - impure function should_stall_write_response return boolean is - begin - return should_stall(p_wresp_stall_prob); - end; - - impure function create_burst(axid : std_logic_vector; - axaddr : std_logic_vector; - axlen : std_logic_vector; - axsize : std_logic_vector; - axburst : axi_burst_type_t) return axi_burst_t is - - -- Return the correct prefix ar/aw depending on slave type - impure function ax return string is - begin - case p_axi_slave_type is - when read_slave => return "ar"; - when write_slave => return "aw"; - end case; - end; - - -- Return the correct read/write burst description - impure function description return string is - begin - case p_axi_slave_type is - when read_slave => return "read burst"; - when write_slave => return "write burst"; - end case; - end; - - impure function burst_string return string is - begin - - if axburst = axi_burst_type_fixed then - return "fixed"; - elsif axburst = axi_burst_type_incr then - return "incr"; - elsif axburst = axi_burst_type_wrap then - return "wrap"; - else - return "undefined"; - end if; - end; - - variable burst : axi_burst_t; - begin - burst.id := to_integer(unsigned(axid)); - burst.address := to_integer(unsigned(axaddr)); - burst.length := to_integer(unsigned(axlen)) + 1; - burst.size := 2**to_integer(unsigned(axsize)); - burst.burst_type := axburst; - assert burst.id <= p_max_id report "axi id to large"; - burst.index := get(p_id_indexes, burst.id); - set(p_id_indexes, burst.id, burst.index + 1); - - if is_visible(p_axi_slave.p_logger, debug) then - debug(p_axi_slave.p_logger, - "Got " & description & " " & describe_burst(burst) & - LF & ax & "id = 0x" & to_hstring(axid) & - LF & ax & "addr = 0x" & to_hstring(axaddr) & - LF & ax & "len = " & to_string(to_integer(unsigned(to_01(axlen)))) & - LF & ax & "size = " & to_string(to_integer(unsigned(to_01(axsize)))) & - LF & ax & "burst = " & burst_string & " (" & to_string(axburst) & ")" - ); - end if; - - add_burst_length(p_statistics, burst.length); - - if burst.burst_type = axi_burst_type_wrap then - fail("Wrapping burst type not supported"); - end if; - - if p_check_4kbyte_boundary then - check_4kbyte_boundary(burst); - end if; - - return burst; - end function; - - procedure push_burst(burst : axi_burst_t) is - begin - push_axi_burst(p_burst_queue, burst); - p_burst_queue_length := p_burst_queue_length + 1; - end; - - impure function pop_burst return axi_burst_t is - constant burst : axi_burst_t := pop_axi_burst(p_burst_queue); - begin - if is_visible(p_axi_slave.p_logger, debug) then - case p_axi_slave_type is - when write_slave => - debug(p_axi_slave.p_logger, - "Start accepting data for write burst " & describe_burst(burst)); - when read_slave => - debug(p_axi_slave.p_logger, - "Start providing data for read burst " & describe_burst(burst)); - end case; - end if; - p_burst_queue_length := p_burst_queue_length - 1; - return burst; - end; - - impure function burst_queue_full return boolean is - begin - return burst_queue_length = p_burst_queue_max_length; - end; - - impure function burst_queue_empty return boolean is - begin - return burst_queue_length = 0; - end; - - impure function burst_queue_length return natural is - begin - return p_burst_queue_length; - end; - - procedure push_resp(burst : axi_burst_t) is - begin - push_axi_burst(p_resp_queue, burst); - p_resp_queue_length := p_resp_queue_length + 1; - end; - - impure function pop_resp return axi_burst_t is - constant resp_burst : axi_burst_t := pop_axi_burst(p_resp_queue); - begin - if is_visible(p_axi_slave.p_logger, debug) then - debug(p_axi_slave.p_logger, - "Providing write response for burst " & describe_burst(resp_burst)); - end if; - p_resp_queue_length := p_resp_queue_length - 1; - return resp_burst; - end; - - procedure finish_burst(burst : axi_burst_t) is - begin - if is_visible(p_axi_slave.p_logger, debug) then - case p_axi_slave_type is - when write_slave => - debug(p_axi_slave.p_logger, - "Accepted last data for write burst " & describe_burst(burst)); - when read_slave => - debug(p_axi_slave.p_logger, - "Providing last data for read burst " & describe_burst(burst)); - end case; - end if; - end; - - impure function random_response_latency return delay_length is - begin - if p_min_response_latency = p_max_response_latency then - return p_min_response_latency; - else - return p_rnd.RandTime(p_min_response_latency, p_max_response_latency); - end if; - end; - - procedure push_random_response_time is - begin - push_time(p_response_time_queue, now + random_response_latency); - end; - - impure function pop_response_time return time is - begin - return pop_time(p_response_time_queue); - end; - - impure function resp_queue_full return boolean is - begin - return resp_queue_length = p_resp_queue_max_length; - end; - - impure function resp_queue_empty return boolean is - begin - return resp_queue_length = 0; - end; - - impure function resp_queue_length return natural is - begin - return p_resp_queue_length; - end; - - procedure fail(msg : string) is - begin - failure(p_axi_slave.p_logger, msg); - end; - - procedure check_4kbyte_boundary(burst : axi_burst_t) is - variable first_address, last_address : integer; - variable first_page, last_page : integer; - begin - first_address := burst.address - (burst.address mod data_size); -- Aligned - last_address := burst.address + burst.size*burst.length - 1; - - first_page := first_address / 4096; - last_page := last_address / 4096; - - if first_page /= last_page then - fail("Crossing 4KByte boundary. First page = " - & integer'image(first_page) & " (" & to_string(first_address) & "/4096)" - & ", last page = " - & integer'image(last_page) & " (" & to_string(last_address) & "/4096)"); - end if; - end procedure; - - impure function data_size return integer is - begin - return p_data_size; - end; - - impure function get_statistics return axi_statistics_t is - begin - return copy(p_statistics); - end; - - procedure clear_statistics is - begin - clear(p_statistics); - end; - - end protected body; - - - procedure push_axi_burst(queue : queue_t; burst : axi_burst_t) is - begin - push(queue, burst.id); - push(queue, burst.address); - push(queue, burst.length); - push(queue, burst.size); - push(queue, burst.index); - push_boolean(queue, burst.burst_type = axi_burst_type_fixed); - end; - - impure function pop_axi_burst(queue : queue_t) return axi_burst_t is - variable burst : axi_burst_t; - begin - burst.id := pop(queue); - burst.address := pop(queue); - burst.length := pop(queue); - burst.size := pop(queue); - burst.index := pop(queue); - - if pop_boolean(queue) then - burst.burst_type := axi_burst_type_fixed; - else - burst.burst_type := axi_burst_type_incr; - end if; - - return burst; - end; - - procedure main_loop(variable self : inout axi_slave_private_t; - signal net : inout network_t) is - variable reply_msg, request_msg : msg_t; - variable msg_type : msg_type_t; - - variable clear_stat : boolean; - variable stat : axi_statistics_t; - begin - while true loop - receive(net, self.get_actor, request_msg); - msg_type := message_type(request_msg); - - if msg_type = axi_slave_set_address_fifo_depth_msg then - self.set_address_fifo_depth(pop(request_msg)); - acknowledge(net, request_msg, true); - - elsif msg_type = axi_slave_set_write_response_fifo_depth_msg then - self.set_write_response_fifo_depth(pop(request_msg)); - acknowledge(net, request_msg, true); - - elsif msg_type = axi_slave_set_address_stall_probability_msg then - self.set_address_stall_probability(pop_real(request_msg)); - acknowledge(net, request_msg, true); - - elsif msg_type = axi_slave_set_data_stall_probability_msg then - self.set_data_stall_probability(pop_real(request_msg)); - acknowledge(net, request_msg, true); - - elsif msg_type = axi_slave_set_write_response_stall_probability_msg then - self.set_write_response_stall_probability(pop_real(request_msg)); - acknowledge(net, request_msg, true); - - elsif msg_type = axi_slave_set_response_latency_msg then - self.set_min_response_latency(pop_time(request_msg)); - self.set_max_response_latency(pop_time(request_msg)); - acknowledge(net, request_msg, true); - - elsif msg_type = axi_slave_configure_4kbyte_boundary_check_msg then - self.set_check_4kbyte_boundary(pop_boolean(request_msg)); - acknowledge(net, request_msg, true); - - elsif msg_type = axi_slave_get_statistics_msg then - clear_stat := pop_boolean(request_msg); - stat := self.get_statistics; - - if clear_stat then - self.clear_statistics; - end if; - - reply_msg := new_msg; - push_integer_vector_ptr_ref(reply_msg, stat.p_count_by_burst_length); - reply(net, request_msg, reply_msg); - delete(request_msg); - - elsif msg_type = axi_slave_enable_well_behaved_check_msg then - self.enable_well_behaved_check; - acknowledge(net, request_msg, true); - else - unexpected_msg_type(msg_type); - end if; - - delete(request_msg); - end loop; - end; - - function resp_to_string(resp : axi_resp_t) return string is - begin - case resp is - when axi_resp_okay => return "OKAY"; - when axi_resp_exokay => return "EXOKAY"; - when axi_resp_slverr => return "SLVERR"; - when axi_resp_decerr => return "DECERR"; - when others => return "UNKNOWN"; - end case; - end; - - procedure check_axi_resp(bus_handle : bus_master_t; got, expected : axi_resp_t; msg : string) is - function describe(resp : axi_resp_t) return string is - begin - return resp_to_string(resp) & "(" & to_string(resp) & ")"; - end; - begin - if got /= expected then - failure(bus_handle.p_logger, msg & " - Got AXI response " & describe(got) & " expected " & describe(expected)); - end if; - end; -end package body; diff --git a/vunit/vhdl/verification_components/src/axi_statistics_pkg.vhd b/vunit/vhdl/verification_components/src/axi_statistics_pkg.vhd deleted file mode 100644 index d39895601..000000000 --- a/vunit/vhdl/verification_components/src/axi_statistics_pkg.vhd +++ /dev/null @@ -1,128 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -use work.axi_pkg.all; -use work.integer_vector_ptr_pool_pkg.all; -use work.integer_vector_ptr_pkg.all; - -package axi_statistics_pkg is - type axi_statistics_t is record - -- Private - p_count_by_burst_length : integer_vector_ptr_t; - end record; - constant null_axi_statistics : axi_statistics_t := (p_count_by_burst_length => null_ptr); - - -- Get the maximum burst length that occured - impure function max_burst_length(stat : axi_statistics_t) return natural; - - -- Get the minimum burst length that occured - impure function min_burst_length(stat : axi_statistics_t) return natural; - - -- Get the number of bursts that occured with specific length - impure function get_num_burst_with_length(stat : axi_statistics_t; - burst_length : natural) return natural; - - -- Get the number of bursts - impure function num_bursts(stat : axi_statistics_t) return natural; - - -- Free dynamically allocated memory - procedure deallocate(variable stat : inout axi_statistics_t); - - -- Private - impure function new_axi_statistics return axi_statistics_t; - procedure add_burst_length(stat : axi_statistics_t; - burst_length : natural); - impure function copy(stat : axi_statistics_t) return axi_statistics_t; - procedure clear(stat : axi_statistics_t); -end package; - - -package body axi_statistics_pkg is - constant ptr_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool; - - impure function new_axi_statistics return axi_statistics_t is - variable stat : axi_statistics_t; - begin - stat := (p_count_by_burst_length => new_integer_vector_ptr(ptr_pool, - min_length => max_axi4_burst_length + 1)); - clear(stat); - return stat; - end; - - procedure clear(stat : axi_statistics_t) is - begin - -- Clear re-used integer_vector_ptr - for i in 0 to length(stat.p_count_by_burst_length) - 1 loop - set(stat.p_count_by_burst_length, i, 0); - end loop; - end; - - procedure add_burst_length(stat : axi_statistics_t; - burst_length : natural) is - - begin - set(stat.p_count_by_burst_length, burst_length, - get(stat.p_count_by_burst_length, burst_length) + 1); - end; - - impure function max_burst_length(stat : axi_statistics_t) return natural is - begin - for i in length(stat.p_count_by_burst_length)-1 downto 0 loop - if get_num_burst_with_length(stat, i) > 0 then - return i; - end if; - end loop; - - return 0; - end; - - impure function min_burst_length(stat : axi_statistics_t) return natural is - begin - for i in 0 to length(stat.p_count_by_burst_length)-1 loop - if get_num_burst_with_length(stat, i) > 0 then - return i; - end if; - end loop; - - return 0; - end; - - impure function get_num_burst_with_length(stat : axi_statistics_t; - burst_length : natural) return natural is - begin - if burst_length >= length(stat.p_count_by_burst_length) then - return 0; - else - return get(stat.p_count_by_burst_length, burst_length); - end if; - end; - - impure function num_bursts(stat : axi_statistics_t) return natural is - variable sum : natural := 0; - begin - for i in 0 to max_axi4_burst_length loop - sum := sum + get_num_burst_with_length(stat, i); - end loop; - return sum; - end; - - impure function copy(stat : axi_statistics_t) return axi_statistics_t is - constant stat2 : axi_statistics_t := new_axi_statistics; - begin - for i in 0 to length(stat.p_count_by_burst_length)-1 loop - set(stat2.p_count_by_burst_length, i, get(stat.p_count_by_burst_length, i)); - end loop; - return stat2; - end; - - procedure deallocate(variable stat : inout axi_statistics_t) is - begin - if stat /= null_axi_statistics then - recycle(ptr_pool, stat.p_count_by_burst_length); - stat := null_axi_statistics; - end if; - end; -end package body; diff --git a/vunit/vhdl/verification_components/src/axi_stream_master.vhd b/vunit/vhdl/verification_components/src/axi_stream_master.vhd deleted file mode 100644 index 228d223c5..000000000 --- a/vunit/vhdl/verification_components/src/axi_stream_master.vhd +++ /dev/null @@ -1,174 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -context work.vunit_context; -context work.com_context; -use work.stream_master_pkg.all; -use work.axi_stream_pkg.all; -use work.queue_pkg.all; -use work.sync_pkg.all; - -entity axi_stream_master is - generic ( - master : axi_stream_master_t; - drive_invalid : boolean := true; - drive_invalid_val : std_logic := 'X'; - drive_invalid_val_user : std_logic := '0' - ); - port ( - aclk : in std_logic; - areset_n : in std_logic := '1'; - tvalid : out std_logic := '0'; - tready : in std_logic := '1'; - tdata : out std_logic_vector(data_length(master)-1 downto 0) := (others => '0'); - tlast : out std_logic := '0'; - tkeep : out std_logic_vector(data_length(master)/8-1 downto 0) := (others => '0'); - tstrb : out std_logic_vector(data_length(master)/8-1 downto 0) := (others => '0'); - tid : out std_logic_vector(id_length(master)-1 downto 0) := (others => '0'); - tdest : out std_logic_vector(dest_length(master)-1 downto 0) := (others => '0'); - tuser : out std_logic_vector(user_length(master)-1 downto 0) := (others => '0') - ); -end entity; - -architecture a of axi_stream_master is - - constant notify_request_msg : msg_type_t := new_msg_type("notify request"); - constant message_queue : queue_t := new_queue; - signal notify_bus_process_done : std_logic := '0'; - -begin - - main : process - variable request_msg : msg_t; - variable notify_msg : msg_t; - variable msg_type : msg_type_t; - begin - receive(net, master.p_actor, request_msg); - msg_type := message_type(request_msg); - - if msg_type = stream_push_msg or msg_type = push_axi_stream_msg then - push(message_queue, request_msg); - elsif msg_type = wait_for_time_msg then - push(message_queue, request_msg); - elsif msg_type = wait_until_idle_msg then - notify_msg := new_msg(notify_request_msg); - push(message_queue, notify_msg); - wait on notify_bus_process_done until is_empty(message_queue); - handle_wait_until_idle(net, msg_type, request_msg); - else - unexpected_msg_type(msg_type); - end if; - end process; - - bus_process : process - variable msg : msg_t; - variable msg_type : msg_type_t; - begin - if drive_invalid then - tdata <= (others => drive_invalid_val); - tkeep <= (others => drive_invalid_val); - tstrb <= (others => drive_invalid_val); - tid <= (others => drive_invalid_val); - tdest <= (others => drive_invalid_val); - tuser <= (others => drive_invalid_val_user); - end if; - - -- Wait for messages to arrive on the queue, posted by the process above - wait until rising_edge(aclk) and (not is_empty(message_queue) or areset_n = '0'); - - if (areset_n = '0') then - tvalid <= '0'; - else - while not is_empty(message_queue) loop - msg := pop(message_queue); - msg_type := message_type(msg); - - if msg_type = wait_for_time_msg then - handle_sync_message(net, msg_type, msg); - -- Re-align with the clock when a wait for time message was handled, because this breaks edge alignment. - wait until rising_edge(aclk); - elsif msg_type = notify_request_msg then - -- Ignore this message, but expect it - elsif msg_type = stream_push_msg or msg_type = push_axi_stream_msg then - tvalid <= '1'; - tdata <= pop_std_ulogic_vector(msg); - if msg_type = push_axi_stream_msg then - tlast <= pop_std_ulogic(msg); - tkeep <= pop_std_ulogic_vector(msg); - tstrb <= pop_std_ulogic_vector(msg); - tid <= pop_std_ulogic_vector(msg); - tdest <= pop_std_ulogic_vector(msg); - tuser <= pop_std_ulogic_vector(msg); - else - if pop_boolean(msg) then - tlast <= '1'; - else - tlast <= '0'; - end if; - tkeep <= (others => '1'); - tstrb <= (others => '1'); - tid <= (others => '0'); - tdest <= (others => '0'); - tuser <= (others => '0'); - end if; - wait until ((tvalid and tready) = '1' or areset_n = '0') and rising_edge(aclk); - tvalid <= '0'; - tlast <= '0'; - else - unexpected_msg_type(msg_type); - end if; - - delete(msg); - end loop; - - notify_bus_process_done <= '1'; - wait until notify_bus_process_done = '1'; - notify_bus_process_done <= '0'; - end if; - end process; - - axi_stream_monitor_generate : if master.p_monitor /= null_axi_stream_monitor generate - axi_stream_monitor_inst : entity work.axi_stream_monitor - generic map( - monitor => master.p_monitor - ) - port map( - aclk => aclk, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - end generate axi_stream_monitor_generate; - - axi_stream_protocol_checker_generate : if master.p_protocol_checker /= null_axi_stream_protocol_checker generate - axi_stream_protocol_checker_inst: entity work.axi_stream_protocol_checker - generic map ( - protocol_checker => master.p_protocol_checker) - port map ( - aclk => aclk, - areset_n => areset_n, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - end generate axi_stream_protocol_checker_generate; - -end architecture; \ No newline at end of file diff --git a/vunit/vhdl/verification_components/src/axi_stream_monitor.vhd b/vunit/vhdl/verification_components/src/axi_stream_monitor.vhd deleted file mode 100644 index 35e9622bc..000000000 --- a/vunit/vhdl/verification_components/src/axi_stream_monitor.vhd +++ /dev/null @@ -1,83 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -context work.vunit_context; -context work.com_context; -use work.axi_stream_pkg.all; - -entity axi_stream_monitor is - generic ( - monitor : axi_stream_monitor_t); - port ( - aclk : in std_logic; - tvalid : in std_logic; - tready : in std_logic := '1'; - tdata : in std_logic_vector(data_length(monitor) - 1 downto 0); - tlast : in std_logic := '1'; - tkeep : in std_logic_vector(data_length(monitor)/8-1 downto 0) := (others => '0'); - tstrb : in std_logic_vector(data_length(monitor)/8-1 downto 0) := (others => '0'); - tid : in std_logic_vector(id_length(monitor)-1 downto 0) := (others => '0'); - tdest : in std_logic_vector(dest_length(monitor)-1 downto 0) := (others => '0'); - tuser : in std_logic_vector(user_length(monitor)-1 downto 0) := (others => '0') - ); -end entity; - -architecture a of axi_stream_monitor is -begin - main : process - variable msg : msg_t; - variable axi_stream_transaction : axi_stream_transaction_t( - tdata(tdata'range), - tkeep(tkeep'range), - tstrb(tstrb'range), - tid(tid'range), - tdest(tdest'range), - tuser(tuser'range) - ); - begin - wait until (tvalid and tready) = '1' and rising_edge(aclk); - - if is_visible(monitor.p_logger, debug) then - debug(monitor.p_logger, "tdata: " & to_nibble_string(tdata) & " (" & to_integer_string(tdata) & ")" & ", tlast: " & to_string(tlast)); - end if; - - axi_stream_transaction := ( - tdata => tdata, - tlast => tlast = '1', - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - - msg := new_axi_stream_transaction_msg(axi_stream_transaction); - publish(net, monitor.p_actor, msg); - end process; - - axi_stream_protocol_checker_generate : if monitor.p_protocol_checker /= null_axi_stream_protocol_checker generate - axi_stream_protocol_checker_inst: entity work.axi_stream_protocol_checker - generic map ( - protocol_checker => monitor.p_protocol_checker) - port map ( - aclk => aclk, - areset_n => open, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - end generate axi_stream_protocol_checker_generate; - -end architecture; diff --git a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd deleted file mode 100644 index d03f8ca0b..000000000 --- a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd +++ /dev/null @@ -1,775 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -use work.logger_pkg.all; -use work.checker_pkg.all; -use work.check_pkg.all; -use work.stream_master_pkg.all; -use work.stream_slave_pkg.all; -use work.sync_pkg.all; -context work.vunit_context; -context work.com_context; -context work.data_types_context; - -package axi_stream_pkg is - - type axi_stream_component_type_t is (null_component, default_component, custom_component); - - type axi_stream_protocol_checker_t is record - p_type : axi_stream_component_type_t; - p_actor : actor_t; - p_data_length : natural; - p_id_length : natural; - p_dest_length : natural; - p_user_length : natural; - p_logger : logger_t; - p_max_waits : natural; - end record; - - constant null_axi_stream_protocol_checker : axi_stream_protocol_checker_t := ( - p_type => null_component, - p_actor => null_actor, - p_data_length => 0, - p_id_length => 0, - p_dest_length => 0, - p_user_length => 0, - p_logger => null_logger, - p_max_waits => 0 - ); - - -- The default protocol checker is used to specify that the checker - -- configuration is defined by the parent component into which the checker is - -- instantiated. - constant default_axi_stream_protocol_checker : axi_stream_protocol_checker_t := ( - p_type => default_component, - p_actor => null_actor, - p_data_length => 0, - p_id_length => 0, - p_dest_length => 0, - p_user_length => 0, - p_logger => null_logger, - p_max_waits => 0 - ); - - type axi_stream_monitor_t is record - p_type : axi_stream_component_type_t; - p_actor : actor_t; - p_data_length : natural; - p_id_length : natural; - p_dest_length : natural; - p_user_length : natural; - p_logger : logger_t; - p_protocol_checker : axi_stream_protocol_checker_t; - end record; - - constant null_axi_stream_monitor : axi_stream_monitor_t := ( - p_type => null_component, - p_actor => null_actor, - p_data_length => 0, - p_id_length => 0, - p_dest_length => 0, - p_user_length => 0, - p_logger => null_logger, - p_protocol_checker => null_axi_stream_protocol_checker - ); - - -- The default monitor is used to specify that the monitor - -- configuration is defined by the parent component into which the monitor is - -- instantiated. - constant default_axi_stream_monitor : axi_stream_monitor_t := ( - p_type => default_component, - p_actor => null_actor, - p_data_length => 0, - p_id_length => 0, - p_dest_length => 0, - p_user_length => 0, - p_logger => null_logger, - p_protocol_checker => null_axi_stream_protocol_checker - ); - - type axi_stream_master_t is record - p_actor : actor_t; - p_data_length : natural; - p_id_length : natural; - p_dest_length : natural; - p_user_length : natural; - p_logger : logger_t; - p_monitor : axi_stream_monitor_t; - p_protocol_checker : axi_stream_protocol_checker_t; - end record; - - type axi_stream_slave_t is record - p_actor : actor_t; - p_data_length : natural; - p_id_length : natural; - p_dest_length : natural; - p_user_length : natural; - p_logger : logger_t; - p_monitor : axi_stream_monitor_t; - p_protocol_checker : axi_stream_protocol_checker_t; - end record; - - constant axi_stream_logger : logger_t := get_logger("vunit_lib:axi_stream_pkg"); - constant axi_stream_checker : checker_t := new_checker(axi_stream_logger); - - impure function new_axi_stream_master( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_master_t; - - impure function new_axi_stream_slave( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_slave_t; - - impure function new_axi_stream_monitor( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_monitor_t; - - impure function new_axi_stream_protocol_checker( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - max_waits : natural := 16 - ) return axi_stream_protocol_checker_t; - - impure function data_length(master : axi_stream_master_t) return natural; - impure function data_length(slave : axi_stream_slave_t) return natural; - impure function data_length(monitor : axi_stream_monitor_t) return natural; - impure function data_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function id_length(master : axi_stream_master_t) return natural; - impure function id_length(slave : axi_stream_slave_t) return natural; - impure function id_length(monitor : axi_stream_monitor_t) return natural; - impure function id_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function dest_length(master : axi_stream_master_t) return natural; - impure function dest_length(slave : axi_stream_slave_t) return natural; - impure function dest_length(monitor : axi_stream_monitor_t) return natural; - impure function dest_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function user_length(master : axi_stream_master_t) return natural; - impure function user_length(slave : axi_stream_slave_t) return natural; - impure function user_length(monitor : axi_stream_monitor_t) return natural; - impure function user_length(protocol_checker : axi_stream_protocol_checker_t) return natural; - impure function as_stream(master : axi_stream_master_t) return stream_master_t; - impure function as_stream(slave : axi_stream_slave_t) return stream_slave_t; - impure function as_sync(master : axi_stream_master_t) return sync_handle_t; - impure function as_sync(slave : axi_stream_slave_t) return sync_handle_t; - - constant push_axi_stream_msg : msg_type_t := new_msg_type("push axi stream"); - constant pop_axi_stream_msg : msg_type_t := new_msg_type("pop axi stream"); - constant check_axi_stream_msg : msg_type_t := new_msg_type("check axi stream"); - constant axi_stream_transaction_msg : msg_type_t := new_msg_type("axi stream transaction"); - - alias axi_stream_reference_t is msg_t; - - procedure push_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_master_t; - tdata : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := "" - ); - - -- Blocking: pop a value from the axi stream - procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector - ); - - procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic - ); - - -- Non-blocking: pop a value from the axi stream to be read in the future - procedure pop_axi_stream(signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable reference : inout axi_stream_reference_t); - - -- Blocking: Wait for reply to non-blocking pop - procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector - ); - - procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic - ); - - -- Blocking: read axi stream and check result against expected value - procedure check_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - expected : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := ""; - msg : string := ""; - blocking : boolean := true - ); - - type axi_stream_transaction_t is record - tdata : std_logic_vector; - tlast : boolean; - tkeep : std_logic_vector; - tstrb : std_logic_vector; - tid : std_logic_vector; - tdest : std_logic_vector; - tuser : std_logic_vector; - end record; - - procedure push_axi_stream_transaction(msg : msg_t; axi_stream_transaction : axi_stream_transaction_t); - procedure pop_axi_stream_transaction( - constant msg : in msg_t; - variable axi_stream_transaction : out axi_stream_transaction_t - ); - - impure function new_axi_stream_transaction_msg( - axi_stream_transaction : axi_stream_transaction_t - ) return msg_t; - - procedure handle_axi_stream_transaction( - variable msg_type : inout msg_type_t; - variable msg : inout msg_t; - variable axi_transaction : out axi_stream_transaction_t); - -end package; - -package body axi_stream_pkg is - - impure function get_valid_monitor( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t; - monitor : axi_stream_monitor_t; - parent_component : string - ) return axi_stream_monitor_t is - begin - if monitor = null_axi_stream_monitor then - return monitor; - elsif monitor = default_axi_stream_monitor then - check(actor /= null_actor, "A valid actor is needed to create a default monitor"); - return new_axi_stream_monitor(data_length, id_length, dest_length, user_length, logger, actor); - else - check_equal(axi_stream_checker, monitor.p_data_length, data_length, "Data length of monitor doesn't match that of the " & parent_component); - check_equal(axi_stream_checker, monitor.p_id_length, id_length, "ID length of monitor doesn't match that of the " & parent_component); - check_equal(axi_stream_checker, monitor.p_dest_length, dest_length, "Dest length of monitor doesn't match that of the " & parent_component); - check_equal(axi_stream_checker, monitor.p_user_length, user_length, "User length of monitor doesn't match that of the " & parent_component); - return monitor; - end if; - end; - - impure function get_valid_protocol_checker( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t; - actor : actor_t; - protocol_checker : axi_stream_protocol_checker_t; - parent_component : string - ) return axi_stream_protocol_checker_t is - begin - if protocol_checker = null_axi_stream_protocol_checker then - return protocol_checker; - elsif protocol_checker = default_axi_stream_protocol_checker then - return new_axi_stream_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor); - else - check_equal(axi_stream_checker, protocol_checker.p_data_length, data_length, "Data length of protocol checker doesn't match that of the " & parent_component); - check_equal(axi_stream_checker, protocol_checker.p_id_length, id_length, "ID length of monitor doesn't match that of the " & parent_component); - check_equal(axi_stream_checker, protocol_checker.p_dest_length, dest_length, "Dest length of monitor doesn't match that of the " & parent_component); - check_equal(axi_stream_checker, protocol_checker.p_user_length, user_length, "User length of monitor doesn't match that of the " & parent_component); - return protocol_checker; - end if; - end; - - impure function new_axi_stream_master( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_master_t is - variable p_actor : actor_t; - variable p_monitor : axi_stream_monitor_t; - variable p_protocol_checker : axi_stream_protocol_checker_t; - begin - p_monitor := get_valid_monitor(data_length, id_length, dest_length, user_length, logger, actor, monitor, "master"); - p_actor := actor when actor /= null_actor else new_actor; - p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, protocol_checker, "master"); - - return (p_actor => p_actor, - p_data_length => data_length, - p_id_length => id_length, - p_dest_length => dest_length, - p_user_length => user_length, - p_logger => logger, - p_monitor => p_monitor, - p_protocol_checker => p_protocol_checker); - end; - - impure function new_axi_stream_slave( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - monitor : axi_stream_monitor_t := null_axi_stream_monitor; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_slave_t is - variable p_actor : actor_t; - variable p_monitor : axi_stream_monitor_t; - variable p_protocol_checker : axi_stream_protocol_checker_t; - begin - p_monitor := get_valid_monitor(data_length, id_length, dest_length, user_length, logger, actor, monitor, "slave"); - p_actor := actor when actor /= null_actor else new_actor; - p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, protocol_checker, "slave"); - - return (p_actor => new_actor, - p_data_length => data_length, - p_id_length => id_length, - p_dest_length => dest_length, - p_user_length => user_length, - p_logger => logger, - p_monitor => p_monitor, - p_protocol_checker => p_protocol_checker); - end; - - impure function new_axi_stream_monitor( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t; - protocol_checker : axi_stream_protocol_checker_t := null_axi_stream_protocol_checker - ) return axi_stream_monitor_t is - constant p_protocol_checker : axi_stream_protocol_checker_t := get_valid_protocol_checker( - data_length, id_length, dest_length, user_length, logger, actor, protocol_checker, "monitor" - ); - begin - return ( - p_type => custom_component, - p_actor => actor, - p_data_length => data_length, - p_id_length => id_length, - p_dest_length => dest_length, - p_user_length => user_length, - p_logger => logger, - p_protocol_checker => p_protocol_checker); - end; - - impure function new_axi_stream_protocol_checker( - data_length : natural; - id_length : natural := 0; - dest_length : natural := 0; - user_length : natural := 0; - logger : logger_t := axi_stream_logger; - actor : actor_t := null_actor; - max_waits : natural := 16 - ) return axi_stream_protocol_checker_t is - begin - return ( - p_type => custom_component, - p_actor => actor, - p_data_length => data_length, - p_id_length => id_length, - p_dest_length => dest_length, - p_user_length => user_length, - p_logger => logger, - p_max_waits => max_waits); - end; - - impure function data_length(master : axi_stream_master_t) return natural is - begin - return master.p_data_length; - end; - - impure function data_length(slave : axi_stream_slave_t) return natural is - begin - return slave.p_data_length; - end; - - impure function data_length(monitor : axi_stream_monitor_t) return natural is - begin - return monitor.p_data_length; - end; - - impure function data_length(protocol_checker : axi_stream_protocol_checker_t) return natural is - begin - return protocol_checker.p_data_length; - end; - - impure function id_length(master : axi_stream_master_t) return natural is - begin - return master.p_id_length; - end; - - impure function id_length(slave : axi_stream_slave_t) return natural is - begin - return slave.p_id_length; - end; - - impure function id_length(monitor : axi_stream_monitor_t) return natural is - begin - return monitor.p_id_length; - end; - - impure function id_length(protocol_checker: axi_stream_protocol_checker_t) return natural is - begin - return protocol_checker.p_id_length; - end; - - impure function dest_length(master : axi_stream_master_t) return natural is - begin - return master.p_dest_length; - end; - - impure function dest_length(slave: axi_stream_slave_t) return natural is - begin - return slave.p_dest_length; - end; - - impure function dest_length(monitor : axi_stream_monitor_t) return natural is - begin - return monitor.p_dest_length; - end; - - impure function dest_length(protocol_checker : axi_stream_protocol_checker_t) return natural is - begin - return protocol_checker.p_dest_length; - end; - - impure function user_length(master : axi_stream_master_t) return natural is - begin - return master.p_user_length; - end; - - impure function user_length(slave : axi_stream_slave_t) return natural is - begin - return slave.p_user_length; - end; - - impure function user_length(monitor : axi_stream_monitor_t) return natural is - begin - return monitor.p_user_length; - end; - - impure function user_length(protocol_checker : axi_stream_protocol_checker_t) return natural is - begin - return protocol_checker.p_user_length; - end; - - impure function as_stream(master : axi_stream_master_t) return stream_master_t is - begin - return (p_actor => master.p_actor); - end; - - impure function as_stream(slave : axi_stream_slave_t) return stream_slave_t is - begin - return (p_actor => slave.p_actor); - end; - - impure function as_sync(master : axi_stream_master_t) return sync_handle_t is - begin - return master.p_actor; - end; - - impure function as_sync(slave : axi_stream_slave_t) return sync_handle_t is - begin - return slave.p_actor; - end; - - procedure push_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_master_t; - tdata : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := "" - ) is - variable msg : msg_t := new_msg(push_axi_stream_msg); - variable normalized_data : std_logic_vector(data_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_keep : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); - variable normalized_strb : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); - variable normalized_id : std_logic_vector(id_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_dest : std_logic_vector(dest_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_user : std_logic_vector(user_length(axi_stream)-1 downto 0) := (others => '0'); - begin - normalized_data(tdata'length-1 downto 0) := tdata; - push_std_ulogic_vector(msg, normalized_data); - push_std_ulogic(msg, tlast); - normalized_keep(tkeep'length-1 downto 0) := tkeep; - push_std_ulogic_vector(msg, normalized_keep); - normalized_strb(tstrb'length-1 downto 0) := tstrb; - push_std_ulogic_vector(msg, normalized_strb); - normalized_id(tid'length-1 downto 0) := tid; - push_std_ulogic_vector(msg, normalized_id); - normalized_dest(tdest'length-1 downto 0) := tdest; - push_std_ulogic_vector(msg, normalized_dest); - normalized_user(tuser'length-1 downto 0) := tuser; - push_std_ulogic_vector(msg, normalized_user); - send(net, axi_stream.p_actor, msg); - end; - - procedure pop_axi_stream(signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable reference : inout axi_stream_reference_t) is - begin - reference := new_msg(pop_axi_stream_msg); - send(net, axi_stream.p_actor, reference); - end; - - procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector - ) is - variable reply_msg : msg_t; - begin - receive_reply(net, reference, reply_msg); - tdata := pop_std_ulogic_vector(reply_msg); - if pop_boolean(reply_msg) then - tlast := '1'; - else - tlast := '0'; - end if; - tkeep := pop_std_ulogic_vector(reply_msg); - tstrb := pop_std_ulogic_vector(reply_msg); - tid := pop_std_ulogic_vector(reply_msg); - tdest := pop_std_ulogic_vector(reply_msg); - tuser := pop_std_ulogic_vector(reply_msg); - delete(reference); - delete(reply_msg); - end; - - procedure await_pop_axi_stream_reply( - signal net : inout network_t; - variable reference : inout axi_stream_reference_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic - ) is - variable reply_msg : msg_t; - begin - receive_reply(net, reference, reply_msg); - tdata := pop_std_ulogic_vector(reply_msg); - if pop_boolean(reply_msg) then - tlast := '1'; - else - tlast := '0'; - end if; - delete(reference); - delete(reply_msg); - end; - - procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic; - variable tkeep : out std_logic_vector; - variable tstrb : out std_logic_vector; - variable tid : out std_logic_vector; - variable tdest : out std_logic_vector; - variable tuser : out std_logic_vector - ) is - variable reference : axi_stream_reference_t; - begin - pop_axi_stream(net, axi_stream, reference); - await_pop_axi_stream_reply(net, reference, tdata, tlast, tkeep, tstrb, tid, tdest, tuser); - end; - - procedure pop_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - variable tdata : out std_logic_vector; - variable tlast : out std_logic - ) is - variable reference : axi_stream_reference_t; - begin - pop_axi_stream(net, axi_stream, reference); - await_pop_axi_stream_reply(net, reference, tdata, tlast); - end; - - procedure check_axi_stream( - signal net : inout network_t; - axi_stream : axi_stream_slave_t; - expected : std_logic_vector; - tlast : std_logic := '1'; - tkeep : std_logic_vector := ""; - tstrb : std_logic_vector := ""; - tid : std_logic_vector := ""; - tdest : std_logic_vector := ""; - tuser : std_logic_vector := ""; - msg : string := ""; - blocking : boolean := true - ) is - variable got_tdata : std_logic_vector(data_length(axi_stream)-1 downto 0); - variable got_tlast : std_logic; - variable got_tkeep : std_logic_vector(data_length(axi_stream)/8-1 downto 0); - variable got_tstrb : std_logic_vector(data_length(axi_stream)/8-1 downto 0); - variable got_tid : std_logic_vector(id_length(axi_stream)-1 downto 0); - variable got_tdest : std_logic_vector(dest_length(axi_stream)-1 downto 0); - variable got_tuser : std_logic_vector(user_length(axi_stream)-1 downto 0); - variable check_msg : msg_t := new_msg(check_axi_stream_msg); - variable normalized_data : std_logic_vector(data_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_keep : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); - variable normalized_strb : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); - variable normalized_id : std_logic_vector(id_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_dest : std_logic_vector(dest_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_user : std_logic_vector(user_length(axi_stream)-1 downto 0) := (others => '0'); - begin - if blocking then - pop_axi_stream(net, axi_stream, got_tdata, got_tlast, got_tkeep, got_tstrb, got_tid, got_tdest, got_tuser); - check_equal(got_tdata, expected, "TDATA mismatch, " & msg); - check_equal(got_tlast, tlast, "TLAST mismatch, " & msg); - if tkeep'length > 0 then - check_equal(got_tkeep, tkeep, "TKEEP mismatch, " & msg); - end if; - if tstrb'length > 0 then - check_equal(got_tstrb, tstrb, "TSTRB mismatch, " & msg); - end if; - if tid'length > 0 then - check_equal(got_tid, tid, "TID mismatch, " & msg); - end if; - if tdest'length > 0 then - check_equal(got_tdest, tdest, "TDEST mismatch, " & msg); - end if; - if tuser'length > 0 then - check_equal(got_tuser, tuser, "TUSER mismatch, " & msg); - end if; - else - push_string(check_msg, msg); - normalized_data(expected'length-1 downto 0) := expected; - push_std_ulogic_vector(check_msg, normalized_data); - push_std_ulogic(check_msg, tlast); - normalized_keep(tkeep'length-1 downto 0) := tkeep; - push_std_ulogic_vector(check_msg, normalized_keep); - normalized_strb(tstrb'length-1 downto 0) := tstrb; - push_std_ulogic_vector(check_msg, normalized_strb); - normalized_id(tid'length-1 downto 0) := tid; - push_std_ulogic_vector(check_msg, normalized_id); - normalized_dest(tdest'length-1 downto 0) := tdest; - push_std_ulogic_vector(check_msg, normalized_dest); - normalized_user(tuser'length-1 downto 0) := tuser; - push_std_ulogic_vector(check_msg, normalized_user); - send(net, axi_stream.p_actor, check_msg); - end if; - end procedure; - - procedure push_axi_stream_transaction(msg : msg_t; axi_stream_transaction : axi_stream_transaction_t) is - begin - push_std_ulogic_vector(msg, axi_stream_transaction.tdata); - push_boolean(msg, axi_stream_transaction.tlast); - push_std_ulogic_vector(msg, axi_stream_transaction.tkeep); - push_std_ulogic_vector(msg, axi_stream_transaction.tstrb); - push_std_ulogic_vector(msg, axi_stream_transaction.tid); - push_std_ulogic_vector(msg, axi_stream_transaction.tdest); - push_std_ulogic_vector(msg, axi_stream_transaction.tuser); - end; - - procedure pop_axi_stream_transaction( - constant msg : in msg_t; - variable axi_stream_transaction : out axi_stream_transaction_t - ) is - begin - axi_stream_transaction.tdata := pop_std_ulogic_vector(msg); - axi_stream_transaction.tlast := pop_boolean(msg); - axi_stream_transaction.tkeep := pop_std_ulogic_vector(msg); - axi_stream_transaction.tstrb := pop_std_ulogic_vector(msg); - axi_stream_transaction.tid := pop_std_ulogic_vector(msg); - axi_stream_transaction.tdest := pop_std_ulogic_vector(msg); - axi_stream_transaction.tuser := pop_std_ulogic_vector(msg); - end; - - impure function new_axi_stream_transaction_msg( - axi_stream_transaction : axi_stream_transaction_t - ) return msg_t is - variable msg : msg_t; - begin - msg := new_msg(axi_stream_transaction_msg); - push_axi_stream_transaction(msg, axi_stream_transaction); - return msg; - end; - - procedure handle_axi_stream_transaction( - variable msg_type : inout msg_type_t; - variable msg : inout msg_t; - variable axi_transaction : out axi_stream_transaction_t) is - begin - if msg_type = axi_stream_transaction_msg then - handle_message(msg_type); - - pop_axi_stream_transaction(msg, axi_transaction); - end if; - end; - -end package body; diff --git a/vunit/vhdl/verification_components/src/axi_stream_protocol_checker.vhd b/vunit/vhdl/verification_components/src/axi_stream_protocol_checker.vhd deleted file mode 100644 index 7b237cf43..000000000 --- a/vunit/vhdl/verification_components/src/axi_stream_protocol_checker.vhd +++ /dev/null @@ -1,263 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std_unsigned.all; - -use std.textio.all; - -context work.vunit_context; -context work.com_context; -use work.axi_stream_pkg.all; - -entity axi_stream_protocol_checker is - generic ( - protocol_checker : axi_stream_protocol_checker_t); - port ( - aclk : in std_logic; - areset_n : in std_logic := '1'; - tvalid : in std_logic; - tready : in std_logic := '1'; - tdata : in std_logic_vector(data_length(protocol_checker) - 1 downto 0); - tlast : in std_logic := '1'; - tkeep : in std_logic_vector(data_length(protocol_checker)/8-1 downto 0) := (others => '0'); - tstrb : in std_logic_vector(data_length(protocol_checker)/8-1 downto 0) := (others => '0'); - tid : in std_logic_vector(id_length(protocol_checker)-1 downto 0) := (others => '0'); - tdest : in std_logic_vector(dest_length(protocol_checker)-1 downto 0) := (others => '0'); - tuser : in std_logic_vector(user_length(protocol_checker)-1 downto 0) := (others => '0') - ); -end entity; - -architecture a of axi_stream_protocol_checker is - constant rule1_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 1"); - constant rule2_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 2"); - constant rule3_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 3"); - constant rule4_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 4"); - constant rule5_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 5"); - constant rule6_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 6"); - constant rule7_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 7"); - constant rule8_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 8"); - constant rule9_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 9"); - constant rule10_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 10"); - constant rule11_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 11"); - constant rule12_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 12"); - constant rule13_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 13"); - constant rule14_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 14"); - constant rule15_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 15"); - constant rule16_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 16"); - constant rule17_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 17"); - constant rule18_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 18"); - constant rule19_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 19"); - constant rule20_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 20"); - constant rule21_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 21"); - constant rule22_checker : checker_t := new_checker(get_name(protocol_checker.p_logger) & ":rule 22"); - - signal handshake_is_not_x : std_logic; - signal enable_rule1_check : std_logic; - signal enable_rule2_check : std_logic; - signal enable_rule11_check : std_logic; - signal enable_rule12_check : std_logic; - signal enable_rule13_check : std_logic; - signal enable_rule14_check : std_logic; - signal enable_rule15_check : std_logic; - signal rule20_check_value : std_logic; - - signal areset_n_d : std_logic := '0'; - signal areset_rose : std_logic; - signal not_tvalid : std_logic; -begin - handshake_is_not_x <= '1' when not is_x(tvalid) and not is_x(tready) else '0'; - - -- AXI4STREAM_ERRM_TDATA_STABLE TDATA remains stable when TVALID is asserted, - -- and TREADY is LOW - enable_rule1_check <= '1' when (handshake_is_not_x = '1') and not is_x(tdata) else '0'; - check_stable( - rule1_checker, aclk, enable_rule1_check, tvalid, tready, tdata, - result("for tdata while waiting for tready")); - - -- AXI4STREAM_ERRM_TLAST_STABLE TLAST remains stable when TVALID is asserted, - -- and TREADY is LOW - enable_rule2_check <= '1' when (handshake_is_not_x = '1') and not is_x(tlast) else '0'; - check_stable( - rule2_checker, aclk, enable_rule2_check, tvalid, tready, tlast, - result("for tlast while waiting for tready")); - - -- AXI4STREAM_ERRM_TVALID_STABLE When TVALID is asserted, then it must remain - -- asserted until TREADY is HIGH - check_stable( - rule3_checker, aclk, handshake_is_not_x, tvalid, tready, tvalid, - result("for tvalid while waiting for tready")); - - -- AXI4STREAM_RECS_TREADY_MAX_WAIT Recommended that TREADY is asserted within - -- MAXWAITS cycles of TVALID being asserted - process - variable n_clock_cycles : natural; - begin - wait until rising_edge(aclk) and (to_x01(tvalid) = '1'); - while not tready loop - wait until rising_edge(aclk); - n_clock_cycles := n_clock_cycles + 1; - end loop; - check(rule4_checker, - n_clock_cycles <= protocol_checker.p_max_waits, - result("for performance - tready active " & to_string(n_clock_cycles) & - " clock cycles after tvalid. Expected <= " & to_string(protocol_checker.p_max_waits) & " clock cycles."), - level => warning); - end process; - - -- AXI4STREAM_ERRM_TDATA_X A value of X on TDATA is not permitted when TVALID - -- is HIGH - check_not_unknown(rule5_checker, aclk, tvalid, tdata, result("for tdata when tvalid is high")); - - -- AXI4STREAM_ERRM_TLAST_X A value of X on TLAST is not permitted when TVALID - -- is HIGH - check_not_unknown(rule6_checker, aclk, tvalid, tlast, result("for tlast when tvalid is high")); - - -- AXI4STREAM_ERRM_TVALID_X A value of X on TVALID is not permitted when not - -- in reset - check_not_unknown(rule7_checker, aclk, areset_n, tvalid, result("for tvalid when not in reset")); - - -- AXI4STREAM_ERRS_TREADY_X A value of X on TREADY is not permitted when not - -- in reset - check_not_unknown(rule8_checker, aclk, areset_n, tready, result("for tready when not in reset")); - - -- AXI4STREAM_ERRM_STREAM_ALL_DONE_EOS At the end of simulation, all streams have had - -- their corresponding TLAST transfer - check_complete_packets : block is - constant active_streams : integer_array_t := new_1d(length => 2 ** tid'length); - begin - assert tid'length <= 8 report "tid must not be more than 8 bits (maximum recommendation)" severity failure; - - track_streams : process - variable value : natural; - begin - wait until rising_edge(aclk) and (to_x01(tvalid) = '1'); - if tid'length = 0 then - value := 1 when to_x01(tlast) = '0' else 0; - set(active_streams, 0, value); - elsif not is_x(tid) then - value := 1 when to_x01(tlast) = '0' else 0; - set(active_streams, to_integer(tid), value); - end if; - end process; - - check_that_streams_have_ended : process - variable incomplete_streams : line; - begin - lock_entry(runner, test_runner_cleanup); - wait_until(runner, test_runner_cleanup); - - if tid'length = 0 then - check(rule9_checker, get(active_streams, 0) = 0, result("for packet completion.")); - else - for i in 0 to 2 * tid'length - 1 loop - if get(active_streams, i) /= 0 then - if incomplete_streams = null then - write(incomplete_streams, to_string(i)); - else - write(incomplete_streams, ", " & to_string(i)); - end if; - end if; - end loop; - - if incomplete_streams /= null then - check_failed(rule9_checker, result("for packet completion for the following streams: " & - incomplete_streams.all & ".")); - else - check_passed(rule9_checker, result("for packet completion.")); - end if; - end if; - - unlock_entry(runner, test_runner_cleanup); - wait; - end process; - end block; - - -- AXI4STREAM_ERRM_TUSER_X A value of X on TUSER is not permitted when not in reset - -- is HIGH - check_not_unknown(rule10_checker, aclk, areset_n, tuser, result("for tuser when areset_n is high")); - - -- AXI4STREAM_ERRM_TUSER_STABLE TUSER payload signals must remain constant while TVALID is asserted, - -- and TREADY is de-asserted - enable_rule11_check <= '1' when (handshake_is_not_x = '1') and not is_x(tuser) else '0'; - check_stable( - rule11_checker, aclk, enable_rule11_check, tvalid, tready, tuser, - result("for tuser while waiting for tready")); - - -- AXI4STREAM_ERRM_TID_STABLE TID remains stable when TVALID is asserted, - -- and TREADY is LOW - enable_rule12_check <= '1' when (handshake_is_not_x = '1') and not is_x(tid) else '0'; - check_stable( - rule12_checker, aclk, enable_rule12_check, tvalid, tready, tid, - result("for tid while waiting for tready")); - - -- AXI4STREAM_ERRM_TDEST_STABLE TDEST remains stable when TVALID is asserted, - -- and TREADY is LOW - enable_rule13_check <= '1' when (handshake_is_not_x = '1') and not is_x(tdest) else '0'; - check_stable( - rule13_checker, aclk, enable_rule13_check, tvalid, tready, tdest, - result("for tdest while waiting for tready")); - - -- AXI4STREAM_ERRM_TSTRB_STABLE TSTRB remains stable when TVALID is asserted, - -- and TREADY is LOW - enable_rule14_check <= '1' when (handshake_is_not_x = '1') and not is_x(tstrb) else '0'; - check_stable( - rule14_checker, aclk, enable_rule14_check, tvalid, tready, tstrb, - result("for tstrb while waiting for tready")); - - -- AXI4STREAM_ERRM_TKEEP_STABLE TKEEP remains stable when TVALID is asserted, - -- and TREADY is LOW - enable_rule15_check <= '1' when (handshake_is_not_x = '1') and not is_x(tkeep) else '0'; - check_stable( - rule15_checker, aclk, enable_rule15_check, tvalid, tready, tkeep, - result("for tkeep while waiting for tready")); - - -- AXI4STREAM_ERRM_TID_X A value of X on TID is not permitted when TVALID - -- is HIGH - check_not_unknown(rule16_checker, aclk, tvalid, tid, result("for tid when tvalid is high")); - - -- AXI4STREAM_ERRM_TDEST_X A value of X on TDEST is not permitted when TVALID - -- is HIGH - check_not_unknown(rule17_checker, aclk, tvalid, tdest, result("for tdest when tvalid is high")); - - -- AXI4STREAM_ERRM_TSTRB_X A value of X on TSTRB is not permitted when TVALID - -- is HIGH - check_not_unknown(rule18_checker, aclk, tvalid, tstrb, result("for tstrb when tvalid is high")); - - -- AXI4STREAM_ERRM_TKEEP_X A value of X on TKEEP is not permitted when TVALID - -- is HIGH - check_not_unknown(rule19_checker, aclk, tvalid, tkeep, result("for tkeep when tvalid is high")); - - -- AXI4STREAM_ERRM_TKEEP_TSTRB If TKEEP is de-asserted, then TSTRB must also be de-asserted - -- eschmidscs: Binding this to tvalid. ARM does not include that, but makes more sense this way? - rule20_check_value <= not(or(((not tkeep) and tstrb))); - check_true(rule20_checker, aclk, tvalid, rule20_check_value, result("for tstrb de-asserted when tkeep de-asserted")); - - -- AXI4STREAM_AUXM_TID_TDTEST_WIDTH The value of ID_WIDTH + DEST_WIDTH must not exceed 24 - -- eschmidscs: Must wait a short while to allow testing of the rule. - process - begin - wait for 1 ps; - check_true(rule21_checker, tid'length + tdest'length <= 24, result("for tid width and tdest width together must be less than 25")); - wait; - end process; - - -- AXI4STREAM_ERRM_TVALID_RESET TVALID is LOW for the first cycle after ARESETn goes HIGH - process (aclk) is - begin - if rising_edge(aclk) then - areset_n_d <= areset_n; - end if; - end process; - areset_rose <= areset_n and not areset_n_d; - not_tvalid <= not tvalid; - check_implication(rule22_checker, aclk, areset_n, areset_rose, not_tvalid, result("for tvalid de-asserted after reset release")); - - -- for * being DATA, KEEP, STRB, ID, DEST or USER - -- AXI4STREAM_ERRM_T*_TIEOFF T* must be stable while *_WIDTH has been set to zero - -- cannot be checked, vector has negative range -end architecture; diff --git a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd deleted file mode 100644 index 69a33a7ff..000000000 --- a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd +++ /dev/null @@ -1,181 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -context work.vunit_context; -context work.com_context; -use work.stream_slave_pkg.all; -use work.axi_stream_pkg.all; -use work.sync_pkg.all; -use work.string_ptr_pkg.all; - -entity axi_stream_slave is - generic ( - slave : axi_stream_slave_t); - port ( - aclk : in std_logic; - areset_n : in std_logic := '1'; - tvalid : in std_logic; - tready : out std_logic := '0'; - tdata : in std_logic_vector(data_length(slave)-1 downto 0); - tlast : in std_logic := '1'; - tkeep : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); - tstrb : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); - tid : in std_logic_vector(id_length(slave)-1 downto 0) := (others => '0'); - tdest : in std_logic_vector(dest_length(slave)-1 downto 0) := (others => '0'); - tuser : in std_logic_vector(user_length(slave)-1 downto 0) := (others => '0') - ); -end entity; - -architecture a of axi_stream_slave is - - constant notify_request_msg : msg_type_t := new_msg_type("notify request"); - constant message_queue : queue_t := new_queue; - signal notify_bus_process_done : std_logic := '0'; - -begin - - main : process - variable request_msg : msg_t; - variable notify_msg : msg_t; - variable msg_type : msg_type_t; - begin - receive(net, slave.p_actor, request_msg); - msg_type := message_type(request_msg); - - if msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg then - push(message_queue, request_msg); - elsif msg_type = check_axi_stream_msg then - push(message_queue, request_msg); - elsif msg_type = wait_for_time_msg then - push(message_queue, request_msg); - elsif msg_type = wait_until_idle_msg then - notify_msg := new_msg(notify_request_msg); - push(message_queue, notify_msg); - wait on notify_bus_process_done until is_empty(message_queue); - handle_wait_until_idle(net, msg_type, request_msg); - else - unexpected_msg_type(msg_type); - end if; - end process; - - bus_process : process - variable reply_msg, msg : msg_t; - variable msg_type : msg_type_t; - variable report_msg : string_ptr_t; - variable axi_stream_transaction : axi_stream_transaction_t( - tdata(tdata'range), - tkeep(tkeep'range), - tstrb(tstrb'range), - tid(tid'range), - tdest(tdest'range), - tuser(tuser'range) - ); - begin - -- Wait for messages to arrive on the queue, posted by the process above - wait until rising_edge(aclk) and (not is_empty(message_queue)); - - while not is_empty(message_queue) loop - msg := pop(message_queue); - msg_type := message_type(msg); - - if msg_type = wait_for_time_msg then - handle_sync_message(net, msg_type, msg); - wait until rising_edge(aclk); - elsif msg_type = notify_request_msg then - -- Ignore this message, but expect it - elsif msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg then - tready <= '1'; - wait until (tvalid and tready) = '1' and rising_edge(aclk); - tready <= '0'; - - axi_stream_transaction := ( - tdata => tdata, - tlast => tlast = '1', - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - - reply_msg := new_axi_stream_transaction_msg(axi_stream_transaction); - reply(net, msg, reply_msg); - elsif msg_type = check_axi_stream_msg then - tready <= '1'; - wait until (tvalid and tready) = '1' and rising_edge(aclk); - tready <= '0'; - - report_msg := new_string_ptr(pop_string(msg)); - check_equal(tdata, pop_std_ulogic_vector(msg), "TDATA mismatch, " & to_string(report_msg)); - check_equal(tlast, pop_std_ulogic(msg), "TLAST mismatch, " & to_string(report_msg)); - if tkeep'length > 0 then - check_equal(tkeep, pop_std_ulogic_vector(msg), "TKEEP mismatch, " & to_string(report_msg)); - end if; - if tstrb'length > 0 then - check_equal(tstrb, pop_std_ulogic_vector(msg), "TSTRB mismatch, " & to_string(report_msg)); - end if; - if tid'length > 0 then - check_equal(tid, pop_std_ulogic_vector(msg), "TID mismatch, " & to_string(report_msg)); - end if; - if tdest'length > 0 then - check_equal(tdest, pop_std_ulogic_vector(msg), "TDEST mismatch, " & to_string(report_msg)); - end if; - if tuser'length > 0 then - check_equal(tuser, pop_std_ulogic_vector(msg), "TUSER mismatch, " & to_string(report_msg)); - end if; - else - unexpected_msg_type(msg_type); - end if; - end loop; - - notify_bus_process_done <= '1'; - wait until notify_bus_process_done = '1'; - notify_bus_process_done <= '0'; - - end process; - - axi_stream_monitor_generate : if slave.p_monitor /= null_axi_stream_monitor generate - axi_stream_monitor_inst : entity work.axi_stream_monitor - generic map( - monitor => slave.p_monitor - ) - port map( - aclk => aclk, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - end generate axi_stream_monitor_generate; - - axi_stream_protocol_checker_generate : if slave.p_protocol_checker /= null_axi_stream_protocol_checker generate - axi_stream_protocol_checker_inst: entity work.axi_stream_protocol_checker - generic map ( - protocol_checker => slave.p_protocol_checker) - port map ( - aclk => aclk, - areset_n => areset_n, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - end generate axi_stream_protocol_checker_generate; - -end architecture; diff --git a/vunit/vhdl/verification_components/src/axi_write_slave.vhd b/vunit/vhdl/verification_components/src/axi_write_slave.vhd deleted file mode 100644 index 94a44f8f3..000000000 --- a/vunit/vhdl/verification_components/src/axi_write_slave.vhd +++ /dev/null @@ -1,264 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.axi_pkg.all; -use work.axi_slave_pkg.all; -use work.axi_slave_private_pkg.all; -use work.queue_pkg.all; -use work.memory_pkg.all; -use work.integer_vector_ptr_pkg.all; -use work.integer_vector_ptr_pool_pkg.all; -context work.com_context; - -entity axi_write_slave is - generic ( - axi_slave : axi_slave_t); - port ( - aclk : in std_logic; - - awvalid : in std_logic; - awready : out std_logic := '0'; - awid : in std_logic_vector; - awaddr : in std_logic_vector; - awlen : in std_logic_vector; - awsize : in std_logic_vector; - awburst : in axi_burst_type_t; - - wvalid : in std_logic; - wready : out std_logic := '0'; - wdata : in std_logic_vector; - wstrb : in std_logic_vector; - wlast : in std_logic; - - bvalid : out std_logic := '0'; - bready : in std_logic; - bid : out std_logic_vector; - bresp : out axi_resp_t - ); -end entity; - -architecture a of axi_write_slave is - shared variable self : axi_slave_private_t; - signal initialized : boolean := false; - - constant data_vector_length : natural := max_axi4_burst_length * wdata'length; - constant data_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool; - - type burst_data_t is record - length : natural; - address : integer_vector_ptr_t; - data : integer_vector_ptr_t; - end record; - - procedure push_burst_data(queue : queue_t; variable burst_data : inout burst_data_t) is - begin - push_integer(queue, burst_data.length); - push_integer_vector_ptr_ref(queue, burst_data.address); - push_integer_vector_ptr_ref(queue, burst_data.data); - end; - - impure function pop_burst_data(queue : queue_t) return burst_data_t is - variable burst_data : burst_data_t; - begin - burst_data.length := pop_integer(queue); - burst_data.address := pop_integer_vector_ptr_ref(queue); - burst_data.data := pop_integer_vector_ptr_ref(queue); - return burst_data; - end; - - impure function new_burst_data return burst_data_t is - begin - return (length => 0, - address => new_integer_vector_ptr(data_pool, min_length => data_vector_length), - data => new_integer_vector_ptr(data_pool, min_length => data_vector_length)); - end; - - procedure recycle(variable burst_data : inout burst_data_t) is - begin - recycle(data_pool, burst_data.address); - recycle(data_pool, burst_data.data); - end; - -begin - - control_process : process - begin - self.init(axi_slave, write_slave, 2**awid'length-1, wdata); - initialized <= true; - main_loop(self, net); - wait; - end process; - - axi_process : process - - procedure record_input_data(variable input_data : inout burst_data_t; - address : natural; byte : natural) is - variable ignored : boolean; - begin - if not check_address(axi_slave.p_memory, address, reading => false, check_permissions => true) then - return; - end if; - - set(input_data.address, input_data.length, address); - set(input_data.data, input_data.length, byte); - input_data.length := input_data.length + 1; - - ignored := check_write_data(axi_slave.p_memory, address, byte); - end; - - procedure write_data_to_memory(input_data_queue : queue_t) is - variable burst_data : burst_data_t; - begin - burst_data := pop_burst_data(input_data_queue); - for i in 0 to burst_data.length-1 loop - write_byte_unchecked(axi_slave.p_memory, get(burst_data.address, i), get(burst_data.data, i)); - end loop; - recycle(burst_data); - end; - - variable resp_burst, input_burst, burst : axi_burst_t; - variable address, aligned_address : integer; - variable beats : natural := 0; - variable input_data : burst_data_t; - constant input_data_queue : queue_t := new_queue; - - variable response_time : time; - variable has_response_time : boolean := false; - begin - -- Initialization - bid <= (bid'range => '0'); - bresp <= (bresp'range => '0'); - - assert awid'length = bid'length report "arwid vs wid data width mismatch"; - assert (awlen'length = 4 or - awlen'length = 8) report "awlen must be either 4 (AXI3) or 8 (AXI4)"; - - wait on initialized until initialized; - - loop - if bready = '1' then - bvalid <= '0'; - end if; - - if (awvalid and awready) = '1' then - input_burst := self.create_burst(awid, awaddr, awlen, awsize, awburst); - self.push_burst(input_burst); - end if; - - if (wvalid and wready) = '1' then - if (wlast = '1') /= (beats = 1) then - self.fail("Expected wlast='1' on last beat of burst " & describe_burst(burst) & - " with length " & to_string(burst.length) & - " starting at address " & to_string(burst.address)); - end if; - - aligned_address := address - (address mod self.data_size); - for j in 0 to self.data_size-1 loop - if wstrb(j) = '1' then - record_input_data(input_data, aligned_address+j, to_integer(unsigned(wdata(8*j+7 downto 8*j)))); - end if; - end loop; - - if burst.burst_type = axi_burst_type_incr then - address := address + burst.size; - end if; - - beats := beats - 1; - if beats = 0 then - self.push_random_response_time; - self.finish_burst(burst); - self.push_resp(burst); - push_burst_data(input_data_queue, input_data); - end if; - end if; - - if not (self.burst_queue_empty or beats > 0) then - input_data := new_burst_data; - burst := self.pop_burst; - address := burst.address; - beats := burst.length; - end if; - - if not self.resp_queue_empty and (bvalid = '0' or bready = '1') and not self.should_stall_write_response then - - if not has_response_time then - has_response_time := true; - response_time := self.pop_response_time; - end if; - - if has_response_time and response_time <= now then - has_response_time := false; - resp_burst := self.pop_resp; - write_data_to_memory(input_data_queue); - bvalid <= '1'; - bid <= std_logic_vector(to_unsigned(resp_burst.id, bid'length)); - bresp <= axi_resp_okay; - end if; - end if; - - if beats > 0 and not (beats = 1 and self.resp_queue_full) and not self.should_stall_data then - wready <= '1'; - else - wready <= '0'; - end if; - - if self.should_stall_address or self.burst_queue_full then - awready <= '0'; - else - awready <= '1'; - end if; - - wait until rising_edge(aclk); - end loop; - end process; - - well_behaved_check : process - variable size, len : natural; - variable num_beats : integer := 0; - variable num_beats_now : integer; - begin - wait on initialized until initialized; - loop - - num_beats_now := num_beats; - - if awvalid = '1' then - len := to_integer(unsigned(awlen)); - num_beats_now := num_beats + len + 1; - end if; - - -- Always keep track of num_beats such that the well behaved check can be enabled at any time - if (awvalid and awready) = '1' then - size := 2**to_integer(unsigned(awsize)); - num_beats := num_beats_now; - - if self.should_check_well_behaved and size /= self.data_size and len /= 0 then - self.fail("Burst not well behaved, axi size = " & to_string(size) & " but bus data width allows " & to_string(self.data_size)); - end if; - end if; - - if self.should_check_well_behaved and num_beats_now > 0 and wvalid /= '1' then - self.fail("Burst not well behaved, vwalid was not high during active burst"); - end if; - - if self.should_check_well_behaved and num_beats_now > 0 and bready /= '1' then - self.fail("Burst not well behaved, bready was not high during active burst"); - end if; - - if (wvalid and wready) = '1' then - num_beats := -1; - end if; - - wait until rising_edge(aclk); - end loop; - wait; - end process; - -end architecture; diff --git a/vunit/vhdl/verification_components/src/uart_master.vhd b/vunit/vhdl/verification_components/src/uart_master.vhd deleted file mode 100644 index ef9da5e09..000000000 --- a/vunit/vhdl/verification_components/src/uart_master.vhd +++ /dev/null @@ -1,67 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.com_context; -use vunit_lib.stream_master_pkg.all; -use vunit_lib.uart_pkg.all; -use vunit_lib.queue_pkg.all; -use vunit_lib.sync_pkg.all; - -entity uart_master is - generic ( - uart : uart_master_t); - port ( - tx : out std_logic := uart.p_idle_state); -end entity; - -architecture a of uart_master is -begin - - main : process - procedure uart_send(data : std_logic_vector; - signal tx : out std_logic; - baud_rate : integer) is - constant time_per_bit : time := (10**9 / baud_rate) * 1 ns; - - procedure send_bit(value : std_logic) is - begin - tx <= value; - wait for time_per_bit; - end procedure; - - begin - debug("Sending " & to_string(data)); - send_bit(not uart.p_idle_state); - for i in 0 to data'length-1 loop - send_bit(data(i)); - end loop; - send_bit(uart.p_idle_state); - end procedure; - - variable msg : msg_t; - variable baud_rate : natural := uart.p_baud_rate; - variable msg_type : msg_type_t; - begin - receive(net, uart.p_actor, msg); - msg_type := message_type(msg); - - handle_sync_message(net, msg_type, msg); - - if msg_type = stream_push_msg then - uart_send(pop_std_ulogic_vector(msg), tx, baud_rate); - elsif msg_type = uart_set_baud_rate_msg then - baud_rate := pop(msg); - else - unexpected_msg_type(msg_type); - end if; - end process; - -end architecture; diff --git a/vunit/vhdl/verification_components/src/uart_pkg.vhd b/vunit/vhdl/verification_components/src/uart_pkg.vhd deleted file mode 100644 index 3cb944115..000000000 --- a/vunit/vhdl/verification_components/src/uart_pkg.vhd +++ /dev/null @@ -1,119 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -context work.com_context; -use work.stream_master_pkg.all; -use work.stream_slave_pkg.all; -use work.sync_pkg.all; -use work.integer_vector_ptr_pkg.all; -use work.queue_pkg.all; - -package uart_pkg is - type uart_master_t is record - p_actor : actor_t; - p_baud_rate : natural; - p_idle_state : std_logic; - end record; - - type uart_slave_t is record - p_actor : actor_t; - p_baud_rate : natural; - p_idle_state : std_logic; - p_data_length : positive; - end record; - - -- Set the baud rate [bits/s] - procedure set_baud_rate(signal net : inout network_t; - uart_master : uart_master_t; - baud_rate : natural); - - procedure set_baud_rate(signal net : inout network_t; - uart_slave : uart_slave_t; - baud_rate : natural); - - constant default_baud_rate : natural := 115200; - constant default_idle_state : std_logic := '1'; - constant default_data_length : positive := 8; - impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state) return uart_master_t; - impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state; - data_length : positive := default_data_length) return uart_slave_t; - - impure function as_stream(uart_master : uart_master_t) return stream_master_t; - impure function as_stream(uart_slave : uart_slave_t) return stream_slave_t; - impure function as_sync(uart_master : uart_master_t) return sync_handle_t; - impure function as_sync(uart_slave : uart_slave_t) return sync_handle_t; - - constant uart_set_baud_rate_msg : msg_type_t := new_msg_type("uart set baud rate"); -end package; - -package body uart_pkg is - - impure function new_uart_master(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state) return uart_master_t is - begin - return (p_actor => new_actor, - p_baud_rate => initial_baud_rate, - p_idle_state => idle_state); - end; - - impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate; - idle_state : std_logic := default_idle_state; - data_length : positive := default_data_length) return uart_slave_t is - begin - return (p_actor => new_actor, - p_baud_rate => initial_baud_rate, - p_idle_state => idle_state, - p_data_length => data_length); - end; - - impure function as_stream(uart_master : uart_master_t) return stream_master_t is - begin - return stream_master_t'(p_actor => uart_master.p_actor); - end; - - impure function as_stream(uart_slave : uart_slave_t) return stream_slave_t is - begin - return stream_slave_t'(p_actor => uart_slave.p_actor); - end; - - impure function as_sync(uart_master : uart_master_t) return sync_handle_t is - begin - return uart_master.p_actor; - end; - - impure function as_sync(uart_slave : uart_slave_t) return sync_handle_t is - begin - return uart_slave.p_actor; - end; - - procedure set_baud_rate(signal net : inout network_t; - actor : actor_t; - baud_rate : natural) is - variable msg : msg_t := new_msg(uart_set_baud_rate_msg); - begin - push(msg, baud_rate); - send(net, actor, msg); - end; - - procedure set_baud_rate(signal net : inout network_t; - uart_master : uart_master_t; - baud_rate : natural) is - begin - set_baud_rate(net, uart_master.p_actor, baud_rate); - end; - - procedure set_baud_rate(signal net : inout network_t; - uart_slave : uart_slave_t; - baud_rate : natural) is - begin - set_baud_rate(net, uart_slave.p_actor, baud_rate); - end; -end package body; diff --git a/vunit/vhdl/verification_components/src/uart_slave.vhd b/vunit/vhdl/verification_components/src/uart_slave.vhd deleted file mode 100644 index 062c61fbf..000000000 --- a/vunit/vhdl/verification_components/src/uart_slave.vhd +++ /dev/null @@ -1,85 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.com_context; -use vunit_lib.stream_slave_pkg.all; -use vunit_lib.uart_pkg.all; -use vunit_lib.queue_pkg.all; - -entity uart_slave is - generic ( - uart : uart_slave_t); - port ( - rx : in std_logic); -end entity; - -architecture a of uart_slave is - signal baud_rate : natural := uart.p_baud_rate; - signal local_event : std_logic := '0'; - constant data_queue : queue_t := new_queue; -begin - - main : process - variable reply_msg, msg : msg_t; - variable msg_type : msg_type_t; - begin - receive(net, uart.p_actor, msg); - msg_type := message_type(msg); - - if msg_type = uart_set_baud_rate_msg then - baud_rate <= pop(msg); - - elsif msg_type = stream_pop_msg then - reply_msg := new_msg; - if not (length(data_queue) > 0) then - wait on local_event until length(data_queue) > 0; - end if; - push_std_ulogic_vector(reply_msg, pop_std_ulogic_vector(data_queue)); - push_boolean(reply_msg, false); - reply(net, msg, reply_msg); - - else - unexpected_msg_type(msg_type); - end if; - - end process; - - recv : process - procedure uart_recv(variable data : out std_logic_vector; - signal rx : in std_logic; - baud_rate : integer) is - constant time_per_bit : time := (10**9 / baud_rate) * 1 ns; - constant time_per_half_bit : time := (10**9 / (2*baud_rate)) * 1 ns; - begin - wait for time_per_half_bit; -- middle of start bit - assert rx = not uart.p_idle_state; - wait for time_per_bit; -- skip start bit - - for i in 0 to data'length-1 loop - data(i) := rx; - wait for time_per_bit; - end loop; - - assert rx = uart.p_idle_state; - end procedure; - - variable data : std_logic_vector(uart.p_data_length-1 downto 0); - begin - wait on rx until rx = not uart.p_idle_state; - uart_recv(data, rx, baud_rate); - push_std_ulogic_vector(data_queue, data); - local_event <= '1'; - wait for 0 ns; - local_event <= '0'; - wait for 0 ns; - end process; - -end architecture; diff --git a/vunit/vhdl/verification_components/src/vc_context.vhd b/vunit/vhdl/verification_components/src/vc_context.vhd index 3ea436584..1fc195983 100644 --- a/vunit/vhdl/verification_components/src/vc_context.vhd +++ b/vunit/vhdl/verification_components/src/vc_context.vhd @@ -9,16 +9,11 @@ context vc_context is use vunit_lib.avalon_pkg.all; use vunit_lib.avalon_stream_pkg.all; use vunit_lib.bus_master_pkg.all; - use vunit_lib.axi_pkg.all; - use vunit_lib.axi_slave_pkg.all; - use vunit_lib.axi_statistics_pkg.all; - use vunit_lib.axi_stream_pkg.all; use vunit_lib.memory_pkg.all; use vunit_lib.memory_utils_pkg.all; use vunit_lib.stream_master_pkg.all; use vunit_lib.stream_slave_pkg.all; use vunit_lib.sync_pkg.all; - use vunit_lib.uart_pkg.all; use vunit_lib.wishbone_pkg.all; context vunit_lib.com_context; end context; diff --git a/vunit/vhdl/verification_components/test/tb_axi_lite_master.vhd b/vunit/vhdl/verification_components/test/tb_axi_lite_master.vhd deleted file mode 100644 index 605fdcc9f..000000000 --- a/vunit/vhdl/verification_components/test/tb_axi_lite_master.vhd +++ /dev/null @@ -1,398 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context work.com_context; - -use work.axi_pkg.all; -use work.bus_master_pkg.all; -use work.axi_lite_master_pkg.all; - -library osvvm; -use osvvm.RandomPkg.all; - -entity tb_axi_lite_master is - generic (runner_cfg : string); -end entity; - -architecture a of tb_axi_lite_master is - constant num_random_tests : integer := 128; - - signal clk : std_logic := '0'; - signal arready : std_logic := '0'; - signal arvalid : std_logic; - signal araddr : std_logic_vector(31 downto 0); - - signal rready : std_logic := '0'; - signal rvalid : std_logic; - signal rdata : std_logic_vector(15 downto 0); - signal rresp : std_logic_vector(1 downto 0); - - signal awready : std_logic := '0'; - signal awvalid : std_logic; - signal awaddr : std_logic_vector(31 downto 0); - - signal wready : std_logic := '0'; - signal wvalid : std_logic; - signal wdata : std_logic_vector(15 downto 0); - signal wstrb : std_logic_vector(1 downto 0); - - signal bvalid : std_logic := '0'; - signal bready : std_logic; - signal bresp : std_logic_vector(1 downto 0); - - constant bus_handle : bus_master_t := new_bus(data_length => wdata'length, - address_length => awaddr'length); - - signal start, done : boolean := false; -begin - - main : process - variable tmp : std_logic_vector(rdata'range); - variable rnd : RandomPType; - begin - test_runner_setup(runner, runner_cfg); - rnd.InitSeed("common_seed"); - start <= true; - wait for 0 ns; - - if run("Test single write") then - mock(get_logger(bus_handle), debug); - write_bus(net, bus_handle, x"01234567", x"1122"); - wait_until_idle(net, bus_handle); - check_only_log(get_logger(bus_handle), "Wrote 0x1122 to address 0x01234567", debug); - unmock(get_logger(bus_handle)); - - elsif run("Test single write with byte enable") then - write_bus(net, bus_handle, x"01234567", x"1122", byte_enable => "10"); - - elsif run("Test write not okay") then - write_bus(net, bus_handle, x"01234567", x"1122"); - - elsif run("Test write with axi resp") then - write_axi_lite(net, bus_handle, x"01234567", x"1122", axi_resp_slverr); - - elsif run("Test write with wrong axi resp") then - write_axi_lite(net, bus_handle, x"01234567", x"1122", axi_resp_decerr); - - elsif run("Test single read") then - mock(get_logger(bus_handle), debug); - read_bus(net, bus_handle, x"01234567", tmp); - check_equal(tmp, std_logic_vector'(x"5566"), "read data"); - check_only_log(get_logger(bus_handle), "Read 0x5566 from address 0x01234567", debug); - unmock(get_logger(bus_handle)); - - elsif run("Test read not okay") then - read_bus(net, bus_handle, x"01234567", tmp); - - elsif run("Test read with axi resp") then - read_axi_lite(net, bus_handle, x"01234567", axi_resp_slverr, tmp); - - elsif run("Test read with wrong axi resp") then - read_axi_lite(net, bus_handle, x"01234567", axi_resp_exokay, tmp); - - elsif run("Test random") then - for i in 0 to num_random_tests-1 loop - if rnd.RandInt(0, 1) = 0 then - read_bus(net, bus_handle, rnd.RandSlv(araddr'length), tmp); - check_equal(tmp, rnd.RandSlv(rdata'length), "read data"); - else - write_bus(net, bus_handle, rnd.RandSlv(awaddr'length), rnd.RandSlv(wdata'length)); - end if; - end loop; - - elsif run("Test random axi resp") then - for i in 0 to num_random_tests-1 loop - if rnd.RandInt(0, 1) = 0 then - read_axi_lite(net, bus_handle, rnd.RandSlv(araddr'length), rnd.RandSlv(axi_resp_t'length), tmp); - check_equal(tmp, rnd.RandSlv(rdata'length), "read data"); - else - write_axi_lite(net, bus_handle, rnd.RandSlv(awaddr'length), rnd.RandSlv(wdata'length), - rnd.RandSlv(axi_resp_t'length)); - end if; - end loop; - end if; - - wait for 100 ns; - - if not done then - wait until done; - end if; - - test_runner_cleanup(runner); - end process; - test_runner_watchdog(runner, 100 us); - - - support : process - variable rnd : RandomPType; - begin - rnd.InitSeed("common_seed"); - - wait until start; - - if enabled("Test single write") then - awready <= '1'; - wait until (awready and awvalid) = '1' and rising_edge(clk); - awready <= '0'; - check_equal(awaddr, std_logic_vector'(x"01234567"), "awaddr"); - - wready <= '1'; - wait until (wready and wvalid) = '1' and rising_edge(clk); - wready <= '0'; - check_equal(wdata, std_logic_vector'(x"1122"), "wdata"); - check_equal(wstrb, std_logic_vector'("11"), "wstrb"); - - bvalid <= '1'; - bresp <= axi_resp_okay; - wait until (bready and bvalid) = '1' and rising_edge(clk); - bvalid <= '0'; - - done <= true; - - elsif enabled("Test single write with byte enable") then - awready <= '1'; - wait until (awready and awvalid) = '1' and rising_edge(clk); - awready <= '0'; - check_equal(awaddr, std_logic_vector'(x"01234567"), "awaddr"); - - wready <= '1'; - wait until (wready and wvalid) = '1' and rising_edge(clk); - wready <= '0'; - check_equal(wdata, std_logic_vector'(x"1122"), "wdata"); - check_equal(wstrb, std_logic_vector'("10"), "wstrb"); - - bvalid <= '1'; - bresp <= axi_resp_okay; - wait until (bready and bvalid) = '1' and rising_edge(clk); - bvalid <= '0'; - - done <= true; - - elsif enabled("Test write not okay") then - awready <= '1'; - wait until (awready and awvalid) = '1' and rising_edge(clk); - awready <= '0'; - - wready <= '1'; - wait until (wready and wvalid) = '1' and rising_edge(clk); - wready <= '0'; - - bvalid <= '1'; - bresp <= axi_resp_slverr; - mock(bus_logger, failure); - wait until (bready and bvalid) = '1' and rising_edge(clk); - bvalid <= '0'; - wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "bresp - Got AXI response SLVERR(10) expected OKAY(00)", failure); - unmock(bus_logger); - - done <= true; - - elsif enabled("Test write with axi resp") then - awready <= '1'; - wait until (awready and awvalid) = '1' and rising_edge(clk); - awready <= '0'; - check_equal(awaddr, std_logic_vector'(x"01234567"), "awaddr"); - - wready <= '1'; - wait until (wready and wvalid) = '1' and rising_edge(clk); - wready <= '0'; - check_equal(wdata, std_logic_vector'(x"1122"), "wdata"); - check_equal(wstrb, std_logic_vector'("11"), "wstrb"); - - bvalid <= '1'; - bresp <= axi_resp_slverr; - wait until (bready and bvalid) = '1' and rising_edge(clk); - bvalid <= '0'; - - done <= true; - - elsif enabled("Test write with wrong axi resp") then - awready <= '1'; - wait until (awready and awvalid) = '1' and rising_edge(clk); - awready <= '0'; - check_equal(awaddr, std_logic_vector'(x"01234567"), "awaddr"); - - wready <= '1'; - wait until (wready and wvalid) = '1' and rising_edge(clk); - wready <= '0'; - check_equal(wdata, std_logic_vector'(x"1122"), "wdata"); - check_equal(wstrb, std_logic_vector'("11"), "wstrb"); - - bvalid <= '1'; - bresp <= axi_resp_exokay; - mock(bus_logger, failure); - wait until (bready and bvalid) = '1' and rising_edge(clk); - bvalid <= '0'; - wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "bresp - Got AXI response EXOKAY(01) expected DECERR(11)", failure); - unmock(bus_logger); - - done <= true; - - elsif enabled("Test single read") then - arready <= '1'; - wait until (arready and arvalid) = '1' and rising_edge(clk); - arready <= '0'; - check_equal(araddr, std_logic_vector'(x"01234567"), "araddr"); - - rvalid <= '1'; - rresp <= axi_resp_okay; - rdata <= x"5566"; - wait until (rready and rvalid) = '1' and rising_edge(clk); - rvalid <= '0'; - - done <= true; - - elsif enabled("Test read not okay") then - arready <= '1'; - wait until (arready and arvalid) = '1' and rising_edge(clk); - arready <= '0'; - - rvalid <= '1'; - rresp <= axi_resp_decerr; - rdata <= x"5566"; - mock(bus_logger, failure); - wait until (rready and rvalid) = '1' and rising_edge(clk); - rvalid <= '0'; - wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "rresp - Got AXI response DECERR(11) expected OKAY(00)", failure); - unmock(bus_logger); - - done <= true; - - elsif enabled("Test read with axi resp") then - arready <= '1'; - wait until (arready and arvalid) = '1' and rising_edge(clk); - arready <= '0'; - check_equal(araddr, std_logic_vector'(x"01234567"), "araddr"); - - rvalid <= '1'; - rresp <= axi_resp_slverr; - rdata <= x"0000"; - wait until (rready and rvalid) = '1' and rising_edge(clk); - rvalid <= '0'; - - done <= true; - - elsif enabled("Test read with wrong axi resp") then - arready <= '1'; - wait until (arready and arvalid) = '1' and rising_edge(clk); - arready <= '0'; - check_equal(araddr, std_logic_vector'(x"01234567"), "araddr"); - - rvalid <= '1'; - rresp <= axi_resp_decerr; - rdata <= x"0000"; - mock(bus_logger, failure); - wait until (rready and rvalid) = '1' and rising_edge(clk); - rvalid <= '0'; - wait until mock_queue_length > 0 for 0 ns; - check_only_log(bus_logger, "rresp - Got AXI response DECERR(11) expected EXOKAY(01)", failure); - unmock(bus_logger); - - done <= true; - - elsif enabled("Test random") then - for i in 0 to num_random_tests-1 loop - if rnd.RandInt(0, 1) = 0 then - arready <= '1'; - wait until (arready and arvalid) = '1' and rising_edge(clk); - arready <= '0'; - check_equal(araddr, rnd.RandSlv(araddr'length), "araddr"); - - rvalid <= '1'; - rresp <= axi_resp_okay; - rdata <= rnd.RandSlv(rdata'length); - wait until (rready and rvalid) = '1' and rising_edge(clk); - rvalid <= '0'; - else - awready <= '1'; - wait until (awready and awvalid) = '1' and rising_edge(clk); - awready <= '0'; - check_equal(awaddr, rnd.RandSlv(awaddr'length), "awaddr"); - - wready <= '1'; - wait until (wready and wvalid) = '1' and rising_edge(clk); - wready <= '0'; - check_equal(wdata, rnd.RandSlv(wdata'length), "wdata"); - check_equal(wstrb, std_logic_vector'("11"), "wstrb"); - - bvalid <= '1'; - bresp <= axi_resp_okay; - wait until (bready and bvalid) = '1' and rising_edge(clk); - bvalid <= '0'; - end if; - end loop; - done <= true; - - elsif enabled("Test random axi resp") then - for i in 0 to num_random_tests-1 loop - if rnd.RandInt(0, 1) = 0 then - arready <= '1'; - wait until (arready and arvalid) = '1' and rising_edge(clk); - arready <= '0'; - check_equal(araddr, rnd.RandSlv(araddr'length), "araddr"); - - rvalid <= '1'; - rresp <= rnd.RandSlv(axi_resp_t'length); - rdata <= rnd.RandSlv(rdata'length); - wait until (rready and rvalid) = '1' and rising_edge(clk); - rvalid <= '0'; - else - awready <= '1'; - wait until (awready and awvalid) = '1' and rising_edge(clk); - awready <= '0'; - check_equal(awaddr, rnd.RandSlv(awaddr'length), "awaddr"); - - wready <= '1'; - wait until (wready and wvalid) = '1' and rising_edge(clk); - wready <= '0'; - check_equal(wdata, rnd.RandSlv(wdata'length), "wdata"); - check_equal(wstrb, std_logic_vector'("11"), "wstrb"); - - bvalid <= '1'; - bresp <= rnd.RandSlv(axi_resp_t'length); - wait until (bready and bvalid) = '1' and rising_edge(clk); - bvalid <= '0'; - end if; - end loop; - done <= true; - end if; - end process; - - dut : entity work.axi_lite_master - generic map ( - bus_handle => bus_handle) - port map ( - aclk => clk, - arready => arready, - arvalid => arvalid, - araddr => araddr, - rready => rready, - rvalid => rvalid, - rdata => rdata, - rresp => rresp, - awready => awready, - awvalid => awvalid, - awaddr => awaddr, - wready => wready, - wvalid => wvalid, - wdata => wdata, - wstrb => wstrb, - bvalid => bvalid, - bready => bready, - bresp => bresp); - - clk <= not clk after 5 ns; - -end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_axi_read_slave.vhd b/vunit/vhdl/verification_components/test/tb_axi_read_slave.vhd deleted file mode 100644 index 606969e83..000000000 --- a/vunit/vhdl/verification_components/test/tb_axi_read_slave.vhd +++ /dev/null @@ -1,418 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -context work.vunit_context; -context work.com_context; -context work.vc_context; - -use work.axi_pkg.all; -use work.integer_vector_ptr_pkg.all; -use work.random_pkg.all; - -library osvvm; -use osvvm.RandomPkg.all; - -entity tb_axi_read_slave is - generic (runner_cfg : string); -end entity; - -architecture a of tb_axi_read_slave is - signal clk : std_logic := '1'; - - constant log_data_size : integer := 4; - constant data_size : integer := 2**log_data_size; - - signal arvalid : std_logic := '0'; - signal arready : std_logic; - signal arid : std_logic_vector(3 downto 0); - signal araddr : std_logic_vector(31 downto 0); - signal arlen : axi4_len_t; - signal arsize : axi4_size_t; - signal arburst : axi_burst_type_t; - - signal rvalid : std_logic; - signal rready : std_logic := '0'; - signal rid : std_logic_vector(arid'range); - signal rdata : std_logic_vector(8*data_size-1 downto 0); - signal rresp : axi_resp_t; - signal rlast : std_logic; - - constant memory : memory_t := new_memory; - constant axi_slave : axi_slave_t := new_axi_slave(address_fifo_depth => 1, - memory => memory); - -begin - main : process - variable rnd : RandomPType; - - procedure write_addr(id : std_logic_vector; - addr : natural; - len : natural; - log_size : natural; - burst : axi_burst_type_t) is - begin - arvalid <= '1'; - arid <= id; - araddr <= std_logic_vector(to_unsigned(addr, araddr'length)); - arlen <= std_logic_vector(to_unsigned(len-1, arlen'length)); - arsize <= std_logic_vector(to_unsigned(log_size, arsize'length)); - arburst <= burst; - - wait until (arvalid and arready) = '1' and rising_edge(clk); - arvalid <= '0'; - end procedure; - - procedure read_data(id : std_logic_vector; address : natural; size : natural; resp : axi_resp_t; last : boolean) is - variable idx : integer; - begin - rready <= '1'; - wait until (rvalid and rready) = '1' and rising_edge(clk); - rready <= '0'; - for i in 0 to size-1 loop - idx := (address + i) mod data_size; -- Align data bus - check_equal(rdata(8*idx+7 downto 8*idx), read_byte(memory, address+i)); - end loop; - check_equal(rid, id, "rid"); - check_equal(rresp, resp, "rresp"); - check_equal(rlast, last, "rlast"); - end procedure; - - procedure transfer(log_size, len : natural; - id : std_logic_vector; - burst : std_logic_vector) is - variable buf : buffer_t; - variable size : natural; - variable data : integer_vector_ptr_t; - begin - size := 2**log_size; - random_integer_vector_ptr(rnd, data, size * len, 0, 255); - - buf := allocate(memory, 8 * len, alignment => 4096); - for i in 0 to length(data)-1 loop - write_byte(memory, base_address(buf)+i, get(data, i)); - end loop; - - write_addr(id, base_address(buf), len, log_size, burst); - - for i in 0 to len-1 loop - read_data(id, base_address(buf)+size*i, size, axi_resp_okay, i=len-1); - end loop; - end; - - variable log_size : natural; - variable buf : buffer_t; - variable id : std_logic_vector(arid'range); - variable len : natural; - variable burst : axi_burst_type_t; - variable start_time, diff_time : time; - begin - test_runner_setup(runner, runner_cfg); - rnd.InitSeed(rnd'instance_name); - - if run("Test random read") then - for test_idx in 0 to 32-1 loop - - id := rnd.RandSlv(arid'length); - case rnd.RandInt(1) is - when 0 => - burst := axi_burst_type_fixed; - len := 1; - when 1 => - burst := axi_burst_type_incr; - len := rnd.RandInt(1, 2**arlen'length); - when others => - assert false; - end case; - - log_size := rnd.RandInt(0, 3); - transfer(log_size, len, id, burst); - end loop; - - elsif run("Test random data stall") then - log_size := 3; - len := 128; - id := (arid'range => '0'); - burst := axi_burst_type_incr; - - for i in 0 to 4 loop - if i = 2 then - set_data_stall_probability(net, axi_slave, 0.9); - else - set_data_stall_probability(net, axi_slave, 0.0); - end if; - - start_time := now; - - transfer(log_size, len, id, burst); - info("diff_time := " & to_string(now - start_time)); - - if i = 1 or i = 4 then - -- First two and last two runs should have the same time with 0.0 - -- stall probability - check_equal(diff_time, now - start_time); - elsif i = 2 then - -- Middle run should have larger time - check(5*diff_time < now - start_time); - end if; - - diff_time := now - start_time; - end loop; - - elsif run("Test response latency") then - log_size := 3; - len := 128; - id := (arid'range => '0'); - burst := axi_burst_type_incr; - - for i in 0 to 1 loop - if i = 1 then - set_response_latency(net, axi_slave, 1 us); - end if; - - start_time := now; - - transfer(log_size, len, id, burst); - info("diff_time := " & to_string(now - start_time)); - - if i = 1 then - check_equal(diff_time + 1 us, now - start_time); - end if; - - diff_time := now - start_time; - end loop; - - elsif run("Test that permissions are checked") then - -- Also checks that the axi slave logger is used for memory errors - buf := allocate(memory, data_size, permissions => no_access); - mock(axi_slave_logger, failure); - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_fixed); - wait until mock_queue_length > 0 and rising_edge(clk); - check_only_log(axi_slave_logger, - "Reading from address 0 at offset 0 within anonymous buffer at range (0 to 15) without permission (no_access)", - failure); - unmock(axi_slave_logger); - - elsif run("Test error on unsupported wrap burst") then - mock(axi_slave_logger, failure); - - buf := allocate(memory, 8); - write_addr(x"2", base_address(buf), 2, 0, axi_burst_type_wrap); - wait until mock_queue_length > 0 and rising_edge(clk); - check_only_log(axi_slave_logger, "Wrapping burst type not supported", failure); - unmock(axi_slave_logger); - - elsif run("Test error 4KByte boundary crossing") then - buf := allocate(memory, 4096+32, alignment => 4096); - mock(axi_slave_logger, failure); - write_addr(x"2", base_address(buf)+4000, 256, 0, axi_burst_type_incr); - wait until mock_queue_length > 0 and rising_edge(clk); - check_only_log(axi_slave_logger, "Crossing 4KByte boundary. First page = 0 (4000/4096), last page = 1 (4255/4096)", failure); - unmock(axi_slave_logger); - - elsif run("Test no error on 4KByte boundary crossing with disabled check") then - buf := allocate(memory, 4096+32, alignment => 4096); - disable_4kbyte_boundary_check(net, axi_slave); - write_addr(x"2", base_address(buf)+4000, 256, 0, axi_burst_type_incr); - wait until arvalid = '0' and rising_edge(clk); - - elsif run("Test default address fifo depth is 1") then - buf := allocate(memory, 1024); - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- Taken data process - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- In the queue - for i in 0 to 127 loop - wait until rising_edge(clk); - assert arready = '0' report "Can only have one address in the queue"; - end loop; - - elsif run("Test set address fifo depth") then - buf := allocate(memory, 1024); - set_address_fifo_depth(net, axi_slave, 16); - - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- Taken data process - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- In the queue - end loop; - - for i in 0 to 127 loop - wait until rising_edge(clk); - assert arready = '0' report "Address queue should be full"; - end loop; - - elsif run("Test changing address depth to smaller than content gives error") then - buf := allocate(memory, 1024); - set_address_fifo_depth(net, axi_slave, 16); - - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- Taken data process - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- In the queue - end loop; - - set_address_fifo_depth(net, axi_slave, 17); - set_address_fifo_depth(net, axi_slave, 16); - - mock(axi_slave_logger, failure); - set_address_fifo_depth(net, axi_slave, 1); - check_only_log(axi_slave_logger, "New address fifo depth 1 is smaller than current content size 16", failure); - unmock(axi_slave_logger); - - elsif run("Test address stall probability") then - buf := allocate(memory, 1024); - set_address_fifo_depth(net, axi_slave, 128); - - start_time := now; - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); - end loop; - diff_time := now - start_time; - - set_address_stall_probability(net, axi_slave, 0.9); - start_time := now; - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); - end loop; - assert (now - start_time) > 5.0 * diff_time report "Should take about longer with stall probability"; - - elsif run("Test well behaved check does not fail for well behaved bursts") then - buf := allocate(memory, 128); - enable_well_behaved_check(net, axi_slave); - set_address_fifo_depth(net, axi_slave, 3); - set_write_response_fifo_depth(net, axi_slave, 3); - - wait until rising_edge(clk); - rready <= '1'; - assert rvalid = '0'; - -- Only allow non max size for single beat bursts - write_addr(x"0", base_address(buf), len => 1, log_size => log_data_size, burst => axi_burst_type_incr); - rready <= '1'; - assert rvalid = '0'; - write_addr(x"0", base_address(buf), len => 2, log_size => log_data_size, burst => axi_burst_type_incr); - rready <= '1'; - assert rvalid = '1'; - write_addr(x"0", base_address(buf), len => 1, log_size => 0, burst => axi_burst_type_incr); - rready <= '1'; - assert rvalid = '1'; - wait until rising_edge(clk); - rready <= '1'; - assert rvalid = '1'; - wait until rising_edge(clk); - rready <= '0'; - assert rvalid = '1'; - wait until rising_edge(clk); - rready <= '0'; - assert rvalid = '0'; - wait until rising_edge(clk); - assert rvalid = '0'; - wait until rising_edge(clk); - assert rvalid = '0'; - wait until rising_edge(clk); - assert rvalid = '0'; - - elsif run("Test well behaved check does not fail after well behaved burst finished") then - buf := allocate(memory, 128); - enable_well_behaved_check(net, axi_slave); - - wait until rising_edge(clk); - rready <= '1'; - assert rvalid = '0'; - -- Only allow non max size for single beat bursts - write_addr(x"0", base_address(buf), len => 3, log_size => log_data_size, burst => axi_burst_type_incr); - rready <= '1'; - assert rvalid = '0'; - wait until rising_edge(clk); - rready <= '1'; - assert rvalid = '1'; - wait until rising_edge(clk); - rready <= '1'; - assert rvalid = '1'; - wait until rising_edge(clk); - rready <= '0'; - assert rvalid = '1'; - wait until rising_edge(clk); - rready <= '0'; - assert rvalid = '0'; - wait until rising_edge(clk); - rready <= '0'; - wait until rising_edge(clk); - rready <= '0'; - assert rvalid = '0'; - - elsif run("Test well behaved check fails for ill behaved awsize") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - mock(axi_slave_logger, failure); - rready <= '1'; - wait until rising_edge(clk); - write_addr(x"0", base_address(buf), len => 2, log_size => 0, burst => axi_burst_type_incr); - check_only_log(axi_slave_logger, "Burst not well behaved, axi size = 1 but bus data width allows " & to_string(data_size), failure); - unmock(axi_slave_logger); - - elsif run("Test well behaved check fails when rready not high during active burst") then - buf := allocate(memory, 128); - enable_well_behaved_check(net, axi_slave); - mock(axi_slave_logger, failure); - wait until rising_edge(clk); - write_addr(x"0", base_address(buf), len => 2, log_size => log_data_size, burst => axi_burst_type_incr); - check_only_log(axi_slave_logger, "Burst not well behaved, rready was not high during active burst", failure); - unmock(axi_slave_logger); - - elsif run("Test well behaved check fails when wvalid not high during active burst and arready is low") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - mock(axi_slave_logger, failure); - set_address_stall_probability(net, axi_slave, 1.0); - - wait until rising_edge(clk); - wait until rising_edge(clk); - assert arready = '0'; - - arvalid <= '1'; - arid <= x"0"; - araddr <= std_logic_vector(to_unsigned(base_address(buf), araddr'length)); - arlen <= std_logic_vector(to_unsigned(0, arlen'length)); - arsize <= std_logic_vector(to_unsigned(log_size, arsize'length)); - arburst <= axi_burst_type_incr; - - wait until rising_edge(clk); - assert arready = '0'; - wait until mock_queue_length > 0 for 0 ns; - - check_only_log(axi_slave_logger, "Burst not well behaved, rready was not high during active burst", failure); - unmock(axi_slave_logger); - - - end if; - - test_runner_cleanup(runner); - end process; - test_runner_watchdog(runner, 1 ms); - - dut : entity work.axi_read_slave - generic map ( - axi_slave => axi_slave) - port map ( - aclk => clk, - - arvalid => arvalid, - arready => arready, - arid => arid, - araddr => araddr, - arlen => arlen, - arsize => arsize, - arburst => arburst, - - rvalid => rvalid, - rready => rready, - rid => rid, - rdata => rdata, - rresp => rresp, - rlast => rlast); - - clk <= not clk after 5 ns; -end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_axi_slave_private_pkg.vhd b/vunit/vhdl/verification_components/test/tb_axi_slave_private_pkg.vhd deleted file mode 100644 index 1e107c83c..000000000 --- a/vunit/vhdl/verification_components/test/tb_axi_slave_private_pkg.vhd +++ /dev/null @@ -1,252 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -context work.vunit_context; -context work.vc_context; -use work.axi_pkg.all; -use work.axi_slave_private_pkg.all; - -entity tb_axi_slave_private_pkg is - generic (runner_cfg : string); -end entity; - -architecture tb of tb_axi_slave_private_pkg is - signal init : boolean := false; - shared variable axi_slave : axi_slave_private_t; -begin - main : process - variable data : std_logic_vector(127 downto 0); - - variable axid : std_logic_vector(3 downto 0); - constant max_id : natural := 2**axid'length-1; - variable axaddr : std_logic_vector(31 downto 0); - variable axlen : axi4_len_t; - variable axsize : axi4_size_t; - variable axburst : axi_burst_type_t; - - variable burst : axi_burst_t; - variable logger : logger_t := get_logger("axi_slave"); - constant axi_public_slave : axi_slave_t := new_axi_slave(memory => new_memory, - logger => logger); - variable stat : axi_statistics_t; - - procedure slave_init(axi_slave_type : axi_slave_type_t) is - begin - axi_slave.init(axi_public_slave, - axi_slave_type, - max_id, - data); - end; - - begin - test_runner_setup(runner, runner_cfg); - - if run("test create_burst updates statistics") then - slave_init(read_slave); - init <= true; - wait for 0 ns; - axid := x"2"; - axaddr := x"00100000"; - axlen := x"ff"; - axsize := "100"; - axburst := axi_burst_type_fixed; - - get_statistics(net, axi_public_slave, stat); - check_equal(get_num_burst_with_length(stat, 256), 0, - "No burst before create"); - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - check_equal(get_num_burst_with_length(stat, 256), 0, - "Statistics was copied before create"); - - get_statistics(net, axi_public_slave, stat); - check_equal(get_num_burst_with_length(stat, 256), 1, - "Newly read statistics has one entry"); - - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - - get_statistics(net, axi_public_slave, stat, clear => true); - check_equal(get_num_burst_with_length(stat, 256), 2, - "One more burst"); - - check_equal(min_burst_length(stat), 256, - "min_burst_length"); - - check_equal(max_burst_length(stat), 256, - "max_burst_length"); - - get_statistics(net, axi_public_slave, stat); - - check_equal(get_num_burst_with_length(stat, 256), 0, - "Cleared"); - - elsif run("test create_burst read debug messages") then - slave_init(read_slave); - mock(logger, debug); - axid := x"2"; - axaddr := x"00100000"; - axlen := x"ff"; - axsize := "100"; - axburst := axi_burst_type_fixed; - - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - check_only_log(logger, - "Got read burst #0 for id 2" & LF & - "arid = 0x2" & LF & - "araddr = 0x00100000" & LF & - "arlen = 255" & LF & - "arsize = 4" & LF & - "arburst = fixed (00)", - debug); - - axburst := axi_burst_type_incr; - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - check_only_log(logger, - "Got read burst #1 for id 2" & LF & - "arid = 0x2" & LF & - "araddr = 0x00100000" & LF & - "arlen = 255" & LF & - "arsize = 4" & LF & - "arburst = incr (01)", - debug); - - -- Each id has a separate burst index - axid := x"0"; - axburst := axi_burst_type_incr; - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - check_only_log(logger, - "Got read burst #0 for id 0" & LF & - "arid = 0x0" & LF & - "araddr = 0x00100000" & LF & - "arlen = 255" & LF & - "arsize = 4" & LF & - "arburst = incr (01)", - debug); - - unmock(logger); - - elsif run("test create_burst write debug messages") then - slave_init(write_slave); - - mock(logger, debug); - axid := x"2"; - axaddr := x"00100000"; - axlen := x"ff"; - axsize := "100"; - axburst := axi_burst_type_fixed; - - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - check_only_log(logger, - "Got write burst #0 for id 2" & LF & - "awid = 0x2" & LF & - "awaddr = 0x00100000" & LF & - "awlen = 255" & LF & - "awsize = 4" & LF & - "awburst = fixed (00)", - debug); - - axburst := axi_burst_type_incr; - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - check_only_log(logger, - "Got write burst #1 for id 2" & LF & - "awid = 0x2" & LF & - "awaddr = 0x00100000" & LF & - "awlen = 255" & LF & - "awsize = 4" & LF & - "awburst = incr (01)", - debug); - - -- Each id has a separate burst index - axid := x"0"; - axburst := axi_burst_type_incr; - burst := axi_slave.create_burst(axid, axaddr, axlen, axsize, axburst); - check_only_log(logger, - "Got write burst #0 for id 0" & LF & - "awid = 0x0" & LF & - "awaddr = 0x00100000" & LF & - "awlen = 255" & LF & - "awsize = 4" & LF & - "awburst = incr (01)", - debug); - - unmock(logger); - - elsif run("test pop_resp debug messages") then - slave_init(write_slave); - - mock(logger, debug); - - burst.index := 77; - burst.id := 13; - axi_slave.push_resp(burst); - - check_no_log; - - burst := axi_slave.pop_resp; - - check_only_log(logger, "Providing write response for burst #77 for id 13", debug); - - unmock(logger); - - elsif run("test pop_burst write slave debug messages") then - slave_init(write_slave); - - burst.index := 77; - burst.id := 13; - axi_slave.push_resp(burst); - axi_slave.push_burst(burst); - mock(logger, debug); - burst := axi_slave.pop_burst; - check_only_log(logger, "Start accepting data for write burst #77 for id 13", debug); - unmock(logger); - - elsif run("test pop_burst read slave debug messages") then - slave_init(read_slave); - - burst.index := 77; - burst.id := 13; - axi_slave.push_resp(burst); - axi_slave.push_burst(burst); - mock(logger, debug); - burst := axi_slave.pop_burst; - check_only_log(logger, "Start providing data for read burst #77 for id 13", debug); - unmock(logger); - - elsif run("test finish_burst read slave debug messages") then - slave_init(read_slave); - mock(logger, debug); - - burst.index := 77; - burst.id := 13; - axi_slave.push_resp(burst); - axi_slave.finish_burst(burst); - check_only_log(logger, "Providing last data for read burst #77 for id 13", debug); - - unmock(logger); - - elsif run("test finish_burst write slave debug messages") then - slave_init(write_slave); - mock(logger, debug); - - burst.index := 77; - burst.id := 13; - axi_slave.push_resp(burst); - axi_slave.finish_burst(burst); - check_only_log(logger, "Accepted last data for write burst #77 for id 13", debug); - - unmock(logger); - end if; - test_runner_cleanup(runner); - end process; - - slave_main : process - begin - wait until init; - main_loop(axi_slave, net); - end process; -end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_axi_statistics_pkg.vhd b/vunit/vhdl/verification_components/test/tb_axi_statistics_pkg.vhd deleted file mode 100644 index c42781ab2..000000000 --- a/vunit/vhdl/verification_components/test/tb_axi_statistics_pkg.vhd +++ /dev/null @@ -1,87 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - --- vunit: run_all_in_same_sim - -use work.axi_pkg.all; -context work.vunit_context; -context work.vc_context; - -entity tb_axi_statistics_pkg is - generic (runner_cfg : string); -end entity; - -architecture tb of tb_axi_statistics_pkg is -begin - main : process - variable stat, stat2 : axi_statistics_t; - begin - test_runner_setup(runner, runner_cfg); - check(stat = null_axi_statistics); - - while test_suite loop - deallocate(stat); - check(stat = null_axi_statistics); - - if run("test new_axi_statistics") then - stat := new_axi_statistics; - check_equal(num_bursts(stat), 0); - check_equal(min_burst_length(stat), 0); - check_equal(max_burst_length(stat), 0); - - for i in 0 to max_axi4_burst_length loop - check_equal(get_num_burst_with_length(stat, i), 0); - end loop; - check_equal(get_num_burst_with_length(stat, max_axi4_burst_length+1), 0); - - deallocate(stat); - check(stat = null_axi_statistics); - - elsif run("test add_burst_length") then - stat := new_axi_statistics; - - add_burst_length(stat, 7); - add_burst_length(stat, 7); - add_burst_length(stat, 17); - - check_equal(num_bursts(stat), 3); - check_equal(min_burst_length(stat), 7); - check_equal(max_burst_length(stat), 17); - - for i in 0 to max_axi4_burst_length loop - if i = 7 then - check_equal(get_num_burst_with_length(stat, i), 2); - elsif i = 17 then - check_equal(get_num_burst_with_length(stat, i), 1); - else - check_equal(get_num_burst_with_length(stat, i), 0); - end if; - end loop; - - elsif run("test copy") then - stat := new_axi_statistics; - add_burst_length(stat, 7); - stat2 := copy(stat); - add_burst_length(stat, 17); - check_equal(num_bursts(stat), 2); - clear(stat); - check_equal(num_bursts(stat2), 1); - check_equal(get_num_burst_with_length(stat2, 7), 1); - check_equal(get_num_burst_with_length(stat2, 17), 0); - - elsif run("test clear") then - stat := new_axi_statistics; - add_burst_length(stat, 7); - add_burst_length(stat, 17); - clear(stat); - check_equal(num_bursts(stat), 0); - check_equal(get_num_burst_with_length(stat, 7), 0); - check_equal(get_num_burst_with_length(stat, 17), 0); - end if; - end loop; - test_runner_cleanup(runner); - end process; -end; diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd deleted file mode 100644 index a52de31d0..000000000 --- a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd +++ /dev/null @@ -1,501 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -context work.vunit_context; -context work.com_context; -context work.data_types_context; -use work.axi_stream_pkg.all; -use work.stream_master_pkg.all; -use work.stream_slave_pkg.all; -use work.sync_pkg.all; - -entity tb_axi_stream is - generic(runner_cfg : string); -end entity; - -architecture a of tb_axi_stream is - constant master_axi_stream : axi_stream_master_t := new_axi_stream_master( - data_length => 8, id_length => 8, dest_length => 8, user_length => 8, - logger => get_logger("master"), actor => new_actor("master"), - monitor => default_axi_stream_monitor, protocol_checker => default_axi_stream_protocol_checker - ); - constant master_stream : stream_master_t := as_stream(master_axi_stream); - constant master_sync : sync_handle_t := as_sync(master_axi_stream); - - constant slave_axi_stream : axi_stream_slave_t := new_axi_stream_slave( - data_length => 8, id_length => 8, dest_length => 8, user_length => 8, - logger => get_logger("slave"), actor => new_actor("slave"), - monitor => default_axi_stream_monitor, protocol_checker => default_axi_stream_protocol_checker - ); - constant slave_stream : stream_slave_t := as_stream(slave_axi_stream); - constant slave_sync : sync_handle_t := as_sync(slave_axi_stream); - - constant monitor : axi_stream_monitor_t := new_axi_stream_monitor( - data_length => 8, id_length => 8, dest_length => 8, user_length => 8, - logger => get_logger("monitor"), actor => new_actor("monitor"), - protocol_checker => default_axi_stream_protocol_checker - ); - - constant protocol_checker : axi_stream_protocol_checker_t := new_axi_stream_protocol_checker( - data_length => 8, id_length => 8, dest_length => 8, user_length => 8, - logger => get_logger("protocol_checker"), - max_waits => 8 - ); - - constant n_monitors : natural := 3; - - signal aclk : std_logic := '0'; - signal areset_n : std_logic := '1'; - signal tvalid : std_logic; - signal tready : std_logic; - signal tdata : std_logic_vector(data_length(slave_axi_stream)-1 downto 0); - signal tlast : std_logic; - signal tkeep : std_logic_vector(data_length(slave_axi_stream)/8-1 downto 0); - signal tstrb : std_logic_vector(data_length(slave_axi_stream)/8-1 downto 0); - signal tid : std_logic_vector(id_length(slave_axi_stream)-1 downto 0); - signal tdest : std_logic_vector(dest_length(slave_axi_stream)-1 downto 0); - signal tuser : std_logic_vector(user_length(slave_axi_stream)-1 downto 0); - - signal not_valid : std_logic; - signal not_valid_data : std_logic; - signal not_valid_keep : std_logic; - signal not_valid_strb : std_logic; - signal not_valid_id : std_logic; - signal not_valid_dest : std_logic; - signal not_valid_user : std_logic; -begin - - main : process - constant subscriber : actor_t := new_actor("main"); - - variable data : std_logic_vector(tdata'range); - variable last_bool : boolean; - variable last : std_logic; - variable keep : std_logic_vector(tkeep'range); - variable strb : std_logic_vector(tstrb'range); - variable id : std_logic_vector(tid'range); - variable dest : std_logic_vector(tdest'range); - variable user : std_logic_vector(tuser'range); - - variable axi_stream_transaction : axi_stream_transaction_t( - tdata(tdata'range), - tkeep(tkeep'range), - tstrb(tstrb'range), - tid(tid'range), - tdest(tdest'range), - tuser(tuser'range) - ); - variable reference_queue : queue_t := new_queue; - variable reference : stream_reference_t; - variable msg : msg_t; - variable msg_type : msg_type_t; - variable timestamp : time := 0 ns; - - variable mocklogger : logger_t; - - procedure get_axi_stream_transaction(variable axi_stream_transaction : out axi_stream_transaction_t) is - begin - receive(net, subscriber, msg); - msg_type := message_type(msg); - handle_axi_stream_transaction(msg_type, msg, axi_stream_transaction); - check(is_already_handled(msg_type)); - end; - - begin - test_runner_setup(runner, runner_cfg); - subscribe(subscriber, find("monitor")); - subscribe(subscriber, find("master")); - subscribe(subscriber, find("slave")); - show(get_logger("monitor"), display_handler, debug); - show(get_logger("master"), display_handler, debug); - show(get_logger("slave"), display_handler, debug); - - wait for 20 ns; - - if run("test single push and pop") then - push_stream(net, master_stream, x"77", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"77"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - elsif run("test reset") then - wait until rising_edge(aclk); - areset_n <= '0'; - wait until rising_edge(aclk); - check_equal(tvalid, '0', result("for valid low check while in reset")); - areset_n <= '1'; - wait until rising_edge(aclk); - - elsif run("test single push and pop with tlast") then - push_stream(net, master_stream, x"88", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"88"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"88"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - - elsif run("test single axi push and pop") then - push_axi_stream(net, master_axi_stream, x"99", tlast => '1'); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"99"), result("pop stream data")); - check_equal(last_bool, true, result("pop stream last")); - - elsif run("test single push and axi pop") then - push_stream(net, master_stream, x"AA", last => true); - pop_axi_stream(net, slave_axi_stream, data, last); - check_equal(data, std_logic_vector'(x"AA"), result("pop stream data")); - check_equal(last, '1', result("pop stream last")); - - elsif run("test single axi push and axi pop") then - push_axi_stream(net, master_axi_stream, x"99", tlast => '1', tkeep => "1", tstrb => "1", tid => x"11", tdest => x"22", tuser => x"33" ); - pop_axi_stream(net, slave_axi_stream, data, last, keep, strb, id, dest, user); - check_equal(data, std_logic_vector'(x"99"), result("pop axi stream data")); - check_equal(last, std_logic'('1'), result("pop stream last")); - check_equal(keep, std_logic_vector'("1"), result("pop stream keep")); - check_equal(strb, std_logic_vector'("1"), result("pop stream strb")); - check_equal(id, std_logic_vector'(x"11"), result("pop stream id")); - check_equal(dest, std_logic_vector'(x"22"), result("pop stream dest")); - check_equal(user, std_logic_vector'(x"33"), result("pop stream user")); - - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal(axi_stream_transaction.tdata, std_logic_vector'(x"99"), result("for axi_stream_transaction.tdata")); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - check_equal(axi_stream_transaction.tkeep, std_logic_vector'("1"), result("pop stream keep")); - check_equal(axi_stream_transaction.tstrb, std_logic_vector'("1"), result("pop stream strb")); - check_equal(axi_stream_transaction.tid, std_logic_vector'(x"11"), result("pop stream id")); - check_equal(axi_stream_transaction.tdest, std_logic_vector'(x"22"), result("pop stream dest")); - check_equal(axi_stream_transaction.tuser, std_logic_vector'(x"33"), result("pop stream user")); - end loop; - - elsif run("test single stalled push and pop") then - wait until rising_edge(aclk); - wait_for_time(net, master_sync, 30 ns); - timestamp := now; - push_stream(net, master_stream, x"77", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 50 ns, result("for push wait time")); -- two extra cycles inserted by alignment - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"77"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - - elsif run("test single push and stalled pop") then - wait until rising_edge(aclk); - wait_for_time(net, slave_sync, 30 ns); - timestamp := now; - push_stream(net, master_stream, x"77", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 50 ns, result("for push wait time")); - - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"77"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - - elsif run("test single push and stalled pop with non-multiple of clock period") then - wait until rising_edge(aclk); - wait_for_time(net, slave_sync, 29 ns); - timestamp := now; - push_stream(net, master_stream, x"77", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 40 ns, result("for push wait time")); - - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"77"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - - elsif run("test single stalled push and pop with non-multiple of clock period") then - wait until rising_edge(aclk); - wait_for_time(net, master_sync, 29 ns); - timestamp := now; - push_stream(net, master_stream, x"77", true); - pop_stream(net, slave_stream, data, last_bool); - check_equal(data, std_logic_vector'(x"77"), result("for pop stream data")); - check_true(last_bool, result("for pop stream last")); - check_equal(now - 10 ns, timestamp + 40 ns, result("for push wait time")); -- Aligned to clock edge again - for i in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - std_logic_vector'(x"77"), - result("for axi_stream_transaction.tdata") - ); - check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); - end loop; - - elsif run("test pop before push") then - for i in 0 to 7 loop - pop_stream(net, slave_stream, reference); - push(reference_queue, reference); - end loop; - - for i in 0 to 7 loop - push_stream(net, master_stream, std_logic_vector(to_unsigned(i + 1, data'length)), true); - end loop; - - wait_until_idle(net, master_sync); -- wait until all transfers are done before checking them - wait_until_idle(net, slave_sync); - - for i in 0 to 7 loop - reference := pop(reference_queue); - await_pop_stream_reply(net, reference, data); - check_equal(data, to_unsigned(i + 1, data'length), result("for await pop stream data")); - - for j in 1 to n_monitors loop - get_axi_stream_transaction(axi_stream_transaction); - check_equal( - axi_stream_transaction.tdata, - to_unsigned(i + 1, data'length), - result("for axi_stream_transaction.tdata") - ); - end loop; - end loop; - - elsif run("test passing check") then - push_axi_stream(net, master_axi_stream, x"12", tlast => '1', tkeep => "1", tstrb => "1", tid => x"23", tdest => x"34", tuser => x"45"); - check_axi_stream(net, slave_axi_stream, x"12", '1', "1", "1", x"23", x"34", x"45", "checking axi stream"); - - elsif run("test passing reduced check") then - push_axi_stream(net, master_axi_stream, x"12", tlast => '1', tkeep => "1", tstrb => "1", tid => x"23", tdest => x"34", tuser => x"45"); - check_axi_stream(net, slave_axi_stream, x"12", '1', msg => "reduced checking axi stream"); - - elsif run("test failing check") then - - push_axi_stream(net, master_axi_stream, x"11", tlast => '0', tkeep => "0", tstrb => "0", tid => x"22", tdest => x"33", tuser => x"44"); - -- Delay mocking the logger to prevent 'invalid checks' from failing the checks below - wait until rising_edge (aclk) and tvalid = '1'; - - mocklogger := get_logger("check"); - mock(mocklogger); - - check_axi_stream(net, slave_axi_stream, x"12", '1', "1", "1", x"23", x"34", x"45", "checking axi stream"); - check_log(mocklogger, "TDATA mismatch, checking axi stream - Got 0001_0001 (17). Expected 0001_0010 (18).", error); - check_log(mocklogger, "TLAST mismatch, checking axi stream - Got 0. Expected 1.", error); - check_log(mocklogger, "TKEEP mismatch, checking axi stream - Got 0 (0). Expected 1 (1).", error); - check_log(mocklogger, "TSTRB mismatch, checking axi stream - Got 0 (0). Expected 1 (1).", error); - check_log(mocklogger, "TID mismatch, checking axi stream - Got 0010_0010 (34). Expected 0010_0011 (35).", error); - check_log(mocklogger, "TDEST mismatch, checking axi stream - Got 0011_0011 (51). Expected 0011_0100 (52).", error); - check_log(mocklogger, "TUSER mismatch, checking axi stream - Got 0100_0100 (68). Expected 0100_0101 (69).", error); - - unmock(mocklogger); - - elsif run("test back-to-back passing check") then - wait until rising_edge(aclk); - timestamp := now; - - last := '0'; - for i in 3 to 14 loop - if i = 14 then - last := '1'; - end if; - push_axi_stream(net, master_axi_stream, - tdata => std_logic_vector(to_unsigned(i, 8)), - tlast => last, - tkeep => "1", - tstrb => "1", - tid => std_logic_vector(to_unsigned(42, 8)), - tdest => std_logic_vector(to_unsigned(i+1, 8)), - tuser => std_logic_vector(to_unsigned(i*2, 8))); - end loop; - - last := '0'; - for i in 3 to 14 loop - if i = 14 then - last := '1'; - end if; - check_axi_stream(net, slave_axi_stream, - expected => std_logic_vector(to_unsigned(i, 8)), - tlast => last, - tkeep => "1", - tstrb => "1", - tid => std_logic_vector(to_unsigned(42, 8)), - tdest => std_logic_vector(to_unsigned(i+1, 8)), - tuser => std_logic_vector(to_unsigned(i*2, 8)), - msg => "check blocking", - blocking => false); - end loop; - - check_equal(now, timestamp, result(" setting up transaction stalled")); - - wait_until_idle(net, as_sync(slave_axi_stream)); - check_equal(now, timestamp + (12+1)*10 ns, " transaction time incorrect"); - - elsif run("test back-to-back failing check") then - wait until rising_edge(aclk); - timestamp := now; - - push_axi_stream(net, master_axi_stream, - tdata => std_logic_vector(to_unsigned(3, 8)), - tlast => '1', - tkeep => "0", - tstrb => "0", - tid => std_logic_vector(to_unsigned(42, 8)), - tdest => std_logic_vector(to_unsigned(4, 8)), - tuser => std_logic_vector(to_unsigned(7, 8))); - - check_axi_stream(net, slave_axi_stream, - expected => std_logic_vector(to_unsigned(6, 8)), - tlast => '0', - tkeep => "1", - tstrb => "1", - tid => std_logic_vector(to_unsigned(44, 8)), - tdest => std_logic_vector(to_unsigned(5, 8)), - tuser => std_logic_vector(to_unsigned(8, 8)), - msg => "check non-blocking", - blocking => false); - - check_equal(now, timestamp, result(" setting up transaction stalled")); - - wait until rising_edge(aclk); - mocklogger := get_logger("check"); - mock(mocklogger); - - wait until rising_edge(aclk) and tvalid = '1'; - - check_log(mocklogger, "TDATA mismatch, check non-blocking - Got 0000_0011 (3). Expected 0000_0110 (6).", error); - check_log(mocklogger, "TLAST mismatch, check non-blocking - Got 1. Expected 0.", error); - check_log(mocklogger, "TKEEP mismatch, check non-blocking - Got 0 (0). Expected 1 (1).", error); - check_log(mocklogger, "TSTRB mismatch, check non-blocking - Got 0 (0). Expected 1 (1).", error); - check_log(mocklogger, "TID mismatch, check non-blocking - Got 0010_1010 (42). Expected 0010_1100 (44).", error); - check_log(mocklogger, "TDEST mismatch, check non-blocking - Got 0000_0100 (4). Expected 0000_0101 (5).", error); - check_log(mocklogger, "TUSER mismatch, check non-blocking - Got 0000_0111 (7). Expected 0000_1000 (8).", error); - - unmock(mocklogger); - - check_equal(now, timestamp + 20 ns, " transaction time incorrect"); - - end if; - test_runner_cleanup(runner); - end process; - test_runner_watchdog(runner, 10 ms); - - axi_stream_master_inst : entity work.axi_stream_master - generic map( - master => master_axi_stream) - port map( - aclk => aclk, - areset_n => areset_n, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tuser => tuser, - tdest => tdest); - - not_valid <= not tvalid; - - not_valid_data <= '1' when tdata = std_logic_vector'("XXXXXXXX") else '0'; - check_true(aclk, not_valid, not_valid_data, "Invalid data not X"); - not_valid_keep <= '1' when tkeep = std_logic_vector'("X") else '0'; - check_true(aclk, not_valid, not_valid_keep, "Invalid keep not X"); - not_valid_strb <= '1' when tstrb = std_logic_vector'("X") else '0'; - check_true(aclk, not_valid, not_valid_strb, "Invalid strb not X"); - not_valid_id <= '1' when tid = std_logic_vector'("XXXXXXXX") else '0'; - check_true(aclk, not_valid, not_valid_id, "Invalid id not X"); - not_valid_dest <= '1' when tdest = std_logic_vector'("XXXXXXXX") else '0'; - check_true(aclk, not_valid, not_valid_dest, "Invalid dest not X"); - not_valid_user <= '1' when tuser = std_logic_vector'("00000000") else '0'; - check_true(aclk, not_valid, not_valid_user, "Invalid user not 0"); - - axi_stream_slave_inst : entity work.axi_stream_slave - generic map( - slave => slave_axi_stream) - port map( - aclk => aclk, - areset_n => areset_n, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tuser => tuser, - tdest => tdest); - - axi_stream_monitor_inst : entity work.axi_stream_monitor - generic map( - monitor => monitor - ) - port map( - aclk => aclk, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - - axi_stream_protocol_checker_inst : entity work.axi_stream_protocol_checker - generic map( - protocol_checker => protocol_checker) - port map( - aclk => aclk, - areset_n => areset_n, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - - aclk <= not aclk after 5 ns; -end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream_protocol_checker.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream_protocol_checker.vhd deleted file mode 100644 index bfd3fe8c7..000000000 --- a/vunit/vhdl/verification_components/test/tb_axi_stream_protocol_checker.vhd +++ /dev/null @@ -1,619 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -context work.vunit_context; -context work.com_context; -context work.data_types_context; -use work.axi_stream_pkg.all; -use work.stream_master_pkg.all; -use work.stream_slave_pkg.all; -use work.runner_pkg.all; - -entity tb_axi_stream_protocol_checker is - generic( - runner_cfg : string; - data_length : natural := 8; - id_length : natural := 4; - dest_length : natural := 4; - user_length : natural := 8; - max_waits : natural := 16); -end entity; - -architecture a of tb_axi_stream_protocol_checker is - signal aclk : std_logic := '0'; - signal areset_n : std_logic := '1'; - signal tvalid : std_logic := '0'; - signal tready : std_logic := '0'; - signal tdata : std_logic_vector(data_length - 1 downto 0) := (others => '0'); - signal tlast : std_logic := '1'; - signal tdest : std_logic_vector(dest_length - 1 downto 0) := (others => '0'); - signal tid : std_logic_vector(id_length - 1 downto 0) := (others => '0'); - signal tstrb : std_logic_vector(data_length/8 - 1 downto 0) := (others => '0'); - signal tkeep : std_logic_vector(data_length/8 - 1 downto 0) := (others => '0'); - signal tuser : std_logic_vector(user_length - 1 downto 0) := (others => '0'); - - constant logger : logger_t := get_logger("protocol_checker"); - constant protocol_checker : axi_stream_protocol_checker_t := new_axi_stream_protocol_checker( - data_length => tdata'length, id_length => tid'length, dest_length => tdest'length, user_length => tuser'length, - logger => logger, actor => new_actor("protocol_checker"), max_waits => max_waits - ); - constant meta_values : std_logic_vector(1 to 5) := "-XWZU"; - constant valid_values : std_logic_vector(1 to 4) := "01LH"; - -begin - - main : process - variable rule_logger : logger_t; - - procedure pass_stable_test (signal d : out std_logic_vector) is - constant zeros : std_logic_vector(d'range) := (others => '0'); - constant ones : std_logic_vector(d'range) := (others => '1'); - constant highs: std_logic_vector(d'range) := (others => 'H'); - begin - wait until rising_edge(aclk); - d <= ones; - tready <= '1'; - wait until rising_edge(aclk); - d <= zeros; - wait until rising_edge(aclk); - d <= ones; - tready <= '0'; - wait until rising_edge(aclk); - d <= zeros; - wait until rising_edge(aclk); - - tvalid <= '1'; - d <= ones; - wait until rising_edge(aclk); - d <= highs; - wait until rising_edge(aclk); - tready <= '1'; - wait until rising_edge(aclk); - tvalid <= '0'; - end; - - procedure fail_stable_test ( - signal d : out std_logic_vector; - constant rname : string; constant sname : string; - constant szero : string; constant sone : string; - constant vzero : std_logic := '0'; constant vone : std_logic := '1' - ) is - constant zeros : std_logic_vector(d'range) := (others => vzero); - constant ones : std_logic_vector(d'range) := (others => vone); - variable rule_logger : logger_t; - begin - rule_logger := get_logger(get_name(logger) & rname); - mock(rule_logger); - - wait until rising_edge(aclk); - tvalid <= '1'; - wait until rising_edge(aclk); - d <= ones; - wait until rising_edge(aclk); - d <= zeros; - tready <= '1'; - wait until rising_edge(aclk); - tready <= '0'; - tvalid <= '0'; - wait until rising_edge(aclk); - - check_only_log( - rule_logger, - "Stability check failed for " & sname & " while waiting for tready - Got " & sone & " at 2nd active and enabled clock edge. Expected " & szero & ".", - error); - - wait until rising_edge(aclk); - tvalid <= '1'; - wait until rising_edge(aclk); - d <= ones; - tready <= '1'; - wait until rising_edge(aclk); - tready <= '0'; - tvalid <= '0'; - wait until rising_edge(aclk); - - check_only_log( - rule_logger, - "Stability check failed for " & sname & " while waiting for tready - Got " & sone & " at 2nd active and enabled clock edge. Expected " & szero & ".", - error); - - tvalid <= '1'; - wait until rising_edge(aclk); - tready <= '1'; - wait until rising_edge(aclk); - tready <= '0'; - wait until rising_edge(aclk); - d <= zeros; - tready <= '1'; - wait until rising_edge(aclk); - tready <= '0'; - tvalid <= '0'; - wait until rising_edge(aclk); - - check_log( - rule_logger, - "Stability check passed for " & sname & " while waiting for tready - Got " & sone & " for 2 active and enabled clock edges.", - pass); - check_only_log( - rule_logger, - "Stability check failed for " & sname & " while waiting for tready - Got " & szero & " at 2nd active and enabled clock edge. Expected " & sone & ".", - error); - - unmock(rule_logger); - end; - - procedure pass_unknown_test( - signal d : out std_logic_vector; - signal e1, e2 : out std_logic) is - begin - wait until rising_edge(aclk); - e1 <= '0'; - e2 <= '0'; - for i in meta_values'range loop - d <= (d'range => meta_values(i)); - wait until rising_edge(aclk); - end loop; - e1 <= '1'; - e2 <= '1'; - for i in valid_values'range loop - d <= (d'range => valid_values(i)); - wait until rising_edge(aclk); - end loop; - end; - - procedure fail_unknown_test( - signal d: out std_logic_vector; - signal e1, e2: out std_logic; - constant rname : string; constant sname : string; constant e1name : string - ) is - variable rule_logger : logger_t; - begin - rule_logger := get_logger(get_name(logger) & rname); - mock(rule_logger); - - -- need to disable these signals first, because there would be a log message for the first clock edge if enabled (happens with areset_n) - e1 <= '0'; - e2 <= '0'; - wait until rising_edge(aclk); - e1 <= '1'; - e2 <= '1'; - for i in meta_values'range loop - d <= (d'range => meta_values(i)); - wait until rising_edge(aclk); - wait for 1 ns; - check_only_log( - rule_logger, - "Not unknown check failed for " & sname & " when " & e1name & " is high - Got " & to_nibble_string(std_logic_vector'(d'range => meta_values(i))) & ".", - error); - end loop; - - unmock(rule_logger); - end; - - begin - test_runner_setup(runner, runner_cfg); - - if run("Test passing check of that tdata remains stable when tvalid is asserted and tready is low") then - pass_stable_test(tdata); - - elsif run("Test failing check of that tdata remains stable when tvalid is asserted and tready is low") then - fail_stable_test(tdata, ":rule 1", "tdata", "0000_0000 (0)", "1111_1111 (255)"); - - elsif run("Test passing check of that tlast remains stable when tvalid is asserted and tready is low") then - pass_stable_test(d(0) => tlast); - - elsif run("Test failing check of that tlast remains stable when tvalid is asserted and tready is low") then - fail_stable_test(d(0) => tlast, rname => ":rule 2", sname => "tlast", szero => "1", sone => "0", vzero => '1', vone => '0'); - - elsif run("Test passing check of that tvalid remains asserted until tready is high") then - wait until rising_edge(aclk); - tvalid <= '1'; - wait until rising_edge(aclk); - tvalid <= 'H'; - wait until rising_edge(aclk); - tready <= '1'; - wait until rising_edge(aclk); - tvalid <= '0'; - tready <= '0'; - wait until rising_edge(aclk); - - tvalid <= '1'; - tready <= 'H'; - wait until rising_edge(aclk); - tvalid <= '0'; - tready <= '0'; - - elsif run("Test failing check of that tvalid remains asserted until tready is high") then - rule_logger := get_logger(get_name(logger) & ":rule 3"); - mock(rule_logger); - - wait until rising_edge(aclk); - tvalid <= '1'; - wait until rising_edge(aclk); - tvalid <= '0'; - wait until rising_edge(aclk); - tready <= '1'; - wait until rising_edge(aclk); - tready <= '0'; - tvalid <= '0'; - wait until rising_edge(aclk); - - check_log( - rule_logger, - "Stability check failed for tvalid while waiting for tready - Got 0 " & "at 2nd active and enabled clock edge. Expected 1.", - error); - check_only_log( - rule_logger, - "Stability check failed for tvalid while waiting for tready - Got 0 " & "at 3rd active and enabled clock edge. Expected 1.", - error); - - wait until rising_edge(aclk); - tvalid <= '1'; - wait until rising_edge(aclk); - tvalid <= 'L'; - tready <= 'H'; - wait until rising_edge(aclk); - tready <= '0'; - tvalid <= '0'; - wait until rising_edge(aclk); - - check_only_log( - rule_logger, - "Stability check failed for tvalid while waiting for tready - Got L " & "at 2nd active and enabled clock edge. Expected 1.", - error); - - unmock(rule_logger); - - elsif run("Test passing check of that tready comes within max_waits after valid") then - wait until rising_edge(aclk); - tvalid <= '1'; - for i in 1 to max_waits loop - wait until rising_edge(aclk); - end loop; - tready <= '1'; - wait until rising_edge(aclk); - tvalid <= '0'; - tready <= '0'; - - elsif run("Test failing check of that tready comes within max_waits after valid") then - rule_logger := get_logger(get_name(logger) & ":rule 4"); - mock(rule_logger); - - wait until rising_edge(aclk); - tvalid <= 'H'; - for i in 1 to max_waits + 1 loop - wait until rising_edge(aclk); - end loop; - tready <= 'H'; - wait until rising_edge(aclk); - tvalid <= '0'; - tready <= '0'; - - check_only_log( - rule_logger, - "Check failed for performance - tready active " & to_string(max_waits + 1) & " clock cycles after tvalid. Expected <= " & to_string(max_waits) & " clock cycles.", - warning); - - unmock(rule_logger); - - elsif run("Test passing check of that tdata must not be unknown when tvalid is high") then - pass_unknown_test(tdata, tvalid, tready); - - elsif run("Test failing check of that tdata must not be unknown when tvalid is high") then - fail_unknown_test(tdata, tvalid, tready, ":rule 5", "tdata", "tvalid"); - - elsif run("Test passing check of that tlast must not be unknown when tvalid is high") then - wait until rising_edge(aclk); - for i in meta_values'range loop - tlast <= meta_values(i); - wait until rising_edge(aclk); - end loop; - - tvalid <= '1'; - tready <= '1'; - for i in valid_values'range loop - tlast <= valid_values(i); - wait until rising_edge(aclk); - end loop; - - elsif run("Test failing check of that tlast must not be unknown when tvalid is high") then - rule_logger := get_logger(get_name(logger) & ":rule 6"); - mock(rule_logger); - - wait until rising_edge(aclk); - tvalid <= '1'; - tready <= '1'; - for i in meta_values'range loop - tlast <= meta_values(i); - wait until rising_edge(aclk); - wait for 1 ns; - check_only_log( - rule_logger, - "Not unknown check failed for tlast when tvalid is high - Got " & to_string(meta_values(i)) & ".", - error); - end loop; - - unmock(rule_logger); - - elsif run("Test passing check of that tvalid must not be unknown unless in reset") then - wait until rising_edge(aclk); - areset_n <= '0'; - tready <= '1'; - for i in meta_values'range loop - tvalid <= meta_values(i); - wait until rising_edge(aclk); - end loop; - areset_n <= '1'; - tready <= '1'; - for i in valid_values'range loop - tvalid <= valid_values(i); - wait until rising_edge(aclk); - end loop; - - elsif run("Test failing check of that tvalid must not be unknown unless in reset") then - wait until rising_edge(aclk); - wait for 1 ns; - rule_logger := get_logger(get_name(logger) & ":rule 7"); - mock(rule_logger); - - for i in meta_values'range loop - tvalid <= meta_values(i); - wait until rising_edge(aclk); - wait for 1 ns; - check_only_log( - rule_logger, - "Not unknown check failed for tvalid when not in reset - Got " & to_string(meta_values(i)) & ".", - error); - end loop; - - unmock(rule_logger); - - elsif run("Test passing check of that tready must not be unknown unless in reset") then - wait until rising_edge(aclk); - areset_n <= '0'; - tvalid <= '1'; - for i in meta_values'range loop - tready <= meta_values(i); - wait until rising_edge(aclk); - end loop; - areset_n <= '1'; - tvalid <= '0'; - tready <= valid_values(1); - wait until rising_edge(aclk); - tvalid <= '1'; - for i in valid_values'range loop - tready <= valid_values(i); - wait until rising_edge(aclk); - end loop; - - elsif run("Test failing check of that tready must not be unknown unless in reset") then - rule_logger := get_logger(get_name(logger) & ":rule 8"); - mock(rule_logger); - - for i in meta_values'range loop - tready <= meta_values(i); - wait until rising_edge(aclk); - wait for 1 ns; - check_only_log( - rule_logger, - "Not unknown check failed for tready when not in reset - Got " & to_string(meta_values(i)) & ".", - error); - end loop; - - unmock(rule_logger); - - elsif run("Test passing check of that all packets are complete when the simulation ends") then - wait until rising_edge(aclk); - tvalid <= '1'; - tlast <= '0'; - tready <= '1'; - wait until rising_edge(aclk); - tready <= '0'; - wait until rising_edge(aclk); - tready <= '1'; - wait until rising_edge(aclk); - tvalid <= '0'; - wait until rising_edge(aclk); - tvalid <= '1'; - tlast <= '1'; - tready <= '1'; - wait until rising_edge(aclk); - - elsif run("Test failing check of that all packets are complete when the simulation ends") then - wait until rising_edge(aclk); - rule_logger := get_logger(get_name(logger) & ":rule 9"); - mock(rule_logger); - - wait until rising_edge(aclk); - tvalid <= '1'; - tlast <= '0'; - tready <= '1'; - wait until rising_edge(aclk); - tlast <= '0'; - wait until rising_edge(aclk); - - set_phase(runner_state, test_runner_cleanup); - notify(runner); - entry_gate(runner); - - check_only_log(rule_logger, "Unconditional check failed for packet completion for the following streams: 0.", error); - - unmock(rule_logger); - - elsif run("Test passing check of that tuser must not be unknown unless in reset") then - pass_unknown_test(tuser, areset_n, areset_n); - - elsif run("Test failing check of that tuser must not be unknown unless in reset") then - fail_unknown_test(tuser, areset_n, areset_n, ":rule 10", "tuser", "areset_n"); - - elsif run("Test passing check of that tuser remains stable when tvalid is asserted and tready is low") then - pass_stable_test(tuser); - - elsif run("Test failing check of that tuser remains stable when tvalid is asserted and tready is low") then - fail_stable_test(tuser, ":rule 11", "tuser", "0000_0000 (0)", "1111_1111 (255)"); - - elsif run("Test passing check of that tid remains stable when tvalid is asserted and tready is low") then - pass_stable_test(tid); - - elsif run("Test failing check of that tid remains stable when tvalid is asserted and tready is low") then - fail_stable_test(tid, ":rule 12", "tid", "0000 (0)", "1111 (15)"); - - elsif run("Test passing check of that tdest remains stable when tvalid is asserted and tready is low") then - pass_stable_test(tdest); - - elsif run("Test failing check of that tdest remains stable when tvalid is asserted and tready is low") then - fail_stable_test(tdest, ":rule 13", "tdest", "0000 (0)", "1111 (15)"); - - elsif run("Test passing check of that tstrb remains stable when tvalid is asserted and tready is low") then - tkeep <= (others => '1'); - pass_stable_test(tstrb); - - elsif run("Test failing check of that tstrb remains stable when tvalid is asserted and tready is low") then - tkeep <= (others => '1'); - fail_stable_test(tstrb, ":rule 14", "tstrb", "0", "1"); - - elsif run("Test passing check of that tkeep remains stable when tvalid is asserted and tready is low") then - pass_stable_test(tkeep); - - elsif run("Test failing check of that tkeep remains stable when tvalid is asserted and tready is low") then - fail_stable_test(tkeep, ":rule 15", "tkeep", "0", "1"); - - elsif run("Test passing check of that tid must not be unknown when tvalid is high") then - pass_unknown_test(tid, tvalid, tready); - - elsif run("Test failing check of that tid must not be unknown when tvalid is high") then - fail_unknown_test(tid, tvalid, tready, ":rule 16", "tid", "tvalid"); - - elsif run("Test passing check of that tdest must not be unknown when tvalid is high") then - pass_unknown_test(tdest, tvalid, tready); - - elsif run("Test failing check of that tdest must not be unknown when tvalid is high") then - fail_unknown_test(tdest, tvalid, tready, ":rule 17", "tdest", "tvalid"); - - elsif run("Test passing check of that tstrb must not be unknown when tvalid is high") then - tkeep <= (others => '1'); - pass_unknown_test(tstrb, tvalid, tready); - - elsif run("Test failing check of that tstrb must not be unknown when tvalid is high") then - tkeep <= (others => '1'); - fail_unknown_test(tstrb, tvalid, tready, ":rule 18", "tstrb", "tvalid"); - - elsif run("Test passing check of that tkeep must not be unknown when tvalid is high") then - pass_unknown_test(tkeep, tvalid, tready); - - elsif run("Test failing check of that tkeep must not be unknown when tvalid is high") then - fail_unknown_test(tkeep, tvalid, tready, ":rule 19", "tkeep", "tvalid"); - - elsif run("Test passing check of that tstrb must be de-asserted when tkeep is de-asserted") then - wait until rising_edge(aclk); - tvalid <= '1'; - tready <= '1'; - for b in tstrb'range loop - tkeep <= (others => '0'); - tkeep(b) <= '1'; - tstrb <= (others => '0'); - wait until rising_edge(aclk); - tstrb(b) <= '1'; - wait until rising_edge(aclk); - end loop; - - elsif run("Test failing check of that tstrb must be de-asserted when tkeep is de-asserted") then - rule_logger := get_logger(get_name(logger) & ":rule 20"); - mock(rule_logger); - - wait until rising_edge(aclk); - tvalid <= '1'; - tready <= '1'; - for b in tstrb'range loop - tkeep <= (others => '1'); - tkeep(b) <= '0'; - tstrb <= (others => '0'); - wait until rising_edge(aclk); - tstrb(b) <= '1'; - wait until rising_edge(aclk); - wait for 1 ns; - check_log( - rule_logger, - "True check passed for tstrb de-asserted when tkeep de-asserted", - pass); - check_only_log( - rule_logger, - "True check failed for tstrb de-asserted when tkeep de-asserted", - error); - end loop; - - unmock(rule_logger); - - elsif run("Test failing check of that the sum of tid width and tdest width must be less than 25") then - rule_logger := get_logger(get_name(logger) & ":rule 21"); - mock(rule_logger); - - wait for 1 ns; - check_only_log( - rule_logger, - "True check failed for tid width and tdest width together must be less than 25", - error); - - unmock(rule_logger); - - elsif run("Test passing check of that tvalid must be low just after areset_n goes high") then - areset_n <= '0'; - tvalid <= '0'; - wait until rising_edge(aclk); - areset_n <= '1'; - wait until rising_edge(aclk); - tvalid <= '1'; - wait until rising_edge(aclk); - - elsif run("Test failing check of that tvalid must be low just after areset_n goes high") then - rule_logger := get_logger(get_name(logger) & ":rule 22"); - mock(rule_logger); - - areset_n <= '0'; - tvalid <= '0'; - wait until rising_edge(aclk); - areset_n <= '1'; - tvalid <= '1'; - wait until rising_edge(aclk); - wait for 1 ns; - check_only_log( - rule_logger, - "Implication check failed for tvalid de-asserted after reset release", - error); - - unmock(rule_logger); - - end if; - - test_runner_cleanup(runner); - end process; - - test_runner_watchdog(runner, 10 ms); - - axi_stream_protocol_checker_inst : entity work.axi_stream_protocol_checker - generic map( - protocol_checker => protocol_checker - ) - port map( - aclk => aclk, - areset_n => areset_n, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - - aclk <= not aclk after 5 ns; -end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_axi_write_slave.vhd b/vunit/vhdl/verification_components/test/tb_axi_write_slave.vhd deleted file mode 100644 index 09e4ba528..000000000 --- a/vunit/vhdl/verification_components/test/tb_axi_write_slave.vhd +++ /dev/null @@ -1,639 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library vunit_lib; -context vunit_lib.vunit_context; -context work.com_context; -use work.axi_pkg.all; -context work.vc_context; - -use work.integer_vector_ptr_pkg.all; -use work.random_pkg.all; - -library osvvm; -use osvvm.RandomPkg.all; - -entity tb_axi_write_slave is - generic (runner_cfg : string); -end entity; - -architecture a of tb_axi_write_slave is - signal clk : std_logic := '1'; - - constant log_data_size : integer := 4; - constant data_size : integer := 2**log_data_size; - - signal awvalid : std_logic := '0'; - signal awready : std_logic; - signal awid : std_logic_vector(3 downto 0); - signal awaddr : std_logic_vector(31 downto 0); - signal awlen : axi4_len_t; - signal awsize : axi4_size_t; - signal awburst : axi_burst_type_t; - - signal wvalid : std_logic; - signal wready : std_logic := '0'; - signal wdata : std_logic_vector(8*data_size-1 downto 0); - signal wstrb : std_logic_vector(data_size downto 0); - signal wlast : std_logic; - - signal bvalid : std_logic := '0'; - signal bready : std_logic; - signal bid : std_logic_vector(awid'range); - signal bresp : axi_resp_t; - - constant memory : memory_t := new_memory; - constant axi_slave : axi_slave_t := new_axi_slave(memory => memory); - -begin - main : process - variable buf : buffer_t; - variable rnd : RandomPType; - - procedure read_response(id : std_logic_vector; - resp : axi_resp_t := axi_resp_okay) is - begin - bready <= '1'; - wait until (bvalid and bready) = '1' and rising_edge(clk); - check_equal(bresp, resp, "bresp"); - check_equal(bid, id, "bid"); - bready <= '0'; - end procedure; - - - procedure write_addr(id : std_logic_vector; - addr : natural; - len : natural; - log_size : natural; - burst : axi_burst_type_t) is - begin - awvalid <= '1'; - awid <= id; - awaddr <= std_logic_vector(to_unsigned(addr, awaddr'length)); - awlen <= std_logic_vector(to_unsigned(len-1, awlen'length)); - awsize <= std_logic_vector(to_unsigned(log_size, awsize'length)); - awburst <= burst; - - wait until (awvalid and awready) = '1' and rising_edge(clk); - awvalid <= '0'; - end procedure; - - procedure transfer_data(id : std_logic_vector; - buf : buffer_t; - log_size : natural; - data : integer_vector_ptr_t) is - variable size, len, address, idx : natural; - begin - size := 2**log_size; - len := (length(data) + (base_address(buf) mod size)) / data_size; - write_addr(id, base_address(buf), len, log_size, axi_burst_type_incr); - - address := base_address(buf); - for j in 0 to len-1 loop - wstrb <= (others => '0'); - for i in 0 to size-1-(address mod data_size) loop - idx := address mod data_size; - wstrb(idx) <= '1'; - wdata(8*idx+7 downto 8*idx) <= std_logic_vector(to_unsigned(get(data, address - base_address(buf)), 8)); - set_permissions(memory, address, write_only); - set_expected_byte(memory, address, get(data, address - base_address(buf))); - address := address + 1; - end loop; - - if j = len-1 then - wlast <= '1'; - else - wlast <= '0'; - end if; - - wvalid <= '1'; - wait until (wvalid and wready) = '1' and rising_edge(clk); - wvalid <= '0'; - wstrb <= (others => '0'); - wdata <= (others => '0'); - end loop; - end procedure; - - procedure transfer(id : std_logic_vector; - buf : buffer_t; - log_size : natural; - data : integer_vector_ptr_t) is - begin - transfer_data(id, buf, log_size, data); - read_response(id, axi_resp_okay); - check_expected_was_written(buf); - end procedure; - - variable data : integer_vector_ptr_t; - variable strb : integer_vector_ptr_t; - variable size, log_size : natural; - variable id : std_logic_vector(awid'range); - variable len : natural; - variable burst : axi_burst_type_t; - variable idx : integer; - variable num_ops : integer; - variable start_time, diff_time : time; - - constant dummy_byte : natural := 13; - constant large_latency : time := 1 us; - begin - test_runner_setup(runner, runner_cfg); - rnd.InitSeed(rnd'instance_name); - - if run("Test random writes") then - num_ops := 0; - for test_idx in 0 to 32-1 loop - - id := rnd.RandSlv(awid'length); - case rnd.RandInt(1) is - when 0 => - burst := axi_burst_type_fixed; - len := 1; - when 1 => - burst := axi_burst_type_incr; - len := rnd.RandInt(1, 2**awlen'length); - when others => - assert false; - end case; - - log_size := rnd.RandInt(0, 3); - size := 2**log_size; - random_integer_vector_ptr(rnd, data, size * len, 0, 255); - random_integer_vector_ptr(rnd, strb, length(data), 0, 1); - - buf := allocate(memory, 8 * len, alignment => 4096); - for i in 0 to length(data)-1 loop - if get(strb, i) = 1 then - set_expected_byte(memory, base_address(buf)+i, get(data, i)); - num_ops := num_ops + 1; - else - set_permissions(memory, base_address(buf)+i, no_access); - end if; - end loop; - - write_addr(id, base_address(buf), len, log_size, burst); - - - for j in 0 to len-1 loop - for i in 0 to size-1 loop - idx := (base_address(buf) + j*size + i) mod data_size; - wdata(8*idx+7 downto 8*idx) <= std_logic_vector(to_unsigned(get(data, j*size + i), 8)); - wstrb(idx downto idx) <= std_logic_vector(to_unsigned(get(strb, j*size + i), 1)); - end loop; - - if j = len-1 then - wlast <= '1'; - else - wlast <= '0'; - end if; - - wvalid <= '1'; - wait until (wvalid and wready) = '1' and rising_edge(clk); - wvalid <= '0'; - wstrb <= (others => '0'); - wdata <= (others => '0'); - end loop; - - read_response(id, axi_resp_okay); - check_expected_was_written(buf); - end loop; - - assert num_ops > 5000; - - elsif run("Test that permissions are checked") then - -- Also check that memory errors are made to the axi slave logger - buf := allocate(memory, data_size, permissions => no_access); - write_addr(x"0", base_address(buf), 1, log_data_size, axi_burst_type_fixed); - - wvalid <= '1'; - wlast <= '1'; - wstrb <= (0 => '1', others => '0'); - wdata <= (others => '0'); - mock(axi_slave_logger, failure); - wait until (wvalid and wready) = '1' and rising_edge(clk); - wait until mock_queue_length > 0 and rising_edge(clk); - check_only_log(axi_slave_logger, - "Writing to address 0 at offset 0 within anonymous buffer at range (0 to 15) without permission (no_access)", - failure); - unmock(axi_slave_logger); - wvalid <= '0'; - wlast <= '0'; - wstrb <= (others => '0'); - wdata <= (others => '0'); - - elsif run("Test data stall probability") then - for i in 0 to 4 loop - if i = 2 then - set_data_stall_probability(net, axi_slave, 0.9); - else - set_data_stall_probability(net, axi_slave, 0.0); - end if; - - log_size := log_data_size; - size := 2**log_size; - random_integer_vector_ptr(rnd, data, size * 128, 0, 255); - buf := allocate(memory, length(data), permissions => no_access); - start_time := now; - transfer(x"2", buf, log_size, data); - info("diff_time := " & to_string(now - start_time)); - - if i = 1 or i = 4 then - -- First two and last two runs should have the same time with 0.0 - -- stall probability - check_equal(diff_time, now - start_time); - elsif i = 2 then - -- Middle run should have larger time - check(5*diff_time < now - start_time); - end if; - - diff_time := now - start_time; - end loop; - - elsif run("Test response latency") then - for i in 0 to 1 loop - if i = 1 then - set_response_latency(net, axi_slave, large_latency); - end if; - - log_size := log_data_size; - size := 2**log_size; - random_integer_vector_ptr(rnd, data, size * 128, 0, 255); - buf := allocate(memory, length(data), permissions => no_access); - - -- Write known value to memory so that we can check that it has not - -- been changed to early when response latency is high - for addr in base_address(buf) to last_address(buf) loop - write_byte(memory, addr, dummy_byte); - end loop; - - start_time := now; - transfer_data(x"2", buf, log_size, data); - - if i = 1 then - wait for (large_latency - 10 ns); - -- Check that data was not set yet - for addr in base_address(buf) to last_address(buf) loop - check_equal(read_byte(memory, addr), dummy_byte, "Data should not be set yet"); - end loop; - end if; - read_response(x"2", axi_resp_okay); - check_expected_was_written(buf); - info("diff_time := " & to_string(now - start_time)); - - if i = 1 then - check_equal(diff_time + large_latency, now - start_time); - end if; - - diff_time := now - start_time; - end loop; - - elsif run("Test write response stall probability") then - for i in 0 to 4 loop - if i = 2 then - set_write_response_stall_probability(net, axi_slave, 0.95); - else - set_write_response_stall_probability(net, axi_slave, 0.0); - end if; - - log_size := log_data_size; - size := 2**log_size; - random_integer_vector_ptr(rnd, data, size, 0, 255); - buf := allocate(memory, length(data), permissions => no_access); - start_time := now; - for j in 0 to 128 loop - transfer(x"2", buf, log_size, data); - end loop; - - info("diff_time := " & to_string(now - start_time)); - - if i = 1 or i = 4 then - -- First two and last two runs should have the same time with 0.0 - -- stall probability - check_equal(diff_time, now - start_time); - elsif i = 2 then - -- Middle run should have larger time - check(5*diff_time < now - start_time); - end if; - - diff_time := now - start_time; - end loop; - - elsif run("Test narrow write") then - -- Half bus width starting at aligned address - len := 2; - log_size := log_data_size - 1; - size := 2**log_size; - random_integer_vector_ptr(rnd, data, size * 2, 0, 255); - buf := allocate(memory, length(data), permissions => no_access); - transfer(x"2", buf, log_size, data); - - elsif run("Test unaligned narrow write") then - -- Half bus width starting at unaligned address - log_size := log_data_size - 1; - size := 2**log_size; - buf := allocate(memory, 1); -- Unaligned address - random_integer_vector_ptr(rnd, data, size * 2, 0, 255); - buf := allocate(memory, length(data), permissions => no_access); - transfer(x"2", buf, log_size, data); - - elsif run("Test unaligned write") then - -- Full bus width starting at unaligned address - len := 2; - log_size := log_data_size; - size := 2**log_size; - buf := allocate(memory, 1); -- Unaligned address - random_integer_vector_ptr(rnd, data, size * 2, 0, 255); - buf := allocate(memory, length(data), permissions => no_access); - transfer(x"2", buf, log_size, data); - - elsif run("Test error on missing tlast fixed") then - mock(axi_slave_logger, failure); - - buf := allocate(memory, 8); - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_fixed); - wvalid <= '1'; - wait until (wvalid and wready) = '1' and rising_edge(clk); - wvalid <= '0'; - - wait until mock_queue_length > 0 and rising_edge(clk); - check_only_log(axi_slave_logger, - "Expected wlast='1' on last beat of burst #0 for id 2 with length 1 starting at address 0", - failure); - unmock(axi_slave_logger); - read_response(x"2", axi_resp_okay); - - elsif run("Test error on missing tlast incr") then - buf := allocate(memory, 8); - write_addr(x"3", base_address(buf), 2, 0, axi_burst_type_incr); - - wvalid <= '1'; - wait until (wvalid and wready) = '1' and rising_edge(clk); - wvalid <= '0'; - wait until wvalid = '0' and rising_edge(clk); - - mock(axi_slave_logger, failure); - - wvalid <= '1'; - wait until (wvalid and wready) = '1' and rising_edge(clk); - wvalid <= '0'; - wait until mock_queue_length > 0 and rising_edge(clk); - - check_only_log(axi_slave_logger, - "Expected wlast='1' on last beat of burst #0 for id 3 with length 2 starting at address 0", - failure); - unmock(axi_slave_logger); - read_response(x"3", axi_resp_okay); - - elsif run("Test error on unsupported wrap burst") then - mock(axi_slave_logger, failure); - buf := allocate(memory, 8); - write_addr(x"2", base_address(buf), 2, 0, axi_burst_type_wrap); - wait until mock_queue_length > 0 and rising_edge(clk); - check_only_log(axi_slave_logger, "Wrapping burst type not supported", failure); - unmock(axi_slave_logger); - - elsif run("Test error 4KByte boundary crossing") then - buf := allocate(memory, 4096+32, alignment => 4096); - mock(axi_slave_logger, failure); - write_addr(x"2", base_address(buf)+4000, 256, 0, axi_burst_type_incr); - wait until mock_queue_length > 0 and rising_edge(clk); - check_only_log(axi_slave_logger, "Crossing 4KByte boundary. First page = 0 (4000/4096), last page = 1 (4255/4096)", failure); - unmock(axi_slave_logger); - - elsif run("Test no error on 4KByte boundary crossing with disabled check") then - buf := allocate(memory, 4096+32, alignment => 4096); - disable_4kbyte_boundary_check(net, axi_slave); - write_addr(x"2", base_address(buf)+4000, 256, 0, axi_burst_type_incr); - wait until awvalid = '0' and rising_edge(clk); - - elsif run("Test default address depth is 1") then - write_addr(x"2", 0, 1, 0, axi_burst_type_incr); -- Taken data process - write_addr(x"2", 0, 1, 0, axi_burst_type_incr); -- In the queue - for i in 0 to 127 loop - wait until rising_edge(clk); - assert awready = '0' report "Can only have one address in the queue"; - end loop; - - elsif run("Test set address fifo depth") then - set_address_fifo_depth(net, axi_slave, 16); - - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- Taken data process - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- In the queue - end loop; - - for i in 0 to 127 loop - wait until rising_edge(clk); - assert awready = '0' report "Address queue should be full"; - end loop; - - elsif run("Test changing address depth to smaller than content gives error") then - set_address_fifo_depth(net, axi_slave, 16); - - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- Taken data process - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); -- In the queue - end loop; - - set_address_fifo_depth(net, axi_slave, 17); - set_address_fifo_depth(net, axi_slave, 16); - - mock(axi_slave_logger, failure); - - set_address_fifo_depth(net, axi_slave, 1); - check_only_log(axi_slave_logger, "New address fifo depth 1 is smaller than current content size 16", failure); - unmock(axi_slave_logger); - - elsif run("Test address stall probability") then - set_address_fifo_depth(net, axi_slave, 128); - - start_time := now; - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); - end loop; - diff_time := now - start_time; - - set_address_stall_probability(net, axi_slave, 0.9); - start_time := now; - for i in 1 to 16 loop - write_addr(x"2", base_address(buf), 1, 0, axi_burst_type_incr); - end loop; - assert (now - start_time) > 5.0 * diff_time report "Should take about longer with stall probability"; - - elsif run("Test well behaved check does not fail for well behaved bursts") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - set_address_fifo_depth(net, axi_slave, 3); - set_write_response_fifo_depth(net, axi_slave, 3); - - bready <= '1'; - - wait until rising_edge(clk); - wvalid <= '1'; - wlast <= '1'; - assert wready = '0'; - -- Only allow non max size for single beat bursts - write_addr(x"0", base_address(buf), len => 1, log_size => log_data_size, burst => axi_burst_type_incr); - wvalid <= '1'; - wlast <= '1'; - assert wready = '0'; - write_addr(x"0", base_address(buf), len => 2, log_size => log_data_size, burst => axi_burst_type_incr); - wvalid <= '1'; - wlast <= '0'; - assert wready = '1'; - write_addr(x"0", base_address(buf), len => 1, log_size => 0, burst => axi_burst_type_incr); - wvalid <= '1'; - wlast <= '1'; - assert wready = '1'; - wait until rising_edge(clk); - wvalid <= '1'; - wlast <= '1'; - assert wready = '1'; - wait until rising_edge(clk); - wvalid <= '0'; - wlast <= '0'; - assert wready = '1'; - wait until rising_edge(clk); - wvalid <= '0'; - wlast <= '0'; - assert wready = '0'; - wait until rising_edge(clk); - assert wready = '0'; - wait until rising_edge(clk); - assert wready = '0'; - wait until rising_edge(clk); - assert wready = '0'; - - elsif run("Test well behaved check does not fail after well behaved burst finished") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - bready <= '1'; - - wait until rising_edge(clk); - wvalid <= '1'; - wlast <= '0'; - assert wready = '0'; - -- Only allow non max size for single beat bursts - write_addr(x"0", base_address(buf), len => 3, log_size => log_data_size, burst => axi_burst_type_incr); - wvalid <= '1'; - wlast <= '0'; - assert wready = '0'; - wait until rising_edge(clk); - wvalid <= '1'; - wlast <= '0'; - assert wready = '1'; - wait until rising_edge(clk); - wvalid <= '1'; - wlast <= '1'; - assert wready = '1'; - wait until rising_edge(clk); - wvalid <= '0'; - wlast <= '0'; - assert wready = '1'; - wait until rising_edge(clk); - wvalid <= '0'; - wlast <= '0'; - assert wready = '0'; - wait until rising_edge(clk); - wvalid <= '0'; - wlast <= '0'; - wait until rising_edge(clk); - wvalid <= '0'; - wlast <= '0'; - assert wready = '0'; - - elsif run("Test well behaved check fails for ill behaved awsize") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - mock(axi_slave_logger, failure); - bready <= '1'; - - wait until rising_edge(clk); - wvalid <= '1'; - wlast <= '0'; - write_addr(x"0", base_address(buf), len => 2, log_size => 0, burst => axi_burst_type_incr); - check_only_log(axi_slave_logger, "Burst not well behaved, axi size = 1 but bus data width allows " & to_string(data_size), failure); - unmock(axi_slave_logger); - - elsif run("Test well behaved check fails when wvalid not high during active burst") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - mock(axi_slave_logger, failure); - bready <= '1'; - wait until rising_edge(clk); - write_addr(x"0", base_address(buf), len => 2, log_size => log_data_size, burst => axi_burst_type_incr); - check_only_log(axi_slave_logger, "Burst not well behaved, vwalid was not high during active burst", failure); - unmock(axi_slave_logger); - - elsif run("Test well behaved check fails when bready not high during active burst") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - mock(axi_slave_logger, failure); - wvalid <= '1'; - wait until rising_edge(clk); - write_addr(x"0", base_address(buf), len => 2, log_size => log_data_size, burst => axi_burst_type_incr); - check_only_log(axi_slave_logger, "Burst not well behaved, bready was not high during active burst", failure); - unmock(axi_slave_logger); - - elsif run("Test well behaved check fails when wvalid not high during active burst and awready is low") then - buf := allocate(memory, 8); - enable_well_behaved_check(net, axi_slave); - mock(axi_slave_logger, failure); - set_address_stall_probability(net, axi_slave, 1.0); - bready <= '1'; - - wait until rising_edge(clk); - wait until rising_edge(clk); - assert awready = '0'; - - awvalid <= '1'; - awid <= x"0"; - awaddr <= std_logic_vector(to_unsigned(base_address(buf), awaddr'length)); - awlen <= std_logic_vector(to_unsigned(0, awlen'length)); - awsize <= std_logic_vector(to_unsigned(log_size, awsize'length)); - awburst <= axi_burst_type_incr; - - wait until rising_edge(clk); - assert awready = '0'; - wait until mock_queue_length > 0 for 0 ns; - - check_only_log(axi_slave_logger, "Burst not well behaved, vwalid was not high during active burst", failure); - unmock(axi_slave_logger); - - end if; - - test_runner_cleanup(runner); - end process; - test_runner_watchdog(runner, 1 ms); - - dut : entity work.axi_write_slave - generic map ( - axi_slave => axi_slave) - port map ( - aclk => clk, - awvalid => awvalid, - awready => awready, - awid => awid, - awaddr => awaddr, - awlen => awlen, - awsize => awsize, - awburst => awburst, - wvalid => wvalid, - wready => wready, - wdata => wdata, - wstrb => wstrb, - wlast => wlast, - bvalid => bvalid, - bready => bready, - bid => bid, - bresp => bresp); - - clk <= not clk after 5 ns; -end architecture; diff --git a/vunit/vhdl/verification_components/test/tb_uart.vhd b/vunit/vhdl/verification_components/test/tb_uart.vhd deleted file mode 100644 index ca3f3a389..000000000 --- a/vunit/vhdl/verification_components/test/tb_uart.vhd +++ /dev/null @@ -1,104 +0,0 @@ --- This Source Code Form is subject to the terms of the Mozilla Public --- License, v. 2.0. If a copy of the MPL was not distributed with this file, --- You can obtain one at http://mozilla.org/MPL/2.0/. --- --- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -context work.vunit_context; -context work.com_context; -context work.data_types_context; -use work.uart_pkg.all; -use work.sync_pkg.all; -use work.stream_master_pkg.all; -use work.stream_slave_pkg.all; - -entity tb_uart is - generic (runner_cfg : string); -end entity; - -architecture a of tb_uart is - constant master_uart : uart_master_t := new_uart_master; - constant master_stream : stream_master_t := as_stream(master_uart); - - constant slave_uart : uart_slave_t := new_uart_slave(data_length => 8); - constant slave_stream : stream_slave_t := as_stream(slave_uart); - - signal chan : std_logic; -begin - - main : process - variable data : std_logic_vector(7 downto 0); - variable reference_queue : queue_t := new_queue; - variable reference : stream_reference_t; - - procedure test_baud_rate(baud_rate : natural) is - variable start : time; - variable got, expected : time; - begin - set_baud_rate(net, master_uart, baud_rate); - set_baud_rate(net, slave_uart, baud_rate); - - start := now; - push_stream(net, master_stream, x"77"); - check_stream(net, slave_stream, x"77"); - - wait_until_idle(net, as_sync(master_uart)); - - got := now - start; - expected := (10 * (1 sec)) / (baud_rate); - - check(abs (got - expected) <= 10 ns, - "Unexpected baud rate got " & to_string(got) & " expected " & to_string(expected)); - end; - begin - test_runner_setup(runner, runner_cfg); - - if run("test single push and pop") then - push_stream(net, master_stream, x"77"); - pop_stream(net, slave_stream, data); - check_equal(data, std_logic_vector'(x"77"), "pop stream data"); - - elsif run("test pop before push") then - for i in 0 to 7 loop - pop_stream(net, slave_stream, reference); - push(reference_queue, reference); - end loop; - - for i in 0 to 7 loop - push_stream(net, master_stream, - std_logic_vector(to_unsigned(i+1, data'length))); - end loop; - - for i in 0 to 7 loop - reference := pop(reference_queue); - await_pop_stream_reply(net, reference, data); - check_equal(data, to_unsigned(i+1, data'length)); - end loop; - - elsif run("test baud rate") then - test_baud_rate(2000); - test_baud_rate(7000); - test_baud_rate(200000); - end if; - - test_runner_cleanup(runner); - end process; - test_runner_watchdog(runner, 20 ms); - - uart_master_inst: entity work.uart_master - generic map ( - uart => master_uart) - port map ( - tx => chan); - - uart_slave_inst: entity work.uart_slave - generic map ( - uart => slave_uart) - port map ( - rx => chan); - -end architecture; diff --git a/vunit/vhdl/verification_components/vc_list.json b/vunit/vhdl/verification_components/vc_list.json new file mode 100644 index 000000000..d69be9b76 --- /dev/null +++ b/vunit/vhdl/verification_components/vc_list.json @@ -0,0 +1,10 @@ +{ + "AXI": { + "path": "vc_axi", + "remote": "https://github.com/VUnit/vc_axi" + }, + "UART": { + "path": "vc_uart", + "remote": "https://github.com/VUnit/vc_uart" + } +} \ No newline at end of file