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

Subversion Repositories yahamm

[/] [yahamm/] [trunk/] [bench/] [vhdl/] [yahamm_tb3.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 Triple Error Detected
47
-- CORRECT false
48
-- EXTRA_PARITY_BIT 1
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_tb3 is
67
 
68
end entity yahamm_tb3;
69
 
70
-------------------------------------------------------------------------------
71
 
72
architecture tb of yahamm_tb3 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 := false;
83 4 ndesimone
  constant EXTRA_PARITY_BIT : natural := 1;
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 5 ndesimone
 
175 4 ndesimone
    if wrong_bit2_position > 0 then
176
      -- flit another bit (can also randomly be the same one)
177
      data_enc_to_dec(wrong_bit2_position - 1) <= not data_enc_out(wrong_bit2_position - 1);
178
    end if;
179
  end process flip_bits_proc;
180 5 ndesimone
 
181 4 ndesimone
  -- waveform generation
182 5 ndesimone
  WaveGen_Proc : process
183
    variable random                                                             : real;
184
    variable seed1, seed2                                                       : positive := 1;
185
    variable test0_errors, test1_errors, test2_errors, test3_errors, test_clear : natural  := 0;
186 4 ndesimone
  begin
187
 
188
    dec_cnt_clr <= '0';
189 5 ndesimone
    rst         <= '1';
190 4 ndesimone
    wait until rising_edge(clk);
191 5 ndesimone
    rst         <= '0';
192 4 ndesimone
 
193
    -- TEST #0
194
    -- Without transmission errors.
195
    wrong_bit0_position <= 0;
196
    wrong_bit1_position <= 0;
197
    wrong_bit2_position <= 0;
198
    for itest in 0 to NITERATIONS-1 loop
199
      uniform(seed1, seed2, random);
200
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
201 5 ndesimone
 
202
      wait until rising_edge(clk);
203 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;
204
 
205
      if data_enc_in_q2 /= data_dec_out then
206 5 ndesimone
        test0_errors := test0_errors + 1;
207 4 ndesimone
      end if;
208 5 ndesimone
 
209 4 ndesimone
    end loop;
210 5 ndesimone
 
211 4 ndesimone
    wait until rising_edge(clk);
212
    wait until rising_edge(clk);
213
 
214
    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;
215
    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;
216
 
217
    -- TEST #1
218
    -- Test the correction with 1 bit transmission error on a random bit
219
    wrong_bit1_position <= 0;
220
    for itest in 0 to NITERATIONS-1 loop
221
      uniform(seed1, seed2, random);
222
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
223 5 ndesimone
 
224
      -- produce an error flipping a random bit in the encoder output.  0 means
225 4 ndesimone
      -- don't flip, so we have to add 1.
226
      uniform(seed1, seed2, random);
227
      wrong_bit0_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
228
 
229
      if data_enc_in_q2 /= data_dec_out then
230 5 ndesimone
        test1_errors := test1_errors + 1;
231 4 ndesimone
      end if;
232 5 ndesimone
 
233 4 ndesimone
      wait until rising_edge(clk);
234
    end loop;
235
 
236
    wrong_bit0_position <= 0;
237
    wait until rising_edge(clk);
238
    wait until rising_edge(clk);
239
 
240
    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;
241
    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;
242
 
243
    -- clear decoder counters
244
    dec_cnt_clr <= '1';
245
    wait until rising_edge(clk);
246
    dec_cnt_clr <= '0';
247
    wait until rising_edge(clk);
248 5 ndesimone
 
249 4 ndesimone
    -- TEST #2
250
    -- Test the correction with 2 bit transmission error on random bits
251
    wrong_bit2_position <= 0;
252
    for itest in 0 to NITERATIONS-1 loop
253
      uniform(seed1, seed2, random);
254
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
255 5 ndesimone
 
256 4 ndesimone
      -- produce 2 errors flipping random bits in the encoder output.  0 means
257
      -- don't flip, so we have to add 1.
258
      uniform(seed1, seed2, random);
259
      wrong_bit0_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
260
      uniform(seed1, seed2, random);
261
      wrong_bit1_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
262
 
263
      if data_enc_in_q2 /= data_dec_out then
264 5 ndesimone
        test2_errors := test2_errors + 1;
265 4 ndesimone
      end if;
266 5 ndesimone
 
267 4 ndesimone
      wait until rising_edge(clk);
268
    end loop;
269
 
270
    wrong_bit0_position <= 0;
271 5 ndesimone
    wrong_bit1_position <= 0;
272 4 ndesimone
    wait until rising_edge(clk);
273
    wait until rising_edge(clk);
274
 
275
    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;
276
    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;
277
 
278
    -- clear decoder counters
279
    dec_cnt_clr <= '1';
280
    wait until rising_edge(clk);
281
    dec_cnt_clr <= '0';
282
    wait until rising_edge(clk);
283
 
284
    -- TEST #3
285
    -- Test the correction with 3 bit transmission error on random bits
286
    for itest in 0 to NITERATIONS-1 loop
287
      uniform(seed1, seed2, random);
288
      data_enc_in <= std_logic_vector(to_unsigned(integer(round(random*real(DATAMAX))), MESSAGE_LENGTH));
289 5 ndesimone
 
290 4 ndesimone
      -- produce 3 errors flipping random bits in the encoder output.  0 means
291
      -- don't flip, so we have to add 1.
292
      uniform(seed1, seed2, random);
293
      wrong_bit0_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
294
      uniform(seed1, seed2, random);
295
      wrong_bit1_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
296
      uniform(seed1, seed2, random);
297
      wrong_bit2_position <= natural(trunc(random*real(MESSAGE_LENGTH))) + 1;
298
 
299
      if data_enc_in_q2 /= data_dec_out then
300 5 ndesimone
        test3_errors := test3_errors + 1;
301 4 ndesimone
      end if;
302 5 ndesimone
 
303 4 ndesimone
      wait until rising_edge(clk);
304
    end loop;
305
 
306
    wrong_bit0_position <= 0;
307
    wrong_bit1_position <= 0;
308 5 ndesimone
    wrong_bit2_position <= 0;
309 4 ndesimone
    wait until rising_edge(clk);
310
    wait until rising_edge(clk);
311
 
312
    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;
313
    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;
314
 
315
    -- clear decoder counters
316
    dec_cnt_clr <= '1';
317
    wait until rising_edge(clk);
318
    dec_cnt_clr <= '0';
319
    wait until rising_edge(clk);
320
 
321
    -- check the clear
322
    if to_integer(unsigned(cnt_errors_corrected)) /= 0 then
323
      report "Unexepcted cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ".  Should be 0 after clear." severity error;
324
      test_clear := 1;
325
    end if;
326
    if to_integer(unsigned(cnt_errors_detected)) /= 0 then
327
      report "Unexepcted cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ".  Should be 0 after clear." severity error;
328
      test_clear := 1;
329
    end if;
330 5 ndesimone
 
331 4 ndesimone
    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;
332
 
333 5 ndesimone
    assert false report "OK" severity note;
334 4 ndesimone
    stop(0);
335 5 ndesimone
 
336 4 ndesimone
  end process WaveGen_Proc;
337
 
338 5 ndesimone
 
339 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.