From 5151e1685d18cb4ea4176f141d39c7e7670ea748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 8 Oct 2023 20:36:53 +0200 Subject: [PATCH] Add input FIFO with TB --- rtl/flacdec_double_mem_fifo.vhd | 323 +++++++++++++++++++++++++++++ rtl/flacdec_input_fifo.vhd | 120 +++++++++++ rtl/mem/flacdec_64x08_memory.vhd | 58 ++++++ rtl/mem/flacdec_byte_fifo.vhd | 143 ------------- verif/.gitignore | 4 + verif/input_fifo_tb/poetry.lock | 188 +++++++++++++++++ verif/input_fifo_tb/pyproject.toml | 17 ++ verif/input_fifo_tb/results.xml | 33 +++ verif/input_fifo_tb/run.sh | 37 ++++ verif/input_fifo_tb/tb/__init__.py | 0 verif/input_fifo_tb/tb/tests.py | 91 ++++++++ 11 files changed, 871 insertions(+), 143 deletions(-) create mode 100644 rtl/flacdec_double_mem_fifo.vhd create mode 100644 rtl/flacdec_input_fifo.vhd create mode 100644 rtl/mem/flacdec_64x08_memory.vhd delete mode 100644 rtl/mem/flacdec_byte_fifo.vhd create mode 100644 verif/input_fifo_tb/poetry.lock create mode 100644 verif/input_fifo_tb/pyproject.toml create mode 100644 verif/input_fifo_tb/results.xml create mode 100755 verif/input_fifo_tb/run.sh create mode 100644 verif/input_fifo_tb/tb/__init__.py create mode 100644 verif/input_fifo_tb/tb/tests.py diff --git a/rtl/flacdec_double_mem_fifo.vhd b/rtl/flacdec_double_mem_fifo.vhd new file mode 100644 index 0000000..561d970 --- /dev/null +++ b/rtl/flacdec_double_mem_fifo.vhd @@ -0,0 +1,323 @@ +------------------------------------------------------------------------------- +-- Title : FIFO based on two single ported memory instances +-- Project : Shimatta VHDL FLAC decoder +------------------------------------------------------------------------------- +-- File : flacdec_double_mem_fifo.vhd +-- Author : Mario Huettel +-- Company : +-- Created : 2023-10-06 +-- Last update: 2023-10-07 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: This is a FIFO implementation based on two single ported memory +-- instances, which will allow continuous read/write with minimal arbitration +-- overhead. The memory instances have to be connected externally. +------------------------------------------------------------------------------- +-- Copyright (c) 2023 +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity flacdec_double_mem_fifo is + + generic ( + ADDRESS_WIDTH : natural range 2 to 32 := 7; -- Adress width of the whole FIFO memory. Defining the FIFO size + DATA_WIDTH : positive := 8); -- Data width in bits + + port ( + clk : in std_logic; -- Clock + rst_n : in std_logic; -- Async. low-active reset + ---------------------------------------------------------------------- + -- MEMORY 0 Connections + ---------------------------------------------------------------------- + mem0_address : out std_logic_vector(ADDRESS_WIDTH - 2 downto 0); + mem0_write_enable : out std_logic; + mem0_read_enable : out std_logic; + mem0_write_data : out std_logic_vector(DATA_WIDTH - 1 downto 0); + mem0_read_data : in std_logic_vector(DATA_WIDTH - 1 downto 0); + ---------------------------------------------------------------------- + -- MEMORY 1 Connections + ---------------------------------------------------------------------- + mem1_address : out std_logic_vector(ADDRESS_WIDTH - 2 downto 0); + mem1_write_enable : out std_logic; + mem1_read_enable : out std_logic; + mem1_write_data : out std_logic_vector(DATA_WIDTH - 1 downto 0); + mem1_read_data : in std_logic_vector(DATA_WIDTH - 1 downto 0); + ---------------------------------------------------------------------- + -- Input AXI Stream + ---------------------------------------------------------------------- + in_tdata : in std_logic_vector(DATA_WIDTH - 1 downto 0); + in_tvalid : in std_logic; + in_tready : out std_logic; + ---------------------------------------------------------------------- + -- Output AXI stream + ---------------------------------------------------------------------- + out_tdata : out std_logic_vector(DATA_WIDTH -1 downto 0); + out_tvalid : out std_logic; + out_tready : in std_logic; + ---------------------------------------------------------------------- + -- Control and status + ---------------------------------------------------------------------- + clear : in std_logic; + flush_output : in std_logic; + fill_level : out std_logic_vector(ADDRESS_WIDTH downto 0); + empty : out std_logic; + full : out std_logic; + half_empty : out std_logic); + +end entity flacdec_double_mem_fifo; + +architecture RTL of flacdec_double_mem_fifo is + + constant FIFO_SIZE : natural := 2**ADDRESS_WIDTH; + + signal accepted_input_reg : std_logic_vector(DATA_WIDTH - 1 downto 0); + signal accepted_input_valid_reg : std_logic; + signal in_tready_s : std_logic; + + signal out_tvalid_reg : std_logic; + signal out_tdata_buffer_reg : std_logic_vector(DATA_WIDTH - 1 downto 0); + signal out_tdata_buffer_valid_reg : std_logic; + signal fifo_read_out_data_s : std_logic_vector(DATA_WIDTH - 1 downto 0); + signal out_ready_for_data_s : std_logic; + + signal write_pointer_reg : unsigned(ADDRESS_WIDTH downto 0); + signal read_pointer_reg : unsigned(ADDRESS_WIDTH downto 0); + + signal write_address_s : std_logic_vector(ADDRESS_WIDTH - 1 downto 0); + signal read_address_s : std_logic_vector(ADDRESS_WIDTH - 1 downto 0); + + signal write_enable : std_logic; + signal read_enable : std_logic; + signal mem0_read_enable_s : std_logic; + signal mem1_read_enable_s : std_logic; + signal write_dest_mem : std_logic; + signal read_source_mem : std_logic; + signal read_data_valid_reg : std_logic_vector(1 downto 0); + + signal fifo_full_s : std_logic; + signal fifo_empty_s : std_logic; + signal fifo_half_empty_s : std_logic; + signal fifo_fill_level_s : integer range 0 to FIFO_SIZE; +begin -- architecture RTL + + full <= fifo_full_s; + empty <= fifo_empty_s; + half_empty <= fifo_half_empty_s; + fill_level <= std_logic_vector(to_unsigned(fifo_fill_level_s, fill_level'length)); + + in_tready <= in_tready_s; + + out_tvalid <= out_tvalid_reg; + + mem0_read_enable <= mem0_read_enable_s; + mem1_read_enable <= mem1_read_enable_s; + + mem0_address <= write_address_s(write_address_s'high downto 1) when mem0_read_enable_s = '0' else read_address_s(read_address_s'high downto 1); + mem1_address <= write_address_s(write_address_s'high downto 1) when mem1_read_enable_s = '0' else read_address_s(read_address_s'high downto 1); + + ------------------------------------------------------------------------------------------------------------------------------------------------- + -- Writing end implementation + ------------------------------------------------------------------------------------------------------------------------------------------------- + write_address_s <= std_logic_vector(write_pointer_reg(write_pointer_reg'high - 1 downto 0)); + + -- Let LSB decide which memory to write to + write_dest_mem <= write_pointer_reg(0); + mem0_write_enable <= write_enable when write_dest_mem = '0' else '0'; + mem1_write_enable <= write_enable when write_dest_mem = '1' else '0'; + + mem0_write_data <= accepted_input_reg; + mem1_write_data <= accepted_input_reg; + + write_enable_proc : process(accepted_input_valid_reg, write_dest_mem, mem0_read_enable_s, mem1_read_enable_s, fifo_full_s) is + begin + write_enable <= '0'; + + -- Perform write if write destination does not collide with current + -- read (This basically implements the arbitration between read and + -- write, giving priority to the read path). + if (write_dest_mem = '0' and mem0_read_enable_s = '0') or (write_dest_mem = '1' and mem1_read_enable_s = '0') then + -- Write if data is available and the FIFO may take new data + if accepted_input_valid_reg = '1' and fifo_full_s = '0' then + write_enable <= '1'; + end if; + end if; + end process write_enable_proc; + + -- Write pointer increment upon write action + write_pointer_proc : process(clk, rst_n) is + begin + if rst_n = '0' then + write_pointer_reg <= (others => '0'); + elsif rising_edge(clk) then + if clear = '1' then + write_pointer_reg <= (others => '0'); + elsif write_enable = '1' then + -- Overflow expected + write_pointer_reg <= write_pointer_reg + 1; + end if; + end if; + end process write_pointer_proc; + + ----------------------------------------------------------------- + -- AXI input + ---------------------------------------------------------------- + + -- Generate the ready signal for the input stream + axi_input_ready_proc : process(accepted_input_valid_reg, write_enable, clear) is + begin + in_tready_s <= '0'; + + if accepted_input_valid_reg = '0' then + in_tready_s <= '1'; + end if; + + if write_enable = '1' then + in_tready_s <= '1'; + end if; + + if clear = '1' then + in_tready_s <= '0'; + end if; + end process axi_input_ready_proc; + + -- Accept the input datum into a FF buffer + axi_input_proc : process(clk, rst_n) is + begin + if rst_n = '0' then + accepted_input_reg <= (others => '0'); + accepted_input_valid_reg <= '0'; + elsif rising_edge(clk) then + if write_enable = '1' or clear = '1' then + -- Reset input buffer once datum is written to memory + accepted_input_valid_reg <= '0'; + end if; + if in_tvalid = '1' and in_tready_s = '1' then + -- Accept datum in buffer + accepted_input_valid_reg <= '1'; + accepted_input_reg <= in_tdata; + end if; + end if; + end process axi_input_proc; + + ------------------------------------------------------------------------ + -- FIFO status calculations + ------------------------------------------------------------------------ + fill_level_proc : process(read_pointer_reg, write_pointer_reg) is + variable wrapped_around : boolean; + variable read_addr : integer range 0 to FIFO_SIZE - 1; + variable write_addr : integer range 0 to FIFO_SIZE - 1; + begin + wrapped_around := (read_pointer_reg(read_pointer_reg'high) /= write_pointer_reg(write_pointer_reg'high)); + write_addr := to_integer(write_pointer_reg(write_pointer_reg'high - 1 downto 0)); + read_addr := to_integer(read_pointer_reg(read_pointer_reg'high -1 downto 0)); + + if not wrapped_around then + fifo_fill_level_s <= write_addr - read_addr; + else + fifo_fill_level_s <= FIFO_SIZE - read_addr + write_addr; + end if; + end process fill_level_proc; + + fifo_full_s <= '1' when write_address_s = read_address_s and read_pointer_reg(read_pointer_reg'high) /= write_pointer_reg(write_pointer_reg'high) else '0'; + fifo_empty_s <= '1' when write_pointer_reg = read_pointer_reg else '0'; + fifo_half_empty_s <= '1' when fifo_fill_level_s <= FIFO_SIZE / 2 else '0'; + + ----------------------------------------------------------------------------------------------------------------------------------------------- + -- READ end implementation + ----------------------------------------------------------------------------------------------------------------------------------------------- + read_address_s <= std_logic_vector(read_pointer_reg(read_pointer_reg'high - 1 downto 0)); + read_source_mem <= read_address_s(0); + + mem0_read_enable_s <= read_enable when read_source_mem = '0' else '0'; + mem1_read_enable_s <= read_enable when read_source_mem = '1' else '0'; + + read_data_valid_proc : process(clk, rst_n) is + begin + if rst_n = '0' then + read_data_valid_reg <= (others => '0'); + elsif rising_edge(clk) then + -- Delay read enables by one cycle, generating a valid signal + read_data_valid_reg <= mem1_read_enable_s & mem0_read_enable_s; + end if; + end process read_data_valid_proc; + + -- Generate the read_enable signal + -- Read from fifo if it is not empty and the output is able to accept a new + -- datum. If clear is set, no read is requested. + read_enable_proc : process(fifo_empty_s, out_ready_for_data_s, clear) is + begin + read_enable <= '0'; + if fifo_empty_s = '0' and clear = '0' then + if out_ready_for_data_s = '1' then + read_enable <= '1'; + end if; + end if; + end process read_enable_proc; + + read_pointer_proc : process(clk, rst_n) is + begin + if rst_n = '0' then + read_pointer_reg <= (others => '0'); + elsif rising_edge(clk) then + if clear = '1' then + read_pointer_reg <= (others => '0'); + elsif read_enable = '1' then + -- Overflow expected + read_pointer_reg <= read_pointer_reg + 1; + end if; + end if; + end process read_pointer_proc; + + -------------------- + -- Output AXI stream + --------------------- + + -- Read data mux + fifo_read_out_data_s <= mem0_read_data when read_data_valid_reg(0) = '1' else mem1_read_data; + + -- Determine if output flops can be loaded with new data + out_ready_for_data_s <= (not out_tvalid_reg) or out_tready; + + axi_output_proc : process(clk, rst_n) is + begin + if rst_n = '0' then + out_tvalid_reg <= '0'; + out_tdata <= (others => '0'); + out_tdata_buffer_valid_reg <= '0'; + out_tdata_buffer_reg <= (others => '0'); + elsif rising_edge(clk) then + if out_tready = '1' then + out_tvalid_reg <= '0'; + end if; + + if flush_output = '1' then + -- Flush the output. This breaks the stream protocol! + out_tvalid_reg <= '0'; + out_tdata_buffer_valid_reg <= '0'; + else -- Output is not flushed + if out_ready_for_data_s = '1' then + if out_tdata_buffer_valid_reg = '1' then + out_tdata <= out_tdata_buffer_reg; + out_tvalid_reg <= '1'; + out_tdata_buffer_valid_reg <= '0'; + elsif read_data_valid_reg /= "00" then + out_tdata <= fifo_read_out_data_s; + out_tvalid_reg <= '1'; + end if; + end if; + + -- Fill buffer register, if output is not ready for data or + -- filled with old buffer data + if read_data_valid_reg /= "00" and ((out_ready_for_data_s = '1' and out_tdata_buffer_valid_reg = '1') or out_ready_for_data_s = '0') then + out_tdata_buffer_reg <= fifo_read_out_data_s; + out_tdata_buffer_valid_reg <= '1'; + end if; + end if; + end if; + end process axi_output_proc; + +end architecture RTL; diff --git a/rtl/flacdec_input_fifo.vhd b/rtl/flacdec_input_fifo.vhd new file mode 100644 index 0000000..d378ceb --- /dev/null +++ b/rtl/flacdec_input_fifo.vhd @@ -0,0 +1,120 @@ +------------------------------------------------------------------------------- +-- Title : Input FIFO for FLAC data +-- Project : Shimatta VHDL FLAC decoder +------------------------------------------------------------------------------- +-- File : flacdec_input_fifo.vhd +-- Author : Mario Huettel +-- Company : +-- Created : 2023-10-07 +-- Last update: 2023-10-07 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: 128 byte input FIFO of FLAC core +------------------------------------------------------------------------------- +-- Copyright (c) 2023 +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity flacdec_input_fifo is + + port ( + clk : in std_logic; -- CLock + rst_n : in std_logic; -- async. low-active reset + ------------------------------------------------ + -- Input AXI stream + ------------------------------------------------ + in_tdata : in std_logic_vector(7 downto 0); + in_tvalid : in std_logic; + in_tready : out std_logic; + ------------------------------------------------ + -- Output AXI Stream + ------------------------------------------------ + out_tdata : out std_logic_vector(7 downto 0); + out_tvalid : out std_logic; + out_tready : in std_logic; + ------------------------------------------------ + -- Control and status signals + ------------------------------------------------ + clear : in std_logic; + half_empty : out std_logic; + empty : out std_logic; + full : out std_logic; + flush_output : in std_logic); + +end entity flacdec_input_fifo; + +architecture RTL of flacdec_input_fifo is + constant ADDRESS_WIDTH : natural := 7; + constant DATA_WIDTH : natural := 8; + + signal mem0_address : std_logic_vector(ADDRESS_WIDTH - 2 downto 0); + signal mem0_write_enable : std_logic; + signal mem0_read_enable : std_logic; + signal mem0_write_data : std_logic_vector(DATA_WIDTH - 1 downto 0); + signal mem0_read_data : std_logic_vector(DATA_WIDTH - 1 downto 0); + signal mem1_address : std_logic_vector(ADDRESS_WIDTH - 2 downto 0); + signal mem1_write_enable : std_logic; + signal mem1_read_enable : std_logic; + signal mem1_write_data : std_logic_vector(DATA_WIDTH - 1 downto 0); + signal mem1_read_data : std_logic_vector(DATA_WIDTH - 1 downto 0); + +begin -- architecture RTL + + -- FIFO logic core + flacdec_double_mem_fifo_1 : entity work.flacdec_double_mem_fifo + generic map ( + ADDRESS_WIDTH => ADDRESS_WIDTH, + DATA_WIDTH => DATA_WIDTH) + port map ( + clk => clk, + rst_n => rst_n, + mem0_address => mem0_address, + mem0_write_enable => mem0_write_enable, + mem0_read_enable => mem0_read_enable, + mem0_write_data => mem0_write_data, + mem0_read_data => mem0_read_data, + mem1_address => mem1_address, + mem1_write_enable => mem1_write_enable, + mem1_read_enable => mem1_read_enable, + mem1_write_data => mem1_write_data, + mem1_read_data => mem1_read_data, + in_tdata => in_tdata, + in_tvalid => in_tvalid, + in_tready => in_tready, + out_tdata => out_tdata, + out_tvalid => out_tvalid, + out_tready => out_tready, + clear => clear, + flush_output => flush_output, + fill_level => open, + empty => empty, + full => full, + half_empty => half_empty); + + --------------------------------------------------------------- + -- Memory instances + --------------------------------------------------------------- + + flacdec_64x08_memory_i0 : entity work.flacdec_64x08_memory + port map ( + clk => clk, + address => mem0_address, + write_enable => mem0_write_enable, + read_enable => mem0_read_enable, + write_data => mem0_write_data, + read_data => mem0_read_data); + + flacdec_64x08_memory_i1 : entity work.flacdec_64x08_memory + port map ( + clk => clk, + address => mem1_address, + write_enable => mem1_write_enable, + read_enable => mem1_read_enable, + write_data => mem1_write_data, + read_data => mem1_read_data); + +end architecture RTL; diff --git a/rtl/mem/flacdec_64x08_memory.vhd b/rtl/mem/flacdec_64x08_memory.vhd new file mode 100644 index 0000000..f0568f9 --- /dev/null +++ b/rtl/mem/flacdec_64x08_memory.vhd @@ -0,0 +1,58 @@ +------------------------------------------------------------------------------- +-- Title : 64x08 byte single port memory +-- Project : Shimatta VHDL FLAC Decoder +------------------------------------------------------------------------------- +-- File : flacdec_64x08_memory.vhd +-- Author : Mario Huettel +-- Company : Shimatta +-- Created : 2023-10-06 +-- Last update: 2023-10-06 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: This is a 64 byte single ported RAM implementation. This file +-- should be able to infer a BRAM on FPGA targets. +-- Swap this implementation on an ASIC flow in order to instantiate a fitting +-- memory instance. +-- Two instances of this memory are used in the input FIFO of the Flac decoder +------------------------------------------------------------------------------- +-- Copyright (c) 2023 +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity flacdec_64x08_memory is + + port ( + clk : in std_logic; -- Clock + address : in std_logic_vector(5 downto 0); -- RAM data address + write_enable : in std_logic; -- Write enable + read_enable : in std_logic; -- Enable readout + write_data : in std_logic_vector(7 downto 0); -- Write data + read_data : out std_logic_vector(7 downto 0)); -- Read data + +end entity flacdec_64x08_memory; + +architecture RTL of flacdec_64x08_memory is + type memory_arr_t is array(natural range <>) of std_logic_vector(7 downto 0); + + signal mem : memory_arr_t(0 to 63); -- Memory array + signal addr_s : integer range 0 to 63; -- Memory access address +begin -- architecture RTL + + addr_s <= to_integer(unsigned(address)); + + memory_proc : process is + begin + wait until rising_edge(clk); + if write_enable = '1' then + mem(addr_s) <= write_data; + end if; + if read_enable = '1' then + read_data <= mem(addr_s); + end if; + end process memory_proc; + +end architecture RTL; diff --git a/rtl/mem/flacdec_byte_fifo.vhd b/rtl/mem/flacdec_byte_fifo.vhd deleted file mode 100644 index f9fe7e3..0000000 --- a/rtl/mem/flacdec_byte_fifo.vhd +++ /dev/null @@ -1,143 +0,0 @@ -------------------------------------------------------------------------------- --- Title : FIFO for 8 bit data --- Project : VHDL FLAC Decoder -------------------------------------------------------------------------------- --- File : flacdec_byte_fifo.vhd --- Author : Mario Huettel --- Company : --- Created : 2023-10-05 --- Last update: 2023-10-05 --- Platform : --- Standard : VHDL'93/02 -------------------------------------------------------------------------------- --- Description: This is a generic FIFO implementation for 8 bit Data. This --- implementation should be able to map to a dual ported BRAM in an FPGA. If an --- ASIC Design is used, decide weather to use a RAM instance or let the --- synthesis generate a FIFO out of Flip Flops. --- The FIFO is 64 bytes large. -------------------------------------------------------------------------------- --- Copyright (c) 2023 Mario Huettel -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity flacdec_byte_fifo is - - port ( - clk : in std_logic; -- Clock - rst_n : in std_logic; -- async. low-active reset - data_in : in std_logic_vector(7 downto 0); - data_in_wstrb : in std_logic; -- Write strobe to push data into the FIFO - data_out : out std_logic_vector(7 downto 0); -- Output data. 1 cycle delayed after read strobe. - data_rstrb : in std_logic; - fifo_full : out std_logic; -- FIFO is full - fifo_empty : out std_logic; -- FIFO is empty - fifo_32_free : out std_logic); -- FIFO has at least 32 bytes free - -end entity flacdec_byte_fifo; - -architecture RTL of flacdec_byte_fifo is - - type fifo_mem_t is array(natural range <>) of std_logic_vector(data_in'range); - - signal mem : fifo_mem_t(0 to 63); - signal read_ptr : unsigned(6 downto 0); - signal write_ptr : unsigned(6 downto 0); - - signal write_strb_s : std_logic; - signal read_strb_s : std_logic; - - signal write_addr : unsigned(5 downto 0); - signal read_addr : unsigned(5 downto 0); - signal fifo_fill_level : integer range 0 to 64; - signal wrapped_around : std_logic; - - signal fifo_full_s : std_logic; - signal fifo_empty_s : std_logic; -begin -- architecture RTL - - fifo_full <= fifo_full_s; - fifo_empty <= fifo_empty_s; - - -------------------------------------------------------------------------- - -- FIFO memory implementation - -------------------------------------------------------------------------- - - -- FIFO memory process. Should allow BRAM infer. - fifo_mem_proc : process is - begin - wait until rising_edge(clk); - if write_strb_s = '1' then - mem(to_integer(write_addr)) <= data_in; - end if; - - if read_strb_s = '1' then - data_out <= mem(to_integer(read_addr)); - end if; - end process fifo_mem_proc; - - -------------------------------------------------------------------------- - -- FIFO fill level and address logic - -------------------------------------------------------------------------- - -- Addresses to memory are the pointers except for the MSB, which is used - -- for wrap around detection - read_addr <= read_ptr(read_ptr'high - 1 downto read_ptr'low); - write_addr <= write_ptr(write_ptr'high - 1 downto write_ptr'low); - - wrapped_around <= '1' when read_ptr(read_ptr'high) /= write_ptr(write_ptr'high) else '0'; - - fill_level_proc : process(wrapped_around, read_addr, write_addr) is - begin - fifo_fill_level <= 0; - if wrapped_around = '0' then - fifo_fill_level <= to_integer(write_addr - read_addr); - else - fifo_fill_level <= to_integer(64 - read_addr + write_addr); - end if; - end process fill_level_proc; - - fifo_full_s <= '1' when read_addr = write_addr and wrapped_around = '1' else '0'; - fifo_empty_s <= '1' when read_addr = write_addr and wrapped_around = '0' else '0'; - fifo_32_free <= '1' when fifo_fill_level >= 32 else '0'; - - --------------------------------------------------------------------------- - -- FIFO write pointer - --------------------------------------------------------------------------- - - write_strb_s <= data_in_wstrb and (not fifo_full_s); - - write_ptr_proc : process(clk, rst_n) is - begin - if rst_n = '0' then - write_ptr <= (others => '0'); - elsif rising_edge(clk) then - if write_strb_s = '1' then - -- Wrap around expected - write_ptr <= write_ptr + 1; - end if; - end if; - end process write_ptr_proc; - - --------------------------------------------------------------------------- - -- FIFO read pointer - --------------------------------------------------------------------------- - - read_strb_s <= data_rstrb and (not fifo_empty_s); - - read_ptr_proc : process(clk, rst_n) is - begin - if rst_n = '0' then - read_ptr <= (others => '0'); - elsif rising_edge(clk) then - if read_strb_s = '1' then - -- Wrap around expected - read_ptr <= read_ptr + 1; - end if; - end if; - end process read_ptr_proc; - - -end architecture RTL; - diff --git a/verif/.gitignore b/verif/.gitignore index ad4a1f1..2f15aa4 100644 --- a/verif/.gitignore +++ b/verif/.gitignore @@ -9,6 +9,10 @@ __pycache__/ # C extensions *.so +*.o + +# Simulation waveforms +*.ghw # Distribution / packaging .Python diff --git a/verif/input_fifo_tb/poetry.lock b/verif/input_fifo_tb/poetry.lock new file mode 100644 index 0000000..6bf5d8e --- /dev/null +++ b/verif/input_fifo_tb/poetry.lock @@ -0,0 +1,188 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "cocotb" +version = "1.8.1" +description = "cocotb is a coroutine based cosimulation library for writing VHDL and Verilog testbenches in Python." +optional = false +python-versions = ">=3.6" +files = [ + {file = "cocotb-1.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06ae2b2d899095ee4fd4f9604e0fd3706102ef681659f8dc68e4faf6d990d89f"}, + {file = "cocotb-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8d642e1106750a519c015c651ec94a5d9008da0a29d39b2d073206bd60ce452"}, + {file = "cocotb-1.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de9d329e747048ae8d9c08794cc2ee48850b13c387d647227ff76ac2df184fcb"}, + {file = "cocotb-1.8.1-cp310-cp310-win32.whl", hash = "sha256:87cb47d81d6c55f64662512dda8088e5f430740a42feaa67f7b8e10bd249c02c"}, + {file = "cocotb-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:8b0643be8b1dee02453233a40ad94919f5781bcb08893689c99b9c7ab08695f3"}, + {file = "cocotb-1.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:708cb6fcb2ee00fe80bd45a03f2a202980d2b563dcb064c2f3c904c84e87e2b1"}, + {file = "cocotb-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a6d3d824c746410da8f294c34dcca820f1350c1639cafb4b6394844a07f7371"}, + {file = "cocotb-1.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3a9e442211691a3602dd8cce288e9b66f2bab220bc01d1b17e5f30db4a9622c"}, + {file = "cocotb-1.8.1-cp311-cp311-win32.whl", hash = "sha256:7d47c3aa3432575eb26f6783ef7832a6db873265fd40a89ade22599e59a784f6"}, + {file = "cocotb-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ffebe392a4f0cb757ccea51d4902db9abc537e57b9151c5ecc8b4f898ec7817"}, + {file = "cocotb-1.8.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9d70978a5c587fc26c66c3f0e8a5bc0545a70397cbfd15b342685fed38959fc1"}, + {file = "cocotb-1.8.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5692e56925de8d71ce8d379bd80a2e103fe0fba1e0c4c3b539b10eafe22fb6c1"}, + {file = "cocotb-1.8.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cbfb462315b12f157381c388f3ab5a074c0293e54852f8851152bf295bf6807"}, + {file = "cocotb-1.8.1-cp312-cp312-win32.whl", hash = "sha256:ac5fa8f47613c1487156d20fb09d4679566572922971ea922ec5acec38629fa9"}, + {file = "cocotb-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:b9e7a09d0f76115f02d9c957110d5970e759c2bc8d1d5a448716ed3a67a66367"}, + {file = "cocotb-1.8.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:34da6f570c584434e34fe98f1b03cd394c2e43302c85a5510c6aebc5bffd679a"}, + {file = "cocotb-1.8.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4f8f7401f107e04fb5f1c1bbb6a4434d11fff4bfe6871bea8a822b3ec91e7885"}, + {file = "cocotb-1.8.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2343642030caf03b707eb7ee665de3adcffab08c5884b40c363ae042e1aad3d4"}, + {file = "cocotb-1.8.1-cp36-cp36m-win32.whl", hash = "sha256:ab136393aa5776a9a6f25d94af62dd947791482d325516072288668741be934b"}, + {file = "cocotb-1.8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:1d3af65372ed044f27b69039325bf018738685e59be928fb4efde0c0e86b1ba0"}, + {file = "cocotb-1.8.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e8d9525a92312d8271fc612c98ce027d285c3f93925f63908c4e9af72a9ba5eb"}, + {file = "cocotb-1.8.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfa07a47e6b0654ed65e06b37b93316cc3afb7d9b52fe5c07579edd10bdb6281"}, + {file = "cocotb-1.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:298f4e3c0eafda1964112d050cf08827f5aa3c3759960bef1cdce1c57ce645d4"}, + {file = "cocotb-1.8.1-cp37-cp37m-win32.whl", hash = "sha256:174209743e2743a4c1adb885bb212bb40447464a54388cae360225cb4353499b"}, + {file = "cocotb-1.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:71a6a2e39596fe6f2094cc3d4fc35621a6c1e74ca70dc868973a71c6f77f3bdb"}, + {file = "cocotb-1.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f3a6f6f0fa5914c491d22d5796f15b5d0b152f76c071fecb3665af60b471bbe7"}, + {file = "cocotb-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1196ba5f341c4e6752e4db71e99932499980a907ec264387d75c6f37d3e09ab6"}, + {file = "cocotb-1.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1ba54da9217b2231d58a380b19f5bc749f6b1d1b21460bc0951d0c1317a2f5d"}, + {file = "cocotb-1.8.1-cp38-cp38-win32.whl", hash = "sha256:032569407d22b55a1d7acb07b1be12e2010e332c49d2c04404707d10d892cc27"}, + {file = "cocotb-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:b70d8c803c7215bd54249e53b2591b484346420168dd1cafdb2e0d27e214db11"}, + {file = "cocotb-1.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cbe760f6a0869140a7fa2124c295e2a4299300f0f839017e6b43ab4490bbc522"}, + {file = "cocotb-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2a05df85a5259654d2c10cc0ac8ad877b6ca986fb559a911a9207bcdbc887fd"}, + {file = "cocotb-1.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59cb5e35533b28301e1ff1858aabe1d6bac4305536d5fc40edb188dfda42e0ae"}, + {file = "cocotb-1.8.1-cp39-cp39-win32.whl", hash = "sha256:2824f26d15713056de44507017f88189419cf7b68252cedbdbed272ee753917f"}, + {file = "cocotb-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:797044b85d5efc56bad7ff789f1811990e67de22fbec614ac37009a9aa608ce5"}, + {file = "cocotb-1.8.1.tar.gz", hash = "sha256:1499dbe0d4d10676bc9b234861e1df171a7f02aca6b696b5fadf01fe61e3a4f6"}, +] + +[package.dependencies] +find-libpython = "*" + +[package.extras] +bus = ["cocotb-bus"] + +[[package]] +name = "cocotb-bus" +version = "0.2.1" +description = "" +optional = false +python-versions = ">=3.5" +files = [ + {file = "cocotb-bus-0.2.1.tar.gz", hash = "sha256:a197aa4b0e0ad28469c8877b41b3fb2ec0206da9f491b9276d1578ce6dd8aa8d"}, +] + +[package.dependencies] +cocotb = ">=1.5.0.dev,<2.0" + +[[package]] +name = "cocotb-coverage" +version = "1.1.0" +description = "Functional Coverage and Constrained Randomization Extensions for Cocotb" +optional = false +python-versions = ">=3.3" +files = [ + {file = "cocotb-coverage-1.1.0.tar.gz", hash = "sha256:6aed5f96bcddec3b8632e5be1559d83f355863affbc2a19a5766bbbb41f161e4"}, + {file = "cocotb_coverage-1.1.0-py3-none-any.whl", hash = "sha256:66f45db27d9835b4a5f92efbc556e36b539e532f1fe07ef5a3036017aca9d1ba"}, +] + +[package.dependencies] +cocotb = "*" +python-constraint = "*" +pyyaml = "*" + +[[package]] +name = "cocotbext-axi" +version = "0.1.24" +description = "AXI, AXI lite, and AXI stream modules for cocotb" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cocotbext-axi-0.1.24.tar.gz", hash = "sha256:3ed62dcaf9448833176826507c5bc5c346431c4846a731e409d87c862d960593"}, + {file = "cocotbext_axi-0.1.24-py3-none-any.whl", hash = "sha256:533ba6c7503c6302bdb9ef86e43a549ad5da876eafb1adce23d39751c54cced4"}, +] + +[package.dependencies] +cocotb = ">=1.6.0" +cocotb-bus = "*" + +[package.extras] +test = ["cocotb-test", "pytest"] + +[[package]] +name = "find-libpython" +version = "0.3.0" +description = "Finds the libpython associated with your environment, wherever it may be hiding" +optional = false +python-versions = "*" +files = [ + {file = "find_libpython-0.3.0-py3-none-any.whl", hash = "sha256:93fa14c8d007a7f9e6b650a486e249b49f01fd8d45b83ecf080a78b1a7011214"}, + {file = "find_libpython-0.3.0.tar.gz", hash = "sha256:6e7fe5d9af7fad6dc066cb5515a0e9c90a71f1feb2bb2f8e4cdbb4f83276e9e5"}, +] + +[[package]] +name = "python-constraint" +version = "1.4.0" +description = "python-constraint is a module implementing support for handling CSPs (Constraint Solving Problems) over finite domain" +optional = false +python-versions = "*" +files = [ + {file = "python-constraint-1.4.0.tar.bz2", hash = "sha256:501d6f17afe0032dfc6ea6c0f8acc12e44f992733f00e8538961031ef27ccb8e"}, +] + +[package.extras] +dev = ["check-manifest", "nose"] +test = ["coverage", "nose"] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "6891ff82be122556d540c217ca1e66b41cf7af93b77485f951064028e5edadcb" diff --git a/verif/input_fifo_tb/pyproject.toml b/verif/input_fifo_tb/pyproject.toml new file mode 100644 index 0000000..9e0ef25 --- /dev/null +++ b/verif/input_fifo_tb/pyproject.toml @@ -0,0 +1,17 @@ +[tool.poetry] +name = "input-fifo-tb" +version = "0.1.0" +description = "" +authors = ["Mario Huettel "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.11" +cocotb = "^1.8.1" +cocotbext-axi = "^0.1.24" +cocotb-coverage = "^1.1.0" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/verif/input_fifo_tb/results.xml b/verif/input_fifo_tb/results.xml new file mode 100644 index 0000000..5422eda --- /dev/null +++ b/verif/input_fifo_tb/results.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/verif/input_fifo_tb/run.sh b/verif/input_fifo_tb/run.sh new file mode 100755 index 0000000..f77682b --- /dev/null +++ b/verif/input_fifo_tb/run.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +SOURCE=${BASH_SOURCE[0]} +while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd ) + SOURCE=$(readlink "$SOURCE") + [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +SCRIPT_DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd ) + +projdir=`readlink -f -n "$SCRIPT_DIR/../../"` + +workdir=`mktemp -d` + +echo "Using tempdir: $workdir" + +toplevel="flacdec_input_fifo" +filelist=("rtl/flacdec_double_mem_fifo.vhd" "rtl/mem/flacdec_64x08_memory.vhd" "rtl/flacdec_input_fifo.vhd") + +cd "$SCRIPT_DIR" + +for file in ${filelist[@]}; do + echo "Importing $file" + ghdl -i --workdir="$workdir" "$projdir/$file" +done + +echo "Building design..." +ghdl -m --workdir="$workdir" $toplevel + +export LIBPYTHON_LOC=`cocotb-config --libpython` +export MODULE=tb.tests + +ghdl -r --workdir="$workdir" "$toplevel" --vpi=$(cocotb-config --lib-name-path vpi ghdl) + + +cd "$projdir" +rm -rf "$rundir" diff --git a/verif/input_fifo_tb/tb/__init__.py b/verif/input_fifo_tb/tb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/verif/input_fifo_tb/tb/tests.py b/verif/input_fifo_tb/tb/tests.py new file mode 100644 index 0000000..c47039e --- /dev/null +++ b/verif/input_fifo_tb/tb/tests.py @@ -0,0 +1,91 @@ +import cocotb +from cocotb.triggers import RisingEdge, FallingEdge, Edge +from cocotb.triggers import Timer +from cocotbext.axi import (AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStreamMonitor, AxiStreamFrame) +from random import randint, randrange +from cocotb.regression import TestFactory +from itertools import cycle + +async def reset_target(dut): + dut.rst_n.value = 0 + dut.out_tready.value = 0 + dut.flush_output.value = 0 + dut.clear.value = 0 + await Timer(10, units='ns') + await RisingEdge(dut.clk) + dut.rst_n.value = 1 + +async def clock_driver(dut): + while True: + dut.clk.value = 0 + await Timer(10, units='ns') + dut.clk.value = 1 + await Timer(10, units='ns') + + +@cocotb.test() +async def test_fifo_fill(dut): + axi_in = AxiStreamSource(AxiStreamBus.from_prefix(dut, 'in'), dut.clk, dut.rst_n, reset_active_level=False) + cocotb.start_soon(clock_driver(dut)) + await reset_target(dut) + + frame = bytearray([randint(0, 2**8-1) for _ in range(128+2)]) + + await axi_in.send(frame) + + await axi_in.wait() + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + assert dut.in_tready.value == 1, 'FIFO full + pipeline full' + assert dut.full.value == 1, 'FIFO full?' + + await axi_in.send(bytearray([randint(0, 255)])) + await axi_in.wait() + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + assert dut.in_tready.value == 0, 'FIFO full + pipeline full' + assert dut.full.value == 1, 'FIFO full' + assert dut.empty.value == 0, 'FIFO empty' + +async def stress_test(dut, tx_pause=None, rx_pause=None, count=512): + axi_in = AxiStreamSource(AxiStreamBus.from_prefix(dut, 'in'), dut.clk, dut.rst_n, reset_active_level=False) + axi_out = AxiStreamSink(AxiStreamBus.from_prefix(dut, "out"), dut.clk, dut.rst_n, reset_active_level=False) + cocotb.start_soon(clock_driver(dut)) + await reset_target(dut) + + if tx_pause: + axi_in.set_pause_generator(tx_pause) + if rx_pause: + axi_out.set_pause_generator(rx_pause) + + frame = bytearray([randint(0, 255) for _ in range(count)]) + await axi_in.send(frame) + await axi_in.wait() + + for _ in range(count*100): + await RisingEdge(dut.clk) + if dut.flacdec_double_mem_fifo_1.fill_level.value == 0: + break + else: + assert False, 'Timeout' + for _ in range(100): + await RisingEdge(dut.clk) + + + rx_data = await axi_out.read(axi_out.count()) + + assert len(rx_data) == len(frame), 'RX TX data count mismatch' + + for tx, rx in zip(frame, rx_data): + assert tx == rx, 'TX, RX data mismatch' + +stress_test_fac = TestFactory(stress_test) +stress_test_fac.add_option('count', [1, 5, randint(1000, 2**16)]) +def generate_random_wait_seq(percent=50, length=20): + seq = [1 if randint(0, 100) >= percent else 0 for _ in range(length)] + return seq + +stress_test_fac.add_option('tx_pause', [None, cycle(generate_random_wait_seq(10, 30)), cycle(generate_random_wait_seq(80, 30))]) +stress_test_fac.add_option('rx_pause', [None, cycle(generate_random_wait_seq(10, 30)), cycle(generate_random_wait_seq(80, 30))]) +stress_test_fac.generate_tests() \ No newline at end of file