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

Subversion Repositories yahamm

[/] [yahamm/] [trunk/] [bench/] [vhdl/] [yahamm_tb1.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 ndesimone
-------------------------------------------------------------------------------
2
-- Yahamm IP core
3
--
4
-- This file is part of the Yahamm project
5
-- http://www.opencores.org/cores/yahamm
6
--
7
-- Description
8
-- A hamming encoder and decoder with single-error correcting and
9
-- double-error detecting capability. The message length can be configured
10
-- through a generic. Both the code generator matrix and the parity-check
11
-- matrix are computed in the VHDL itself.
12
--
13
-- To Do:
14
-- - write docs
15
--
16
-- Author:
17
-- - Nicola De Simone, ndesimone@opencores.org
18
--
19
-------------------------------------------------------------------------------
20
--
21
-- Copyright (C) 2017 Authors and OPENCORES.ORG
22
--
23
-- This source file may be used and distributed without
24
-- restriction provided that this copyright statement is not
25
-- removed from the file and that any derivative work contains
26
-- the original copyright notice and the associated disclaimer.
27
--
28
-- This source file is free software; you can redistribute it
29
-- and/or modify it under the terms of the GNU Lesser General
30
-- Public License as published by the Free Software Foundation;
31
-- either version 2.1 of the License, or (at your option) any
32
-- later version.
33
--
34
-- This source is distributed in the hope that it will be
35
-- useful, but WITHOUT ANY WARRANTY; without even the implied
36
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
37
-- PURPOSE. See the GNU Lesser General Public License for more
38
-- details.
39
--
40
--- You should have received a copy of the GNU Lesser General
41
-- Public License along with this source; if not, download it
42
-- from http://www.opencores.org/lgpl.shtml
43
--
44
-------------------------------------------------------------------------------
45
 
46
-- Testbench with Single Error Corrected.
47
-- CORRECT true
48
-- EXTRA_PARITY_BIT 0
49
-- ONE_PARITY_BIT false
50
--
51
 
52
library std;
53
use std.env.all;
54
 
55
library ieee;
56
use ieee.std_logic_1164.all;
57
use ieee.math_real.all;
58
use ieee.numeric_std.all;
59
 
60
library yahamm;
61
use yahamm.yahamm_pkg.all;
62
use yahamm.matrix_pkg.all;
63
 
64
-------------------------------------------------------------------------------
65
 
66
entity yahamm_tb1 is
67
 
68
end entity yahamm_tb1;
69
 
70
-------------------------------------------------------------------------------
71
 
72
architecture tb of yahamm_tb1 is
73
 
74
  -- component ports
75 5 ndesimone
  signal chken, enc_en : std_logic := '1';
76 4 ndesimone
 
77
  -- Cannot use here MESSAGE_LENGTH > 30 otherwise datamax overflows.  This is
78
  -- just a limitation of this testbench.
79
  constant MESSAGE_LENGTH : natural := 30;
80 5 ndesimone
  constant DATAMAX        : natural := 2**MESSAGE_LENGTH - 1;
81 4 ndesimone
 
82 5 ndesimone
  constant CORRECT          : boolean := true;
83 4 ndesimone
  constant EXTRA_PARITY_BIT : natural := 0;
84
 
85
  constant ONE_PARITY_BIT : boolean := false;
86 5 ndesimone
 
87 4 ndesimone
  constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT);
88
  constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT);
89 5 ndesimone
  constant ERROR_LEN    : natural := 16;
90 4 ndesimone
 
91
  constant NITERATIONS : natural := 1000;  -- number of iterations for each test
92 5 ndesimone
 
93 4 ndesimone
  signal data_enc_in, data_enc_out, data_enc_to_dec, data_dec_out : std_logic_vector(MESSAGE_LENGTH - 1 downto 0) := (others => '0');
94
  signal
95
    data_enc_in_q0,
96
    data_enc_in_q1,
97
    data_enc_in_q2 : std_logic_vector(data_enc_in'range);
98 5 ndesimone
  signal dec_cnt_clr                               : std_logic;  -- clear counters
99
  signal parity_enc_to_dec                         : std_logic_vector(NPARITY_BITS + EXTRA_PARITY_BIT - 1 downto 0);
100
  signal cnt_errors_corrected, cnt_errors_detected : std_logic_vector(ERROR_LEN - 1 downto 0);
101 4 ndesimone
 
102
  -- clock
103
  signal clk, rst : std_logic := '1';
104
 
105
  signal wrong_bit0_position, wrong_bit1_position, wrong_bit2_position : natural := 0;
106 5 ndesimone
 
107 4 ndesimone
begin  -- architecture tb
108
 
109 5 ndesimone
  --instance "yahamm_enc_1"
110
  yahamm_enc_1 : entity yahamm.yahamm_enc
111 4 ndesimone
    generic map (
112 5 ndesimone
      MESSAGE_LENGTH   => MESSAGE_LENGTH,
113
      EXTRA_PARITY_BIT => EXTRA_PARITY_BIT,
114
      ONE_PARITY_BIT   => ONE_PARITY_BIT)
115 4 ndesimone
    port map (
116 5 ndesimone
      clk_i    => clk,
117
      rst_i    => rst,
118
      en_i     => enc_en,
119
      data_i   => data_enc_in,
120
      data_o   => data_enc_out,
121
      parity_o => parity_enc_to_dec);
122 4 ndesimone
 
123 5 ndesimone
  yahamm_dec_1 : entity yahamm.yahamm_dec
124 4 ndesimone
    generic map (
125 5 ndesimone
      MESSAGE_LENGTH   => MESSAGE_LENGTH,
126
      CORRECT          => CORRECT,
127
      EXTRA_PARITY_BIT => EXTRA_PARITY_BIT,
128
      ONE_PARITY_BIT   => ONE_PARITY_BIT,
129
      ERROR_LEN        => ERROR_LEN)
130 4 ndesimone
    port map (
131 5 ndesimone
      clk_i                  => clk,
132
      rst_i                  => rst,
133
      cnt_clr_i              => dec_cnt_clr,
134
      en_i                   => enc_en,
135
      data_i                 => data_enc_to_dec,
136
      parity_i               => parity_enc_to_dec,
137
      data_o                 => data_dec_out,
138
      cnt_errors_corrected_o => cnt_errors_corrected,
139
      cnt_errors_detected_o  => cnt_errors_detected
140 4 ndesimone
      );
141 5 ndesimone
 
142 4 ndesimone
  -- clock generation
143
  clk <= not clk after 10 ns;
144
 
145
  -- purpose: delay inputs for later comparison with outputs.
146 5 ndesimone
  delays : process (clk, rst) is
147
  begin  -- process delays
148
    if rst = '1' then                   -- asynchronous reset (active high)
149 4 ndesimone
      data_enc_in_q0 <= (others => '0');
150
      data_enc_in_q1 <= (others => '0');
151
      data_enc_in_q2 <= (others => '0');
152 5 ndesimone
    elsif rising_edge(clk) then         -- rising clock edge
153 4 ndesimone
      data_enc_in_q0 <= data_enc_in;
154
      data_enc_in_q1 <= data_enc_in_q0;
155
      data_enc_in_q2 <= data_enc_in_q1;
156
    end if;
157
  end process delays;
158
 
159
  -- purpose: flit bits of the decoder inputs to produce errors.
160
  -- type   : combinational
161 5 ndesimone
  flip_bits_proc : process (data_enc_out, wrong_bit0_position, wrong_bit1_position) is
162
  begin  -- process flip_bits_proc
163 4 ndesimone
    data_enc_to_dec <= data_enc_out;
164 5 ndesimone
 
165 4 ndesimone
    if wrong_bit0_position > 0 then
166
      -- flip one bit
167
      data_enc_to_dec(wrong_bit0_position - 1) <= not data_enc_out(wrong_bit0_position - 1);
168
    end if;
169 5 ndesimone
 
170 4 ndesimone
    if wrong_bit1_position > 0 then
171
      -- flit another bit (can also randomly be the same one)
172
      data_enc_to_dec(wrong_bit1_position - 1) <= not data_enc_out(wrong_bit1_position - 1);
173
    end if;
174
  end process flip_bits_proc;
175 5 ndesimone
 
176 4 ndesimone
  -- waveform generation
177 5 ndesimone
  WaveGen_Proc : process
178
    variable random                                               : real;
179
    variable seed1, seed2                                         : positive := 1;
180
    variable test0_errors, test1_errors, test2_errors, test_clear : natural  := 0;
181 4 ndesimone
  begin
182
 
183
    dec_cnt_clr <= '0';
184 5 ndesimone
    rst         <= '1';
185 4 ndesimone
    wait until rising_edge(clk);
186 5 ndesimone
    rst         <= '0';
187 4 ndesimone
 
188
    -- TEST #0
189
    -- Without transmission errors.
190
    wrong_bit0_position <= 0;
191
    wrong_bit1_position <= 0;
192
    for itest in 0 to NITERATIONS-1 loop
193
      uniform(seed1, seed2, random);
194
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
195 5 ndesimone
 
196
      wait until rising_edge(clk);
197 4 ndesimone
      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;
198
 
199
      if data_enc_in_q2 /= data_dec_out then
200 5 ndesimone
        test0_errors := test0_errors + 1;
201 4 ndesimone
      end if;
202 5 ndesimone
 
203 4 ndesimone
    end loop;
204 5 ndesimone
 
205 4 ndesimone
    wait until rising_edge(clk);
206
    wait until rising_edge(clk);
207
 
208
    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;
209
    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;
210
 
211
    -- TEST #1
212
    -- Test the correction with 1 bit transmission error on a random bit
213
    wrong_bit1_position <= 0;
214
    for itest in 0 to NITERATIONS-1 loop
215
      uniform(seed1, seed2, random);
216
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
217 5 ndesimone
 
218
      -- produce an error flipping a random bit in the encoder output.  0 means
219 4 ndesimone
      -- don't flip, so we have to add 1.
220
      uniform(seed1, seed2, random);
221
      wrong_bit0_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
222
 
223
      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;
224
 
225
      if data_enc_in_q2 /= data_dec_out then
226 5 ndesimone
        test1_errors := test1_errors + 1;
227 4 ndesimone
      end if;
228 5 ndesimone
 
229 4 ndesimone
      wait until rising_edge(clk);
230
    end loop;
231
 
232
    wrong_bit0_position <= 0;
233
    wait until rising_edge(clk);
234
    wait until rising_edge(clk);
235
 
236
    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;
237
    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;
238
 
239
    -- clear decoder counters
240
    dec_cnt_clr <= '1';
241
    wait until rising_edge(clk);
242
    dec_cnt_clr <= '0';
243
    wait until rising_edge(clk);
244 5 ndesimone
 
245 4 ndesimone
    -- check the clear
246
    if to_integer(unsigned(cnt_errors_corrected)) /= 0 then
247
      report "Unexpected cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ".  Should be 0 after clear." severity error;
248
      test_clear := 1;
249
    end if;
250 5 ndesimone
 
251 4 ndesimone
    -- TEST #2
252
    -- Test the non working correction with 2 bit transmission error.
253
    for itest in 0 to NITERATIONS-1 loop
254
      uniform(seed1, seed2, random);
255
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
256 5 ndesimone
 
257
      -- produce an error flipping a random bit in the encoder output.  0 means
258 4 ndesimone
      -- don't flip, so we have to add 1.
259
      uniform(seed1, seed2, random);
260
      wrong_bit0_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
261
      uniform(seed1, seed2, random);
262
      wrong_bit1_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
263
 
264
      if data_enc_in_q2 /= data_dec_out then
265 5 ndesimone
        test2_errors := test2_errors + 1;
266 4 ndesimone
      end if;
267 5 ndesimone
 
268 4 ndesimone
      wait until rising_edge(clk);
269
    end loop;
270
 
271
    assert test0_errors = 0 and test1_errors = 0 and test2_errors > 0 and test_clear = 0 report "Test #2: TB1 unsuccessful." severity failure;
272
 
273 5 ndesimone
    assert false report "OK" severity note;
274 4 ndesimone
    stop(0);
275
 
276
  end process WaveGen_Proc;
277
 
278 5 ndesimone
 
279 4 ndesimone
end architecture tb;

powered by: WebSVN 2.1.0

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