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

Subversion Repositories yahamm

[/] [yahamm/] [trunk/] [bench/] [vhdl/] [yahamm_tb0.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 one bit parity check.
47
-- CORRECT false
48
-- EXTRA_PARITY_BIT 0
49
-- ONE_PARITY_BIT true
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_tb0 is
67
 
68
end entity yahamm_tb0;
69
 
70
-------------------------------------------------------------------------------
71
 
72
architecture tb of yahamm_tb0 is
73
 
74
  -- component ports
75
  signal chken, enc_en  : std_logic := '1';
76
 
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
  constant DATAMAX : natural := 2**MESSAGE_LENGTH - 1;
81
 
82
  constant CORRECT : boolean := false;
83
  constant EXTRA_PARITY_BIT : natural := 0;
84
 
85
  constant ONE_PARITY_BIT : boolean := true;
86
 
87
  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
  constant ERROR_LEN : natural := 16;
90
 
91
  constant NITERATIONS : natural := 1000;  -- number of iterations for each test
92
 
93
  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
  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
 
102
  -- clock
103
  signal clk, rst : std_logic := '1';
104
 
105
  signal wrong_bit0_position, wrong_bit1_position, wrong_bit2_position : natural := 0;
106
 
107
begin  -- architecture tb
108
 
109
   --instance "yahamm_enc_1"
110
  yahamm_enc_1: entity yahamm.yahamm_enc
111
    generic map (
112
      MESSAGE_LENGTH => MESSAGE_LENGTH,
113
      EXTRA_PARITY_BIT   => EXTRA_PARITY_BIT,
114
      ONE_PARITY_BIT => ONE_PARITY_BIT)
115
    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
  yahamm_dec_1: entity yahamm.yahamm_dec
124
    generic map (
125
      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
    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
 
142
  -- clock generation
143
  clk <= not clk after 10 ns;
144
 
145
  -- purpose: delay inputs for later comparison with outputs.
146
  delays: process (clk, rst) is
147
  begin  -- process delays
148
    if rst = '1' then                   -- asynchronous reset (active high)
149
      data_enc_in_q0 <= (others => '0');
150
      data_enc_in_q1 <= (others => '0');
151
      data_enc_in_q2 <= (others => '0');
152
    elsif rising_edge(clk) then         -- rising clock edge
153
      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: flip bits of the decoder inputs to produce errors.
160
  -- type   : combinational
161
  flip_bits_proc: process (data_enc_out, wrong_bit0_position, wrong_bit1_position) is
162
  begin  -- process flip_bits_proc
163
    data_enc_to_dec <= data_enc_out;
164
 
165
    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
 
170
    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
 
176
  -- waveform generation
177
  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
  begin
182
 
183
    dec_cnt_clr <= '0';
184
    rst <= '1';
185
    wait until rising_edge(clk);
186
    rst <= '0';
187
 
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
 
196
      wait until rising_edge(clk);
197
      assert data_enc_in_q2 = data_dec_out report "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
        test0_errors := test0_errors + 1;
201
      end if;
202
 
203
    end loop;
204
 
205
    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
 
218
      -- produce an error flipping a random bit in the encoder output.  0 means
219
      -- 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
      if data_enc_in_q2 /= data_dec_out then
224
        test1_errors := test1_errors + 1;
225
      end if;
226
 
227
      wait until rising_edge(clk);
228
    end loop;
229
 
230
    wrong_bit0_position <= 0;
231
    wait until rising_edge(clk);
232
    wait until rising_edge(clk);
233
 
234
    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;
235
    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;
236
 
237
    -- clear decoder counters
238
    dec_cnt_clr <= '1';
239
    wait until rising_edge(clk);
240
    dec_cnt_clr <= '0';
241
    wait until rising_edge(clk);
242
 
243
    -- check the clear
244
    if to_integer(unsigned(cnt_errors_corrected)) /= 0 then
245
      report "Unexepcted cnt_errors_corrected " & integer'image(to_integer(unsigned(cnt_errors_corrected))) & ".  Should be 0 after clear." severity error;
246
      test_clear := 1;
247
    end if;
248
    if to_integer(unsigned(cnt_errors_detected)) /= 0 then
249
      report "Unexepcted cnt_errors_detected " & integer'image(to_integer(unsigned(cnt_errors_detected))) & ".  Should be 0 after clear." severity error;
250
      test_clear := 1;
251
    end if;
252
 
253
    assert test0_errors = 0 and test1_errors > 0 and test_clear = 0 report "TB0 unsuccessful." severity failure;
254
 
255 5 ndesimone
    assert false report "OK" severity note;
256 4 ndesimone
    stop(0);
257
 
258
  end process WaveGen_Proc;
259
 
260
 
261
end architecture tb;

powered by: WebSVN 2.1.0

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