URL
https://opencores.org/ocsvn/yahamm/yahamm/trunk
Subversion Repositories yahamm
Compare Revisions
- This comparison shows the changes necessary to convert path
/yahamm
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/trunk/sim/Makefile
0,0 → 1,14
ifndef ROOTDIR |
ROOTDIR=.. |
endif |
|
VPATH = $(ROOTDIR)/libraries/ieee_proposed:$(ROOTDIR)/ieee_proposed:$(ROOTDIR)/libraries/yahamm |
OPT=--std=08 --workdir=libraries/yahamm --work=yahamm |
|
all: yahamm_tb0 yahamm_tb1 yahamm_tb2 yahamm_tb3 |
|
yahamm_tb%: yahamm_tb%.vhd |
@ghdl -a --std=08 -P$(ROOTDIR)/libraries/yahamm $< |
@ghdl -e --std=08 -P$(ROOTDIR)/libraries/yahamm $@ |
@ghdl -r --std=08 -P$(ROOTDIR)/libraries/yahamm $@ |
|
/trunk/sim/yahamm_tb0.vhd
0,0 → 1,261
------------------------------------------------------------------------------- |
-- 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 one bit parity check. |
-- CORRECT false |
-- EXTRA_PARITY_BIT 0 |
-- ONE_PARITY_BIT true |
-- |
|
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_tb0 is |
|
end entity yahamm_tb0; |
|
------------------------------------------------------------------------------- |
|
architecture tb of yahamm_tb0 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 := 0; |
|
constant ONE_PARITY_BIT : boolean := true; |
|
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 => clk, |
rst => rst, |
en => enc_en, |
din => data_enc_in, |
dout => data_enc_out, |
parity => 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 => clk, |
rst => rst, |
cnt_clr => dec_cnt_clr, |
en => enc_en, |
din => data_enc_to_dec, |
parity => parity_enc_to_dec, |
dout => data_dec_out, |
cnt_errors_corrected => cnt_errors_corrected, |
cnt_errors_detected => 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: flip 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; |
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_position <= 0; |
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)); |
|
wait until rising_edge(clk); |
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; |
|
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)) > 0 report "Test #1: 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 "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 test_clear = 0 report "TB0 unsuccessful." severity failure; |
|
assert false report "SUCCESS" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/trunk/sim/yahamm_tb1.vhd
0,0 → 1,279
------------------------------------------------------------------------------- |
-- 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. |
-- CORRECT true |
-- EXTRA_PARITY_BIT 0 |
-- 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_tb1 is |
|
end entity yahamm_tb1; |
|
------------------------------------------------------------------------------- |
|
architecture tb of yahamm_tb1 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 := true; |
constant EXTRA_PARITY_BIT : natural := 0; |
|
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 => clk, |
rst => rst, |
en => enc_en, |
din => data_enc_in, |
dout => data_enc_out, |
parity => 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 => clk, |
rst => rst, |
cnt_clr => dec_cnt_clr, |
en => enc_en, |
din => data_enc_to_dec, |
parity => parity_enc_to_dec, |
dout => data_dec_out, |
cnt_errors_corrected => cnt_errors_corrected, |
cnt_errors_detected => 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; |
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_position <= 0; |
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)); |
|
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; |
|
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_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; |
|
-- 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; |
|
-- 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_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; |
|
assert test0_errors = 0 and test1_errors = 0 and test2_errors > 0 and test_clear = 0 report "Test #2: TB1 unsuccessful." severity failure; |
|
assert false report "SUCCESS" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/trunk/sim/yahamm_tb2.vhd
0,0 → 1,306
------------------------------------------------------------------------------- |
-- 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 => clk, |
rst => rst, |
en => enc_en, |
din => data_enc_in, |
dout => data_enc_out, |
parity => 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 => clk, |
rst => rst, |
cnt_clr => dec_cnt_clr, |
en => enc_en, |
din => data_enc_to_dec, |
parity => parity_enc_to_dec, |
dout => data_dec_out, |
cnt_errors_corrected => cnt_errors_corrected, |
cnt_errors_detected => 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 "SUCCESS" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/trunk/sim/yahamm_tb3.vhd
0,0 → 1,339
------------------------------------------------------------------------------- |
-- 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 => clk, |
rst => rst, |
en => enc_en, |
din => data_enc_in, |
dout => data_enc_out, |
parity => 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 => clk, |
rst => rst, |
cnt_clr => dec_cnt_clr, |
en => enc_en, |
din => data_enc_to_dec, |
parity => parity_enc_to_dec, |
dout => data_dec_out, |
cnt_errors_corrected => cnt_errors_corrected, |
cnt_errors_detected => 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 "SUCCESS" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/trunk/Makefile
0,0 → 1,21
export ROOT_DIR=${PWD} |
|
VPATH = libraries/ieee_proposed:ieee_proposed:libraries/yahamm |
LIBPREFIX=libraries |
|
OPT=--std=08 --workdir=libraries/yahamm --work=yahamm |
|
yahamm-obj08: matrix_pkg.vhd yahamm_pkg.vhd yahamm_enc.vhd yahamm_dec.vhd |
@mkdir -p libraries/yahamm |
@for f in $^; do\ |
ghdl -a $(OPT) -Pieee_proposed $$f;\ |
done |
|
sim: yahamm-obj08 |
@$(MAKE) -C sim |
|
clean: |
@ghdl --remove $(OPT) |
|
|
.PHONY: sim |
/trunk/matrix_pkg.vhd
1,14 → 1,59
------------------------------------------------------------------------------- |
-- 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 |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
use std.textio.all; |
|
library ieee_proposed; |
use ieee_proposed.std_logic_1164_additions.all; |
use ieee_proposed.standard_additions.all; |
-- pragma synthesis_off |
use ieee_proposed.standard_textio_additions.all; |
-- pragma synthesis_on |
--library ieee_proposed; |
--use ieee_proposed.std_logic_1164_additions.all; |
--use ieee_proposed.standard_additions.all; |
---- pragma synthesis_off |
--use ieee_proposed.standard_textio_additions.all; |
---- pragma synthesis_on |
|
package matrix_pkg is |
|
37,7 → 82,7
procedure set_col ( |
variable M : inout matrix_t; |
constant icol : natural; |
constant col : in bit_vector); |
constant col : bit_vector); |
|
-- pragma synthesis_off |
procedure pretty_print_matrix ( |
50,12 → 95,16
function find_col ( |
constant M : matrix_t; |
constant col : bit_vector) |
return natural; |
return integer; |
|
procedure swap_cols ( |
variable M : inout matrix_t; |
constant icol1, icol2 : in natural); |
|
function and_reduce (L : BIT_VECTOR) return BIT; |
function or_reduce (L : BIT_VECTOR) return BIT; |
function xor_reduce (L : BIT_VECTOR) return BIT; |
|
end package matrix_pkg; |
|
package body matrix_pkg is |
194,4 → 243,31
return -1; |
end function find_col; |
|
function and_reduce (L : BIT_VECTOR) return BIT is |
variable result : BIT := '1'; |
begin |
for i in l'reverse_range loop |
result := l(i) and result; |
end loop; |
return result; |
end function and_reduce; |
|
function or_reduce (L : BIT_VECTOR) return BIT is |
variable result : BIT := '0'; |
begin |
for i in l'reverse_range loop |
result := l(i) or result; |
end loop; |
return result; |
end function or_reduce; |
|
function xor_reduce (L : BIT_VECTOR) return BIT is |
variable result : BIT := '0'; |
begin |
for i in l'reverse_range loop |
result := l(i) xor result; |
end loop; |
return result; |
end function xor_reduce; |
|
end package body matrix_pkg; |
/trunk/yahamm_dec.vhd
1,3 → 1,48
------------------------------------------------------------------------------- |
-- 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 |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
9,11 → 54,6
library std; |
use std.textio.all; |
|
library ieee_proposed; |
use ieee_proposed.std_logic_1164_additions.all; |
use ieee_proposed.numeric_std_additions.all; |
use ieee_proposed.standard_additions.all; |
|
-- There are two monitor counters: |
-- |
-- cnt_errors_corrected: number of error correction performed. |
236,11 → 276,11
|
if iserror then |
if correction_en then |
if and_reduce(cnt_errors_corrected_int) /= '1' then |
if and_reduce(to_bitvector(std_logic_vector(cnt_errors_corrected_int))) /= '1' then |
cnt_errors_corrected_int <= cnt_errors_corrected_int + 1; |
end if; |
else |
if and_reduce(cnt_errors_detected_int) /= '1' then |
if and_reduce(to_bitvector(std_logic_vector(cnt_errors_detected_int))) /= '1' then |
cnt_errors_detected_int <= cnt_errors_detected_int + 1; |
end if; |
end if; |
/trunk/yahamm_enc.vhd
1,3 → 1,48
------------------------------------------------------------------------------- |
-- 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 |
-- |
------------------------------------------------------------------------------- |
|
-- CORRECT: set to true to correct errors at the cost of decreasing error |
-- detection (see table). |
-- |
24,13 → 69,9
library ieee; |
use ieee.std_logic_1164.all; |
|
library ieee_proposed; |
use ieee_proposed.standard_additions.all; |
use ieee_proposed.std_logic_1164_additions.all; |
|
library yahamm; |
use yahamm.matrix_pkg.all; |
use yahamm.hamming_pkg.all; |
use yahamm.yahamm_pkg.all; |
|
entity yahamm_enc is |
generic ( |
58,9 → 99,13
0 to BLOCK_LENGTH - NPARITY_BITS - 1) := |
get_code_generator_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT); |
|
-- G'reverse_range(1) doesn't work in ghdl 0.34 |
--signal code_sys : std_ulogic_vector(G'reverse_range(1)); -- systematic code |
signal code_sys : std_ulogic_vector(BLOCK_LENGTH + EXTRA_PARITY_BIT -1 downto 0); -- systematic code |
|
signal din_padded : bit_vector(BLOCK_LENGTH - NPARITY_BITS - 1 downto 0); |
signal code_sys : std_ulogic_vector(G'reverse_range(1)); -- systematic code |
|
|
begin |
|
check_parameters(BLOCK_LENGTH, NPARITY_BITS, MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT); |
/trunk/yahamm_pkg.vhd
1,12 → 1,53
------------------------------------------------------------------------------- |
-- 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 |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.math_real.all; |
use ieee.numeric_std.all; |
|
--library ieee_proposed; |
--use ieee_proposed.standard_additions.all; |
--use ieee_proposed.std_logic_1164_additions.all; |
|
library yahamm; |
use yahamm.matrix_pkg.all; |
|
53,17 → 94,17
|
function get_code_generator_matrix ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY : in natural range 0 to 1 := 1; -- number of data (non parity) bits |
EXTRA_PARITY : natural range 0 to 1 := 1; -- number of data (non parity) bits |
ONE_PARITY_BIT : boolean := false) |
return matrix_t; |
|
function calc_nparity_bits ( |
k : in natural; |
k : natural; |
ONE_PARITY_BIT : boolean := false) |
return natural; |
|
function calc_block_length ( |
k : in natural; |
k : natural; |
ONE_PARITY_BIT : boolean := false) |
return natural; |
|
75,15 → 116,15
constant ONE_PARITY_BIT : in boolean; |
constant CORRECT : in boolean := false |
); |
|
|
function xor_multiply ( |
A : matrix_t; |
B : in matrix_t) |
B : matrix_t) |
return matrix_t; |
|
function xor_multiply_vec ( |
A : matrix_t; |
x : in bit_vector) |
x : bit_vector) |
return bit_vector; |
|
function get_form_swap_matrix ( |
95,7 → 136,7
end package yahamm_pkg; |
|
package body yahamm_pkg is |
|
|
-- purpose: Return a matrix S that can be used to tranform a parity |
-- check matrix or a code generator matrix M from non-systematic |
-- form to systematic form MS and viceversa (because S = S |
105,7 → 146,7
-- (as the parity check matrix) and the extra column is not swapped. |
function get_form_swap_matrix ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY : in natural; |
EXTRA_PARITY : natural; |
ONE_PARITY_BIT : boolean := false) |
return matrix_t is |
|
350,7 → 391,7
variable swap_matrix : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY - 1, 0 to BLOCK_LENGTH + EXTRA_PARITY - 1); |
|
begin -- function get_code_generator_matrix |
|
|
-- Identity submatrix on the left (I_k) |
for col in 0 to BLOCK_LENGTH - NPARITY_BITS - 1 loop |
gcol := (others => '0'); |
367,7 → 408,7
|
for icol in H'range(2) loop |
hcol := get_col(H, icol); |
if xor_reduce(to_slv(hcol)) = '0' then |
if xor_reduce(hcol) = '0' then |
H(H'high(1), icol) := '0'; |
end if; |
end loop; -- icol |
427,7 → 468,7
-- purpose: Calculate the code block length n for the specified |
-- message length (k). The code has n = 2^r - 1 for r >= 2. |
function calc_block_length ( |
constant k : natural; |
k : natural; |
ONE_PARITY_BIT : boolean := false) |
return natural is |
variable r : natural := 0; |