OpenCores
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;

powered by: WebSVN 2.1.0

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