OpenCores
URL https://opencores.org/ocsvn/yahamm/yahamm/trunk

Subversion Repositories yahamm

[/] [yahamm/] [trunk/] [bench/] [vhdl/] [yahamm_tb2.vhd] - Rev 5

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Yahamm IP core
--
-- This file is part of the Yahamm project
-- http://www.opencores.org/cores/yahamm
--
-- Description
-- A hamming encoder and decoder with single-error correcting and
-- double-error detecting capability. The message length can be configured
-- through a generic. Both the code generator matrix and the parity-check
-- matrix are computed in the VHDL itself.
--
-- To Do:
-- - write docs
--
-- Author:
-- - Nicola De Simone, ndesimone@opencores.org
--
-------------------------------------------------------------------------------
--
-- Copyright (C) 2017 Authors and OPENCORES.ORG
--
-- This source file may be used and distributed without
-- restriction provided that this copyright statement is not
-- removed from the file and that any derivative work contains
-- the original copyright notice and the associated disclaimer.
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
--- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.opencores.org/lgpl.shtml
--
-------------------------------------------------------------------------------
 
-- Testbench with Single Error Corrected, Double Error Detected
-- CORRECT true
-- EXTRA_PARITY_BIT 1
-- ONE_PARITY_BIT false
--
 
library std;
use std.env.all;
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
use ieee.numeric_std.all;
 
library yahamm;
use yahamm.yahamm_pkg.all;
use yahamm.matrix_pkg.all;
 
-------------------------------------------------------------------------------
 
entity yahamm_tb2 is
 
end entity yahamm_tb2;
 
-------------------------------------------------------------------------------
 
architecture tb of yahamm_tb2 is
 
  -- component ports
  signal chken, enc_en : std_logic := '1';
 
  -- Cannot use here MESSAGE_LENGTH > 30 otherwise datamax overflows.  This is
  -- just a limitation of this testbench.
  constant MESSAGE_LENGTH : natural := 3;
  constant DATAMAX	  : natural := 2**MESSAGE_LENGTH - 1;
 
  constant CORRECT	    : boolean := true;
  constant EXTRA_PARITY_BIT : natural := 1;
 
  constant ONE_PARITY_BIT : boolean := false;
 
  constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT);
  constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT);
  constant ERROR_LEN	: natural := 16;
 
  constant NITERATIONS : natural := 1000;  -- number of iterations for each test
 
  signal data_enc_in, data_enc_out, data_enc_to_dec, data_dec_out : std_logic_vector(MESSAGE_LENGTH - 1 downto 0) := (others => '0');
  signal
    data_enc_in_q0,
    data_enc_in_q1,
    data_enc_in_q2 : std_logic_vector(data_enc_in'range);
  signal dec_cnt_clr				   : std_logic;	 -- clear counters
  signal parity_enc_out, parity_enc_to_dec	   : std_logic_vector(NPARITY_BITS + EXTRA_PARITY_BIT - 1 downto 0);
  signal cnt_errors_corrected, cnt_errors_detected : std_logic_vector(ERROR_LEN - 1 downto 0);
 
  -- clock
  signal clk, rst : std_logic := '1';
 
  signal wrong_bit0_data_position, wrong_bit1_data_position	: natural := 0;
  signal wrong_bit0_parity_position, wrong_bit1_parity_position : natural := 0;
 
begin  -- architecture tb
 
  --instance "yahamm_enc_1"
  yahamm_enc_1 : entity yahamm.yahamm_enc
    generic map (
      MESSAGE_LENGTH   => MESSAGE_LENGTH,
      EXTRA_PARITY_BIT => EXTRA_PARITY_BIT,
      ONE_PARITY_BIT   => ONE_PARITY_BIT)
    port map (
      clk_i    => clk,
      rst_i    => rst,
      en_i     => enc_en,
      data_i   => data_enc_in,
      data_o   => data_enc_out,
      parity_o => parity_enc_out);
 
  yahamm_dec_1 : entity yahamm.yahamm_dec
    generic map (
      MESSAGE_LENGTH   => MESSAGE_LENGTH,
      CORRECT	       => CORRECT,
      EXTRA_PARITY_BIT => EXTRA_PARITY_BIT,
      ONE_PARITY_BIT   => ONE_PARITY_BIT,
      ERROR_LEN	       => ERROR_LEN)
    port map (
      clk_i		     => clk,
      rst_i		     => rst,
      cnt_clr_i		     => dec_cnt_clr,
      en_i		     => enc_en,
      data_i		     => data_enc_to_dec,
      parity_i		     => parity_enc_to_dec,
      data_o		     => data_dec_out,
      cnt_errors_corrected_o => cnt_errors_corrected,
      cnt_errors_detected_o  => cnt_errors_detected
      );
 
  -- clock generation
  clk <= not clk after 10 ns;
 
  -- purpose: delay inputs for later comparison with outputs.
  delays : process (clk, rst) is
  begin	 -- process delays
    if rst = '1' then			-- asynchronous reset (active high)
      data_enc_in_q0 <= (others => '0');
      data_enc_in_q1 <= (others => '0');
      data_enc_in_q2 <= (others => '0');
    elsif rising_edge(clk) then		-- rising clock edge
      data_enc_in_q0 <= data_enc_in;
      data_enc_in_q1 <= data_enc_in_q0;
      data_enc_in_q2 <= data_enc_in_q1;
    end if;
  end process delays;
 
  -- purpose: flit bits of the decoder inputs to produce errors.
  -- type   : combinational
  flip_bits_proc : process (data_enc_out,
			    wrong_bit0_data_position, wrong_bit1_data_position,
			    wrong_bit0_parity_position, wrong_bit1_parity_position) is
  begin	 -- process flip_bits_proc
    data_enc_to_dec   <= data_enc_out;
    parity_enc_to_dec <= parity_enc_out;
 
    if wrong_bit0_data_position > 0 then
      -- flip one bit
      data_enc_to_dec(wrong_bit0_data_position - 1) <= not data_enc_out(wrong_bit0_data_position - 1);
    end if;
 
    if wrong_bit1_data_position > 0 then
      -- flip another bit (it can also randomly be the same one)
      data_enc_to_dec(wrong_bit1_data_position - 1) <= not data_enc_out(wrong_bit1_data_position - 1);
    end if;
 
    if wrong_bit0_parity_position > 0 then
      -- flip one bit
      parity_enc_to_dec(wrong_bit0_parity_position - 1) <= not parity_enc_out(wrong_bit0_parity_position - 1);
    end if;
 
    if wrong_bit1_parity_position > 0 then
      -- flip another bit (it can also randomly be the same one)
      parity_enc_to_dec(wrong_bit1_parity_position - 1) <= not parity_enc_out(wrong_bit1_parity_position - 1);
    end if;
 
  end process flip_bits_proc;
 
  -- waveform generation
  WaveGen_Proc : process
    variable random						  : real;
    variable seed1, seed2					  : positive := 1;
    variable test0_errors, test1_errors, test2_errors, test_clear : natural  := 0;
  begin
 
    dec_cnt_clr <= '0';
    rst		<= '1';
    wait until rising_edge(clk);
    rst		<= '0';
 
    -- TEST #0
    -- Without transmission errors.
    wrong_bit0_data_position <= 0;
    wrong_bit1_data_position <= 0;
    for itest in 0 to NITERATIONS-1 loop
      uniform(seed1, seed2, random);
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
 
      wait until rising_edge(clk);
      assert data_enc_in_q2 = data_dec_out report "Test #0: Encoder input (" & to_hstring(data_enc_in_q2) & ") != decoder output (" & to_hstring(data_dec_out) & ")." severity error;
 
      if data_enc_in_q2 /= data_dec_out then
	test0_errors := test0_errors + 1;
      end if;
 
    end loop;
 
    wait until rising_edge(clk);
    wait until rising_edge(clk);
 
    assert to_integer(unsigned(cnt_errors_corrected)) = 0 report "Test #0: Unexpected cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ".  Should be 0." severity error;
    assert to_integer(unsigned(cnt_errors_detected)) = 0 report "Test #0: Unexpected cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ".  Should be 0." severity error;
 
    -- TEST #1
    -- Test the correction with 1 bit transmission error on a random bit
    wrong_bit1_data_position <= 0;
    for itest in 0 to NITERATIONS-1 loop
      uniform(seed1, seed2, random);
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
 
      -- produce an error flipping a random bit in the encoder output.	0 means
      -- don't flip, so we have to add 1.
      uniform(seed1, seed2, random);
      wrong_bit0_data_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
 
      assert data_enc_in_q2 = data_dec_out report "Test #1: Encoder input (" & to_hstring(data_enc_in_q2) & ") != decoder output (" & to_hstring(data_dec_out) & ")." severity error;
 
      if data_enc_in_q2 /= data_dec_out then
	test1_errors := test1_errors + 1;
      end if;
 
      wait until rising_edge(clk);
    end loop;
 
    wrong_bit0_data_position <= 0;
    wait until rising_edge(clk);
    wait until rising_edge(clk);
 
    assert to_integer(unsigned(cnt_errors_corrected)) = NITERATIONS report "Test #1: Unexpected cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ".  Should be " & integer'image(NITERATIONS) severity error;
    assert to_integer(unsigned(cnt_errors_detected)) = 0 report "Test #1: Unexpected cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ".  Should be 0." severity error;
 
    -- TEST #2
    -- Test the non working correction with 2 bit transmission error.
    for itest in 0 to NITERATIONS-1 loop
      uniform(seed1, seed2, random);
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
 
      -- produce an error flipping a random bit in the encoder output.	0 means
      -- don't flip, so we have to add 1.
      uniform(seed1, seed2, random);
      wrong_bit0_data_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
      uniform(seed1, seed2, random);
      wrong_bit1_data_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
 
      if data_enc_in_q2 /= data_dec_out then
	test2_errors := test2_errors + 1;
      end if;
 
      wait until rising_edge(clk);
    end loop;
 
    wrong_bit0_data_position <= 0;
    wrong_bit1_data_position <= 0;
    wait until rising_edge(clk);
    wait until rising_edge(clk);
 
    assert to_integer(unsigned(cnt_errors_corrected)) > 0 report "Test #2: Unexpected cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ".  Should be > 0." severity error;
    assert to_integer(unsigned(cnt_errors_detected)) > 0 report "Test #2: Unexpected cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ".  Should be > 0." severity error;
 
    -- clear decoder counters
    dec_cnt_clr <= '1';
    wait until rising_edge(clk);
    dec_cnt_clr <= '0';
    wait until rising_edge(clk);
 
    -- check the clear
    if to_integer(unsigned(cnt_errors_corrected)) /= 0 then
      report "Unexpected cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ".  Should be 0 after clear." severity error;
      test_clear := 1;
    end if;
    if to_integer(unsigned(cnt_errors_detected)) /= 0 then
      report "Unexpected cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ".  Should be 0 after clear." severity error;
      test_clear := 1;
    end if;
 
    assert test0_errors = 0 and test1_errors = 0 and test2_errors > 0 and test_clear = 0 report "TB2 unsuccessful." severity failure;
 
    assert false report "OK" severity note;
    stop(0);
 
  end process WaveGen_Proc;
 
 
end architecture tb;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.