Commit 9ef6f829 authored by Tristan Gingold's avatar Tristan Gingold

Add a testbench for generic_async_fifo_mixedw

parent 1c4e5bc6
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
action = "simulation"
sim_tool = "ghdl"
target = "xilinx"
syn_device = "xc6slx45t"
top_module = "tb_fifo"
files = [
top_module + ".vhd",
"tb_32_64.vhd", "tb_64_32.vhd", "tb_8_32.vhd", "tb_32_8_ahead.vhd",
]
modules = {
"local" : [
"../../../",
],
}
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-- Simple testbench for generic_async_fifo_mixedw
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_32_64 is
generic (g_show_ahead : boolean);
port (start : std_logic := '1';
done : out std_logic);
end;
architecture arch of tb_32_64 is
constant g_wr_width : natural := 32;
constant g_rd_width : natural := 64;
constant g_size : natural := 4;
signal rst_n, clk_wr, clk_rd, we, rd, full, empty : std_logic;
signal d : std_logic_vector(g_wr_width -1 downto 0);
signal q : std_logic_vector(g_rd_width-1 downto 0);
signal wr_count : std_logic_vector(3 downto 0);
signal rd_count : std_logic_vector(2 downto 0);
begin
dut: entity work.generic_async_fifo_mixedw
generic map (
g_wr_width => g_wr_width,
g_rd_width => g_rd_width,
g_size => g_size,
g_show_ahead => g_show_ahead,
g_memory_implementation_hint => open
)
port map (
rst_n_a_i => rst_n,
clk_wr_i => clk_wr,
d_i => d,
we_i => we,
wr_full_o => full,
wr_count_o => wr_count,
clk_rd_i => clk_rd,
q_o => q,
rd_i => rd,
rd_empty_o => empty,
rd_count_o => rd_count
);
process
procedure pulse_w is
begin
clk_wr <= '0';
wait for 5 ns;
clk_wr <= '1';
wait for 5 ns;
end pulse_w;
procedure pulse_r is
begin
clk_rd <= '0';
wait for 1 ns;
clk_rd <= '1';
wait for 1 ns;
end pulse_r;
begin
done <= '0';
if start /= '1' then
wait until start = '1';
end if;
rst_n <= '0';
we <= '0';
rd <= '0';
pulse_w;
pulse_r;
rst_n <= '1';
for i in 1 to 2 loop
pulse_w;
pulse_r;
end loop;
assert empty = '1' report "fifo must be empty after reset";
assert full = '0' report "fifo must not be full after reset";
assert unsigned(rd_count) = 0 report "rd_count must be 0 after reset";
assert unsigned(wr_count) = 0 report "wr_count must be 0 after reset";
d <= x"01_02_03_04";
we <= '1';
pulse_w;
d <= x"05_06_07_08";
pulse_w;
assert full = '0';
we <= '0';
while empty = '1' loop
pulse_w;
pulse_r;
end loop;
rd <= '1';
if not g_show_ahead then
pulse_r;
end if;
assert q = x"05_06_07_08_01_02_03_04";
if g_show_ahead then
pulse_r;
end if;
rd <= '0';
assert empty = '1';
report "End of 32_64 testbench";
done <= '1';
wait;
end process;
end arch;
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-- Simple testbench for generic_async_fifo_mixedw
-- Using 32b wr port, 8b rd port and show-ahead.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_32_8_ahead is
port (start : std_logic := '1';
done : out std_logic);
end;
architecture arch of tb_32_8_ahead is
constant g_wr_width : natural := 32;
constant g_rd_width : natural := 8;
constant g_size : natural := 4;
signal rst_n, clk_wr, clk_rd, we, rd, full, empty : std_logic;
signal d : std_logic_vector(g_wr_width -1 downto 0);
signal q : std_logic_vector(g_rd_width-1 downto 0);
signal wr_count : std_logic_vector(2 downto 0);
signal rd_count : std_logic_vector(4 downto 0);
begin
dut: entity work.generic_async_fifo_mixedw
generic map (
g_wr_width => g_wr_width,
g_rd_width => g_rd_width,
g_size => g_size,
g_show_ahead => True,
g_memory_implementation_hint => open
)
port map (
rst_n_a_i => rst_n,
clk_wr_i => clk_wr,
d_i => d,
we_i => we,
wr_full_o => full,
wr_count_o => wr_count,
clk_rd_i => clk_rd,
q_o => q,
rd_i => rd,
rd_empty_o => empty,
rd_count_o => rd_count
);
process
procedure pulse_w is
begin
clk_wr <= '0';
wait for 5 ns;
clk_wr <= '1';
wait for 5 ns;
end pulse_w;
procedure pulse_r is
begin
clk_rd <= '0';
wait for 1 ns;
clk_rd <= '1';
wait for 1 ns;
end pulse_r;
begin
done <= '0';
if start /= '1' then
wait until start = '1';
end if;
rst_n <= '0';
we <= '0';
rd <= '0';
pulse_w;
pulse_r;
rst_n <= '1';
for i in 1 to 2 loop
pulse_w;
pulse_r;
end loop;
assert empty = '1' report "fifo must be empty after reset";
assert full = '0' report "fifo must not be full after reset";
assert unsigned(rd_count) = 0 report "rd_count must be 0 after reset";
assert unsigned(wr_count) = 0 report "wr_count must be 0 after reset";
d <= x"04_03_02_01";
we <= '1';
pulse_w;
we <= '0';
for i in 1 to 4 loop
pulse_r;
pulse_w;
end loop;
assert empty = '0' report "fifo must not be empty after a write";
assert full = '0';
assert unsigned(rd_count) = 4 report "expect 4 bytes to be read";
assert unsigned(wr_count) = 1 report "expect 1 word written";
assert q = x"01" report "bad output";
rd <= '1';
pulse_r;
rd <= '0';
assert empty = '0';
assert unsigned(rd_count) >= 3 report "expect at least 3 bytes to be read";
assert q = x"02" report "bad output";
d <= x"08_07_06_05";
we <= '1';
pulse_w;
we <= '0';
rd <= '1';
pulse_r;
assert empty = '0';
assert unsigned(rd_count) >= 2 report "expect at least 2 bytes to be read";
assert q = x"03" report "bad output";
pulse_r;
assert empty = '0';
assert q = x"04" report "bad output";
pulse_r;
if empty = '1' then
-- Depends on propagation delays.
pulse_r;
end if;
assert empty = '0';
assert q = x"05" report "bad output";
-- Flush the fifo.
pulse_r;
assert empty = '0' and q = x"06";
pulse_r;
assert empty = '0' and q = x"07";
pulse_r;
assert empty = '0' and q = x"08";
pulse_r;
assert empty = '1' report "fifo should now be empty";
pulse_r;
assert unsigned(rd_count) = 0;
-- Propagation delay...
pulse_w;
pulse_w;
pulse_w;
assert unsigned(wr_count) = 0;
-- Fifo is empty, try to saturate it.
d <= x"84_83_82_81";
we <= '1';
pulse_w;
assert full = '0';
assert unsigned(wr_count) = 1;
d <= x"88_87_86_85";
pulse_w;
assert full = '0';
assert unsigned(wr_count) = 2;
d <= x"8c_8b_8a_89";
pulse_w;
assert full = '0';
assert unsigned(wr_count) = 3;
d <= x"90_8f_8e_8d";
pulse_w;
assert full = '1';
assert unsigned(wr_count) = 4;
report "End of 32_8_ahead testbench";
done <= '1';
wait;
end process;
end arch;
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-- Simple testbench for generic_async_fifo_mixedw
-- Using 32b wr port, 8b rd port and show-ahead.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_64_32 is
generic (g_show_ahead : boolean);
port (start : std_logic := '1';
done : out std_logic);
end;
architecture arch of tb_64_32 is
constant g_wr_width : natural := 64;
constant g_rd_width : natural := 32;
constant g_size : natural := 4;
signal rst_n, clk_wr, clk_rd, we, rd, full, empty : std_logic;
signal d : std_logic_vector(g_wr_width -1 downto 0);
signal q : std_logic_vector(g_rd_width-1 downto 0);
signal wr_count : std_logic_vector(2 downto 0);
signal rd_count : std_logic_vector(3 downto 0);
begin
dut: entity work.generic_async_fifo_mixedw
generic map (
g_wr_width => g_wr_width,
g_rd_width => g_rd_width,
g_size => g_size,
g_show_ahead => g_show_ahead,
g_memory_implementation_hint => open
)
port map (
rst_n_a_i => rst_n,
clk_wr_i => clk_wr,
d_i => d,
we_i => we,
wr_full_o => full,
wr_count_o => wr_count,
clk_rd_i => clk_rd,
q_o => q,
rd_i => rd,
rd_empty_o => empty,
rd_count_o => rd_count
);
process
procedure pulse_w is
begin
clk_wr <= '0';
wait for 5 ns;
clk_wr <= '1';
wait for 5 ns;
end pulse_w;
procedure pulse_r is
begin
clk_rd <= '0';
wait for 1 ns;
clk_rd <= '1';
wait for 1 ns;
end pulse_r;
begin
done <= '0';
if start /= '1' then
wait until start = '1';
end if;
rst_n <= '0';
we <= '0';
rd <= '0';
pulse_w;
pulse_r;
rst_n <= '1';
for i in 1 to 2 loop
pulse_w;
pulse_r;
end loop;
assert empty = '1' report "fifo must be empty after reset";
assert full = '0' report "fifo must not be full after reset";
assert unsigned(rd_count) = 0 report "rd_count must be 0 after reset";
assert unsigned(wr_count) = 0 report "wr_count must be 0 after reset";
d <= x"28_27_26_25_24_23_22_21";
we <= '1';
pulse_w;
we <= '0';
for i in 1 to 4 loop
pulse_r;
pulse_w;
end loop;
assert empty = '0' report "fifo must not be empty after a write";
assert full = '0';
assert unsigned(rd_count) = 2 report "expect 2 words to be read";
assert unsigned(wr_count) = 1 report "expect 1 8B word written";
rd <= '1';
if not g_show_ahead then
pulse_r;
end if;
assert empty = '0';
assert unsigned(rd_count) >= 1 report "expect at least 1 word to be read";
assert q = x"24_23_22_21" report "bad output";
pulse_r;
assert q = x"28_27_26_25" report "bad output";
if g_show_ahead then
pulse_r;
end if;
assert empty = '1' report "fifo should now be empty";
rd <= '0';
report "End of 64_32 testbench";
done <= '1';
wait;
end process;
end arch;
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-- Simple testbench for generic_async_fifo_mixedw
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_8_32 is
port (start : std_logic := '1';
done : out std_logic);
end;
architecture arch of tb_8_32 is
constant g_wr_width : natural := 8;
constant g_rd_width : natural := 32;
constant g_size : natural := 4;
signal rst_n, clk_wr, clk_rd, we, rd, full, empty : std_logic;
signal d : std_logic_vector(g_wr_width -1 downto 0);
signal q : std_logic_vector(g_rd_width-1 downto 0);
signal wr_count : std_logic_vector(4 downto 0);
signal rd_count : std_logic_vector(2 downto 0);
begin
dut: entity work.generic_async_fifo_mixedw
generic map (
g_wr_width => g_wr_width,
g_rd_width => g_rd_width,
g_size => g_size,
g_show_ahead => False,
g_memory_implementation_hint => open
)
port map (
rst_n_a_i => rst_n,
clk_wr_i => clk_wr,
d_i => d,
we_i => we,
wr_full_o => full,
wr_count_o => wr_count,
clk_rd_i => clk_rd,
q_o => q,
rd_i => rd,
rd_empty_o => empty,
rd_count_o => rd_count
);
process
procedure pulse_w is
begin
clk_wr <= '0';
wait for 5 ns;
clk_wr <= '1';
wait for 5 ns;
end pulse_w;
procedure pulse_r is
begin
clk_rd <= '0';
wait for 1 ns;
clk_rd <= '1';
wait for 1 ns;
end pulse_r;
begin
done <= '0';
if start /= '1' then
wait until start = '1';
end if;
rst_n <= '0';
we <= '0';
rd <= '0';
pulse_w;
pulse_r;
rst_n <= '1';
for i in 1 to 2 loop
pulse_w;
pulse_r;
end loop;
assert empty = '1' report "fifo must be empty after reset";
assert full = '0' report "fifo must not be full after reset";
assert unsigned(rd_count) = 0 report "rd_count must be 0 after reset";
assert unsigned(wr_count) = 0 report "wr_count must be 0 after reset";
d <= x"01";
we <= '1';
pulse_w;
d <= x"02";
pulse_w;
d <= x"03";
pulse_w;
assert full = '0';
d <= x"04";
pulse_w;
we <= '0';
while empty = '1' loop
pulse_w;
pulse_r;
end loop;
rd <= '1';
pulse_r;
rd <= '0';
assert empty = '1';
assert q = x"04_03_02_01";
report "End of 8_32 testbench";
done <= '1';
wait;
end process;
end arch;
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-- Simple testbench for generic_async_fifo_mixedw
library ieee;
use ieee.std_logic_1164.all;
entity tb_fifo is
end;
architecture arch of tb_fifo is
signal start_32_64 : std_logic := '0';
signal done_32_64 : std_logic;
signal start_8_32 : std_logic := '0';
signal done_8_32 : std_logic;
signal start_32_8_a : std_logic := '0';
signal done_32_8_a : std_logic;
signal start_32_64_a : std_logic := '0';
signal done_32_64_a : std_logic;
signal start_64_32 : std_logic := '0';
signal done_64_32 : std_logic;
signal start_64_32_a : std_logic := '0';
signal done_64_32_a : std_logic;
begin
dut_8_32: entity work.tb_8_32
port map (start_8_32, done_8_32);
dut_32_8_a: entity work.tb_32_8_ahead
port map (start_32_8_a, done_32_8_a);
dut_32_64: entity work.tb_32_64
generic map (g_show_ahead => False)
port map (start_32_64, done_32_64);
dut_32_64_a: entity work.tb_32_64
generic map (g_show_ahead => False)
port map (start_32_64_a, done_32_64_a);
dut_64_32: entity work.tb_64_32
generic map (g_show_ahead => false)
port map (start_64_32, done_64_32);
dut_64_32_a: entity work.tb_64_32
generic map (g_show_ahead => True)
port map (start_64_32_a, done_64_32_a);
process
begin
wait for 1 ns;
start_8_32 <= '1';
wait until done_8_32 = '1';
wait for 10 ns;
start_32_8_a <= '1';
wait until done_32_8_a = '1';
wait for 10 ns;
start_32_64 <= '1';
wait until done_32_64 = '1';
wait for 10 ns;
start_32_64_a <= '1';
wait until done_32_64_a = '1';
wait for 10 ns;
start_64_32 <= '1';
wait until done_64_32 = '1';
wait for 10 ns;
start_64_32_a <= '1';
wait until done_64_32_a = '1';
wait for 8 ns;
wait;
end process;
end arch;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment