URL
https://opencores.org/ocsvn/yahamm/yahamm/trunk
Subversion Repositories yahamm
[/] [yahamm/] [trunk/] [bench/] [vhdl/] [yahamm_tb3.vhd] - Rev 9
Go to most recent revision | 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 Triple Error Detected -- CORRECT false -- 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_tb3 is end entity yahamm_tb3; ------------------------------------------------------------------------------- architecture tb of yahamm_tb3 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 := 30; constant DATAMAX : natural := 2**MESSAGE_LENGTH - 1; constant CORRECT : boolean := false; 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_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_position, wrong_bit1_position, wrong_bit2_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_to_dec); 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_position, wrong_bit1_position) is begin -- process flip_bits_proc data_enc_to_dec <= data_enc_out; if wrong_bit0_position > 0 then -- flip one bit data_enc_to_dec(wrong_bit0_position - 1) <= not data_enc_out(wrong_bit0_position - 1); end if; if wrong_bit1_position > 0 then -- flit another bit (can also randomly be the same one) data_enc_to_dec(wrong_bit1_position - 1) <= not data_enc_out(wrong_bit1_position - 1); end if; if wrong_bit2_position > 0 then -- flit another bit (can also randomly be the same one) data_enc_to_dec(wrong_bit2_position - 1) <= not data_enc_out(wrong_bit2_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, test3_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_position <= 0; wrong_bit1_position <= 0; wrong_bit2_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_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_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1; 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_position <= 0; wait until rising_edge(clk); wait until rising_edge(clk); assert to_integer(unsigned(cnt_errors_corrected)) = 0 report "Test #1: Unexpected cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ". Should be 0." severity error; assert to_integer(unsigned(cnt_errors_detected)) = NITERATIONS report "Test #1: Unexpected cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ". Should be " & integer'image(NITERATIONS) & "." severity error; -- clear decoder counters dec_cnt_clr <= '1'; wait until rising_edge(clk); dec_cnt_clr <= '0'; wait until rising_edge(clk); -- TEST #2 -- Test the correction with 2 bit transmission error on random bits wrong_bit2_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 2 errors flipping random bits in the encoder output. 0 means -- don't flip, so we have to add 1. uniform(seed1, seed2, random); wrong_bit0_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1; uniform(seed1, seed2, random); wrong_bit1_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_position <= 0; wrong_bit1_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)) = NITERATIONS report "Test #2: Unexpected cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ". Should be " & integer'image(NITERATIONS) & "." severity error; -- clear decoder counters dec_cnt_clr <= '1'; wait until rising_edge(clk); dec_cnt_clr <= '0'; wait until rising_edge(clk); -- TEST #3 -- Test the correction with 3 bit transmission error on random bits 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 3 errors flipping random bits in the encoder output. 0 means -- don't flip, so we have to add 1. uniform(seed1, seed2, random); wrong_bit0_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1; uniform(seed1, seed2, random); wrong_bit1_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1; uniform(seed1, seed2, random); wrong_bit2_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1; if data_enc_in_q2 /= data_dec_out then test3_errors := test3_errors + 1; end if; wait until rising_edge(clk); end loop; wrong_bit0_position <= 0; wrong_bit1_position <= 0; wrong_bit2_position <= 0; wait until rising_edge(clk); wait until rising_edge(clk); assert to_integer(unsigned(cnt_errors_corrected)) = 0 report "Test #3: Unexpected cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ". Should be 0." severity error; assert to_integer(unsigned(cnt_errors_detected)) = NITERATIONS report "Test #3: Unexpected cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ". Should be " & integer'image(NITERATIONS) & "." 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 "Unexepcted 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 "Unexepcted 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 test3_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;
Go to most recent revision | Compare with Previous | Blame | View Log