URL
https://opencores.org/ocsvn/yahamm/yahamm/trunk
Subversion Repositories yahamm
Compare Revisions
- This comparison shows the changes necessary to convert path
/yahamm/trunk
- from Rev 4 to Rev 5
- ↔ Reverse comparison
Rev 4 → Rev 5
/yahamm_dec.vhd
File deleted
/yahamm_pkg.vhd
File deleted
/yahamm_enc.vhd
File deleted
/matrix_pkg.vhd
File deleted
/Makefile
File deleted
/bench/vhdl/Makefile
0,0 → 1,33
# This Makefile requires that you have ghdl compiled with gcc backend |
# (objects files *.o and executable targets don't make sense |
# otherwise). |
# |
# Compile matrix_pkg yahamm_pkg in the main root before compiling he |
# tests-benches. |
|
|
VIEWER=gtkwave |
LIBPREFIX=libs |
|
ifndef ROOTDIR |
ROOTDIR=.. |
endif |
|
VPATH = $(ROOTDIR)/$(LIBPREFIX)/yahamm |
GHDLFLAGS=--std=08 --workdir=$(ROOTDIR)/$(LIBPREFIX)/sim -P$(ROOTDIR)/$(LIBPREFIX)/yahamm --work=work |
|
all: yahamm_tb0 yahamm_tb1 yahamm_tb2 yahamm_tb3 |
|
%: %.o |
ghdl -e $(GHDLFLAGS) $@ |
./$@ --vcdgz=$(ROOTDIR)/$(LIBPREFIX)/sim/$@.vcdgz |
|
%.o: %.vhd |
mkdir -p $(ROOTDIR)/$(LIBPREFIX)/sim |
ghdl -a $(GHDLFLAGS) $< |
|
view: |
gunzip -c $(ROOTDIR)/$(LIBPREFIX)/sim/$@.vcdgz | $(VIEWER) --vcd |
|
clean: |
@ghdl --remove $(GHDLFLAGS) |
/bench/vhdl/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_i => clk, |
rst_i => rst, |
en_i => enc_en, |
data_i => data_enc_in, |
data_o => data_enc_out, |
parity_o => 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_i => clk, |
rst_i => rst, |
cnt_clr_i => dec_cnt_clr, |
en_i => enc_en, |
data_i => data_enc_to_dec, |
parity_i => parity_enc_to_dec, |
data_o => data_dec_out, |
cnt_errors_corrected_o => cnt_errors_corrected, |
cnt_errors_detected_o => 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 "OK" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/bench/vhdl/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_i => clk, |
rst_i => rst, |
en_i => enc_en, |
data_i => data_enc_in, |
data_o => data_enc_out, |
parity_o => 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_i => clk, |
rst_i => rst, |
cnt_clr_i => dec_cnt_clr, |
en_i => enc_en, |
data_i => data_enc_to_dec, |
parity_i => parity_enc_to_dec, |
data_o => data_dec_out, |
cnt_errors_corrected_o => cnt_errors_corrected, |
cnt_errors_detected_o => 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 "OK" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/bench/vhdl/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_i => clk, |
rst_i => rst, |
en_i => enc_en, |
data_i => data_enc_in, |
data_o => data_enc_out, |
parity_o => 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_i => clk, |
rst_i => rst, |
cnt_clr_i => dec_cnt_clr, |
en_i => enc_en, |
data_i => data_enc_to_dec, |
parity_i => parity_enc_to_dec, |
data_o => data_dec_out, |
cnt_errors_corrected_o => cnt_errors_corrected, |
cnt_errors_detected_o => 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 "OK" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/bench/vhdl/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_i => clk, |
rst_i => rst, |
en_i => enc_en, |
data_i => data_enc_in, |
data_o => data_enc_out, |
parity_o => 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_i => clk, |
rst_i => rst, |
cnt_clr_i => dec_cnt_clr, |
en_i => enc_en, |
data_i => data_enc_to_dec, |
parity_i => parity_enc_to_dec, |
data_o => data_dec_out, |
cnt_errors_corrected_o => cnt_errors_corrected, |
cnt_errors_detected_o => 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 "OK" severity note; |
stop(0); |
|
end process WaveGen_Proc; |
|
|
end architecture tb; |
/rtl/vhdl/Makefile
0,0 → 1,26
# This Makefile requires that you have ghdl compiled with gcc backend |
# (objects files *.o and executable targets don't make sense |
# otherwise). |
|
LIBPREFIX=libs |
VPATH = $(LIBPREFIX)/yahamm |
|
GHDLFLAGS=--std=08 --workdir=$(LIBPREFIX)/yahamm --work=yahamm |
|
all: yahamm_enc.o yahamm_dec.o |
|
|
yahamm_dec: matrix_pkg.o yahamm_pkg.o |
yahamm_enc: matrix_pkg.o yahamm_pkg.o |
|
%: %.o |
ghdl -e $(GHDLFLAGS) $@ |
|
%.o: %.vhd |
@mkdir -p $(LIBPREFIX)/yahamm |
ghdl -a $(GHDLFLAGS) $< |
|
clean: |
ghdl --remove $(GHDLFLAGS) |
|
.PHONY: sim |
/rtl/vhdl/matrix_pkg.vhd
0,0 → 1,273
------------------------------------------------------------------------------- |
-- 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 |
|
package matrix_pkg is |
|
----------------------------------------------------------------------------- |
-- Here 2D arrays are used to implement matrices. There are various |
-- limitations to the use of 2D arrays (e.g. limited easy slicing) |
-- that would maybe suggest an implementation with 1Dx1D matrices. |
-- But anyway this would make easy slicing either rows or columns |
-- but not both. The approach used here is implementing functions |
-- to handle various matrix operations. Having a 2D type allows to |
-- use one type definition for any matrix. |
----------------------------------------------------------------------------- |
|
type matrix_t is array (integer range <>, integer range<>) of bit; |
|
function get_row ( |
constant matrix : matrix_t; |
constant row : natural) |
return bit_vector; |
|
function get_col ( |
constant matrix : matrix_t; |
constant col : natural) |
return bit_vector; |
|
procedure set_col ( |
variable M : inout matrix_t; |
constant icol : natural; |
constant col : bit_vector); |
|
-- pragma synthesis_off |
procedure pretty_print_matrix ( |
constant matrix : in matrix_t); |
|
procedure pretty_print_vector ( |
constant vin : in bit_vector); |
-- pragma synthesis_on |
|
function find_col ( |
constant M : matrix_t; |
constant col : bit_vector) |
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 |
|
-- purpose: Return matrix M with columns at positions col1 and col2 |
-- swapped. |
procedure swap_cols ( |
variable M : inout matrix_t; |
constant icol1, icol2 : in natural) is |
|
variable col1, col2 : bit_vector(M'range(1)); |
variable Mout : matrix_t(M'range(1), M'range(2)); |
|
begin |
|
col1 := get_col(M, icol1); |
col2 := get_col(M, icol2); |
|
set_col(M, icol1, col2); |
set_col(M, icol2, col1); |
|
end procedure swap_cols; |
|
-- purpose: Return the matrix row. |
function get_row ( |
constant matrix : matrix_t; |
constant row : natural) |
return bit_vector is |
variable y : bit_vector(matrix'range(2)); |
begin -- function get_row |
|
for col in matrix'range(2) loop |
y(col) := matrix(row, col); |
end loop; -- irow |
|
return y; |
end function get_row; |
|
-- purpose: Return the matrix col. |
function get_col ( |
constant matrix : matrix_t; |
constant col : natural) |
return bit_vector is |
variable y : bit_vector(matrix'range(1)); |
begin -- function get_col |
|
for row in matrix'range(1) loop |
y(row) := matrix(row, col); |
end loop; -- irow |
|
return y; |
end function get_col; |
|
-- purpose: Set the matrix column icol to col. |
procedure set_col ( |
variable M : inout matrix_t; |
constant icol : natural; |
constant col : bit_vector) is |
begin -- function get_col |
|
for row in M'range(1) loop |
M(row, icol) := col(row); |
end loop; -- irow |
|
end procedure set_col; |
|
-- pragma synthesis_off |
|
-- purpose: Print out matrix for debugging. |
procedure pretty_print_matrix ( |
constant matrix : in matrix_t) is |
variable l : line; |
|
begin -- procedure pretty_print_matrix |
|
for row in matrix'range(1) loop |
|
for col in matrix'range(2) loop |
write(l, matrix(row, col)); |
swrite(l, " "); |
end loop; -- col |
|
writeline(output, l); |
end loop; -- row |
|
writeline(output, l); -- blank line |
|
end procedure pretty_print_matrix; |
|
-- purpose: Print out vector for debugging. |
procedure pretty_print_vector ( |
constant vin : in bit_vector) is |
variable l : line; |
|
begin -- procedure pretty_print_matrix |
|
swrite(l, integer'image(vin'left)); |
swrite(l, " to/downto "); |
swrite(l, integer'image(vin'right)); |
swrite(l, ": "); |
for i in vin'range loop |
write(l, vin(i)); |
swrite(l, " "); |
end loop; -- i |
|
writeline(output, l); |
writeline(output, l); -- blank line |
|
end procedure pretty_print_vector; |
|
-- pragma synthesis_on |
|
-- purpose: Return the position of col in M or -1 if not found. |
function find_col ( |
constant M : matrix_t; -- Any matrix |
constant col : bit_vector) -- The column to find |
return integer is |
variable match : boolean; |
begin -- function find_col |
for icol in M'range(2) loop |
|
match := true; |
for j in col'range loop |
if col(j) /= M(j, icol) then |
match := false; |
end if; |
end loop; |
|
if match then |
return icol; |
end if; |
|
end loop; |
|
-- not found |
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; |
/rtl/vhdl/yahamm_dec.vhd
0,0 → 1,324
------------------------------------------------------------------------------- |
-- 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; |
|
library yahamm; |
use yahamm.matrix_pkg.all; |
use yahamm.yahamm_pkg.all; |
|
library std; |
use std.textio.all; |
|
-- There are two monitor counters: |
-- |
-- cnt_errors_corrected: number of error correction performed. |
-- cnt_errors_detected: numbers of errors detected but not corrected. |
-- |
-- The two never count together and they don't overflow. If CORRECT |
-- is false, no correction is performed cnt_errors_corrected never counts. |
-- If CORRECT is true and EXTRA_PARITY_BIT is true, cnt_errors_detected |
-- never counts because all errors (supposedly single-bit errors) are |
-- corrected. |
-- |
-- ERROR_LEN: width of the cnt_errors_corrected and cnt_errors_detected counters. |
-- |
-- dout_valid_o: dout data valid, it's the en input pipelined. It takes into |
-- account the total latency. |
-- |
entity yahamm_dec is |
generic ( |
MESSAGE_LENGTH : natural := 5; |
CORRECT : boolean := true; |
EXTRA_PARITY_BIT : natural range 0 to 1 := 1; |
ONE_PARITY_BIT : boolean := false; |
ERROR_LEN : natural := 16 |
); |
port( |
clk_i, rst_i : in std_logic; |
cnt_clr_i : in std_logic := '0'; -- Clear monitor counters. |
en_i : in std_logic := '1'; -- Input enable. |
data_i : in std_logic_vector(MESSAGE_LENGTH - 1 downto 0); -- Input data. |
parity_i : in std_logic_vector(calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT) + EXTRA_PARITY_BIT - 1 downto 0); -- Parity bits. |
data_o : out std_logic_vector(MESSAGE_LENGTH - 1 downto 0); -- Out data. |
dout_valid_o : out std_logic; -- data_o valid. |
cnt_errors_corrected_o, cnt_errors_detected_o : out std_logic_vector(ERROR_LEN - 1 downto 0); |
log_wrong_bit_pos_data_o : out std_logic_vector(MESSAGE_LENGTH - 1 downto 0); |
log_wrong_bit_pos_parity_o : out std_logic_vector(calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT) + EXTRA_PARITY_BIT - 1 downto 0) |
); |
|
end yahamm_dec; |
|
architecture std of yahamm_dec is |
|
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 H : matrix_t(0 to NPARITY_BITS + EXTRA_PARITY_BIT - 1, |
0 to BLOCK_LENGTH + EXTRA_PARITY_BIT - 1) := |
get_parity_check_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT); |
|
signal data_i_padded : bit_vector(BLOCK_LENGTH - NPARITY_BITS - 1 downto 0); |
signal code_sys, code_nonsys, code_nonsys_q : bit_vector(BLOCK_LENGTH + EXTRA_PARITY_BIT - 1 downto 0); |
signal syndrome : bit_vector(NPARITY_BITS + EXTRA_PARITY_BIT - 1 downto 0); |
signal wrong_bit : integer range 0 to code_sys'length; |
|
constant SWAPM : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY_BIT - 1, |
0 to BLOCK_LENGTH + EXTRA_PARITY_BIT - 1) := |
get_form_swap_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT); |
|
signal correction_en : boolean; |
signal cnt_errors_corrected_o_int, cnt_errors_detected_o_int : unsigned(ERROR_LEN - 1 downto 0); |
signal log_wrong_bit_pos_data_o_sys, log_wrong_bit_pos_data_o_nonsys : bit_vector(BLOCK_LENGTH + EXTRA_PARITY_BIT - 1 downto 0); |
|
signal dout_valid_o_p0 : std_logic; |
|
begin |
|
check_parameters(BLOCK_LENGTH, NPARITY_BITS, MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT, CORRECT); |
|
cnt_errors_corrected_o <= std_logic_vector(cnt_errors_corrected_o_int); |
cnt_errors_detected_o <= std_logic_vector(cnt_errors_detected_o_int); |
|
-- Pad data_i with zeros on the left, so that data_i_padded'length = BLOCK_LENGTH. |
-- This allow the user to reduce data_i width. |
data_i_padded(MESSAGE_LENGTH - 1 downto 0) <= to_bitvector(data_i); |
gen_padding: if BLOCK_LENGTH - NPARITY_BITS > MESSAGE_LENGTH generate |
data_i_padded(BLOCK_LENGTH - NPARITY_BITS - 1 downto MESSAGE_LENGTH) <= (others => '0'); |
end generate gen_padding; |
|
-- Wire data and parity inputs in the systematic code code_sys (data |
-- on LSB, parity on MSB). |
code_sys <= to_bitvector(parity_i) & data_i_padded; |
|
-- Get the non-systematic code code_nonsys by swapping the |
-- systematic code code_sys. The non-systematic code is needed to |
-- obtain an immediately meaningful syndrome. This is timing-safe: |
-- no logic here, it's purely wiring. |
code_nonsys <= xor_multiply_vec(SWAPM, code_sys); |
|
-- Output log_wrong_bit_pos_log, uses log_wrong_bit_pos_log_nonsys is padded |
-- as data_i_padded |
log_wrong_bit_pos_data_o_sys <= xor_multiply_vec(SWAPM, log_wrong_bit_pos_data_o_nonsys); |
log_wrong_bit_pos_data_o <= To_StdLogicVector(log_wrong_bit_pos_data_o_sys(MESSAGE_LENGTH-1 downto 0)); |
log_wrong_bit_pos_parity_o <= To_StdLogicVector(log_wrong_bit_pos_data_o_sys(BLOCK_LENGTH + EXTRA_PARITY_BIT - 1 downto BLOCK_LENGTH - NPARITY_BITS)); |
|
-- purpose: Compute error syndrome from the non-systematic code |
-- (input) and the non-systemacic parity check matrix H. Also delay |
-- code_nonsys to have code_nonsys_q synchronous with syndrome. And start |
-- pipelining en input. |
-- type : sequential |
-- inputs : clk_i, rst_i, code_nonsys |
-- outputs: syndrome |
syndrome_proc: process (clk_i, rst_i) is |
begin -- process syndrome_proc |
if rst_i = '1' then -- asynchronous reset (active high) |
syndrome <= (others => '0'); |
code_nonsys_q <= (others => '0'); |
dout_valid_o_p0 <= '0'; |
elsif rising_edge(clk_i) then -- rising clock edge |
syndrome <= xor_multiply_vec(H, code_nonsys); |
code_nonsys_q <= code_nonsys; |
dout_valid_o_p0 <= en_i; |
end if; |
end process syndrome_proc; |
|
-- purpose: Enable error correction (signal correction_en) for a single bit |
-- error. Dependent from the generic parameters. If correction is enabled |
-- wrong_bit signal is assigned the position of the wrong bit. |
-- type : combinational |
-- inputs : syndrome |
-- outputs: correction_enabled |
correction_enable_proc: process (syndrome) is |
begin -- process correction_enable_proc |
wrong_bit <= 0; |
|
case CORRECT is |
when false => |
-- Entity does not implement correction. |
correction_en <= false; |
|
when true => |
-- Entity implements correction. |
|
case EXTRA_PARITY_BIT is |
when 0 => |
-- SEC case (see table). Always correct. |
correction_en <= true; |
|
-- The wrong bit is the syndrome itself. |
wrong_bit <= to_integer(unsigned(To_StdULogicVector(syndrome))); |
|
when 1 => |
-- SECDED case (see table). The error, if any, is a single error to be |
-- corrected if the extra parity bit in the syndrome is '1'. |
if syndrome(syndrome'high) = '0' then |
-- Double error: don't correct. |
correction_en <= false; |
else |
-- Single error: correct. |
correction_en <= true; |
|
-- The wrong bit is not just the syndrome, because the |
-- syndrome has the extra parity bit as MSB bit. |
if or_reduce(syndrome(syndrome'high-1 downto 0)) = '0' then |
-- No other error. So the extra parity bit itself is |
-- wrong, that in this implementation is the MSB of |
-- the non-systematic code word. |
wrong_bit <= code_nonsys_q'length; |
else |
-- Extra parity bit '1', ignore it for wrong_bit position. |
wrong_bit <= to_integer(unsigned(To_StdULogicVector(syndrome(NPARITY_BITS-1 downto 0)))); |
end if; |
end if; |
end case; |
|
end case; |
|
end process correction_enable_proc; |
|
-- purpose: Decode the non systematic code code_nonsys_q and drive |
-- output data_o. Single error correction is performed, depending on |
-- the configuration. |
-- type : sequential |
-- inputs : clk_i, rst_i, code_nonsys_q, syndrome |
-- outputs: data_o |
decode_proc: process (clk_i, rst_i) is |
variable iserror : boolean; -- parity error condition |
variable code_sys_dec, code_nonsys_dec : bit_vector(code_sys'range); |
begin -- process decode_proc |
if rst_i = '1' then -- asynchronous reset (active high) |
data_o <= (others => '0'); |
dout_valid_o <= '0'; |
elsif rising_edge(clk_i) then -- rising clock edge |
|
if dout_valid_o_p0 = '0' then |
data_o <= (others => '0'); |
dout_valid_o <= '0'; |
else |
|
code_nonsys_dec := code_nonsys_q; |
iserror := or_reduce(syndrome) = '1'; |
|
if correction_en and iserror then |
code_nonsys_dec(wrong_bit-1) := not code_nonsys_q(wrong_bit-1); |
end if; |
|
code_sys_dec := xor_multiply_vec(SWAPM, code_nonsys_dec); |
data_o <= To_StdLogicVector(code_sys_dec(MESSAGE_LENGTH - 1 downto 0)); |
dout_valid_o <= '1'; |
|
end if; |
end if; |
end process decode_proc; |
|
-- purpose: Monitor counters. |
-- type : sequential |
-- inputs : clk_i, rst_i, syndrome, correction_en |
-- outputs: cnt_errors_corrected_o_int, cnt_errors_detected_o_int, log_wrong_bit_pos_log |
cnt_proc: process (clk_i, rst_i) is |
variable iserror : boolean; -- parity error condition |
begin -- process cnt_proc |
if rst_i = '1' then -- asynchronous reset (active high) |
cnt_errors_detected_o_int <= (others => '0'); |
cnt_errors_corrected_o_int <= (others => '0'); |
elsif rising_edge(clk_i) then -- rising clock edge |
if cnt_clr_i = '1' then |
-- synchronous clear |
cnt_errors_detected_o_int <= (others => '0'); |
cnt_errors_corrected_o_int <= (others => '0'); |
else |
iserror := or_reduce(syndrome) = '1'; |
|
if iserror then |
if correction_en then |
if and_reduce(to_bitvector(std_logic_vector(cnt_errors_corrected_o_int))) /= '1' then |
cnt_errors_corrected_o_int <= cnt_errors_corrected_o_int + 1; |
end if; |
else |
if and_reduce(to_bitvector(std_logic_vector(cnt_errors_detected_o_int))) /= '1' then |
cnt_errors_detected_o_int <= cnt_errors_detected_o_int + 1; |
end if; |
end if; |
end if; |
end if; |
|
end if; |
end process cnt_proc; |
|
-- purpose: Monitor counters. |
-- type : sequential |
-- inputs : clk_i, rst_i, syndrome, correction_en |
-- outputs: cnt_errors_corrected_o_int, cnt_errors_detected_o_int, log_wrong_bit_pos_log |
log_wrong_bit_gen: if CORRECT generate |
log_wrong_bit_proc: process (clk_i, rst_i) is |
variable iserror : boolean; -- parity error condition |
begin -- process cnt_proc |
if rst_i = '1' then |
log_wrong_bit_pos_data_o_nonsys <= (others => '0'); |
elsif rising_edge(clk_i) then |
if cnt_clr_i = '1' then |
log_wrong_bit_pos_data_o_nonsys <= (others => '0'); |
else |
iserror := or_reduce(syndrome) = '1'; |
|
if iserror then |
if correction_en then |
|
-- Note: wrong_bit refers to the wrong bit of the code in |
-- non-systematic form. Indeed this is swapped to |
-- systematic form for the output. |
log_wrong_bit_pos_data_o_nonsys(wrong_bit-1) <= '1'; |
|
end if; |
end if; |
end if; |
end if; |
end process log_wrong_bit_proc; |
end generate log_wrong_bit_gen; |
|
end architecture std; |
/rtl/vhdl/yahamm_enc.vhd
0,0 → 1,148
------------------------------------------------------------------------------- |
-- 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). |
-- |
-- SEC = single bit error corrected |
-- SED = single bit error detected |
-- DED = double bit error detected |
-- TED = triple bit error detected |
-- |
-- EXTRA_PARITY_BIT | CORRECT FALSE TRUE |
------------------------------------------------------------------------------- |
-- FALSE | SED-DED SEC |
-- ----------------------------------------------------------- |
-- TRUE | SED-DED-TED SEC-DED |
------------------------------------------------------------------------------- |
-- |
-- Note that, for example, SEC-DED (EXTRA_PARITY_BIT = true, CORRECT = |
-- true) means that triple bit errors are not detected and messages |
-- will be wrongly corrected because the correction corrects toward |
-- the code word within the smaller hamming distance. Practically you |
-- usually know that something is very wrong with your communication |
-- channel because you will also see double bit errors. Then you |
-- should not trust corrected data at all. |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
library yahamm; |
use yahamm.matrix_pkg.all; |
use yahamm.yahamm_pkg.all; |
|
entity yahamm_enc is |
generic ( |
MESSAGE_LENGTH : natural := 5; |
EXTRA_PARITY_BIT : natural range 0 to 1 := 1; |
ONE_PARITY_BIT : boolean := false |
); |
port( |
clk_i, rst_i : in std_logic; |
en_i : in std_logic := '1'; -- Synchronous output enable . |
data_i : in std_logic_vector(MESSAGE_LENGTH - 1 downto 0); -- Input data. |
data_o : out std_logic_vector(MESSAGE_LENGTH - 1 downto 0); -- Out data. |
data_valid_o : out std_logic; |
parity_o : out std_logic_vector(calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT) + EXTRA_PARITY_BIT - 1 downto 0) -- Parity bits. |
); |
|
end yahamm_enc; |
|
architecture std of yahamm_enc is |
|
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 G : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY_BIT - 1, |
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 data_i_padded : bit_vector(BLOCK_LENGTH - NPARITY_BITS - 1 downto 0); |
|
|
begin |
|
check_parameters(BLOCK_LENGTH, NPARITY_BITS, MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT); |
|
data_i_padded(MESSAGE_LENGTH - 1 downto 0) <= to_bitvector(data_i); |
pad_gen: if MESSAGE_LENGTH < BLOCK_LENGTH - NPARITY_BITS generate |
-- Pad data_i with zeros on the left, so that data_i_padded'length = BLOCK_LENGTH. |
-- This allow the user to reduce data_i width. |
data_i_padded(BLOCK_LENGTH - NPARITY_BITS - 1 downto MESSAGE_LENGTH) <= (others => '0'); |
end generate pad_gen; |
|
-- Wire systematic code signal code_sys on data_o and parity_o output ports. |
-- Because of the form of the code generator matrix G, data are the LSB part |
-- of code and parity the MSB part. |
parity_o <= to_slv(code_sys(code_sys'high downto code_sys'high - (EXTRA_PARITY_BIT + NPARITY_BITS) + 1)); |
data_o <= to_slv(code_sys(MESSAGE_LENGTH - 1 downto 0)); |
|
-- purpose: Sequentially encode input with output enable. |
-- type : sequential |
-- inputs : clk_i, rst_i, d_sig |
-- outputs: msg_sys |
encode_proc: process (clk_i, rst_i) is |
begin -- process encode_proc |
if rst_i = '1' then -- asynchronous reset (active high) |
code_sys <= (others => '0'); |
data_valid_o <= '0'; |
elsif rising_edge(clk_i) then -- rising clock edge |
|
if en_i = '0' then -- syncronous output enable |
code_sys <= (others => '0'); |
data_valid_o <= '0'; |
else |
code_sys <= To_StdULogicVector(xor_multiply_vec(G, data_i_padded)); |
data_valid_o <= '1'; |
end if; |
|
end if; |
end process encode_proc; |
|
end architecture std; |
/rtl/vhdl/yahamm_pkg.vhd
0,0 → 1,507
------------------------------------------------------------------------------- |
-- 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 yahamm; |
use yahamm.matrix_pkg.all; |
|
package yahamm_pkg is |
|
component yahamm_dec is |
generic ( |
MESSAGE_LENGTH : natural; |
CORRECT : boolean; |
EXTRA_PARITY_BIT : natural range 0 to 1; |
ONE_PARITY_BIT : boolean; |
ERROR_LEN : natural; |
NPARITY_BITS : natural; |
BLOCK_LENGTH : natural); |
port ( |
clk, rst : in std_logic; |
en : in std_logic; |
din : in std_logic_vector(MESSAGE_LENGTH - 1 downto 0); |
parity : in std_logic_vector(NPARITY_BITS + EXTRA_PARITY_BIT - 1 downto 0); |
dout : out std_logic_vector(MESSAGE_LENGTH - 1 downto 0); |
cnt_errors_corrected, cnt_errors_detected : out std_logic_vector(ERROR_LEN - 1 downto 0)); |
end component yahamm_dec; |
|
component yahamm_enc is |
generic ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY_BIT : natural range 0 to 1; |
ONE_PARITY_BIT : boolean; |
NPARITY_BITS : natural; |
BLOCK_LENGTH : natural); |
port ( |
clk, rst : in std_logic; |
en : in std_logic := '1'; |
din : in std_logic_vector(MESSAGE_LENGTH - 1 downto 0); |
dout : out std_logic_vector(MESSAGE_LENGTH - 1 downto 0); |
parity : out std_logic_vector(NPARITY_BITS + EXTRA_PARITY_BIT - 1 downto 0)); |
end component yahamm_enc; |
|
function get_parity_check_matrix ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY : natural range 0 to 1 := 1; |
ONE_PARITY_BIT : boolean := false) |
return matrix_t; |
|
function get_code_generator_matrix ( |
MESSAGE_LENGTH : natural; |
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 : natural; |
ONE_PARITY_BIT : boolean := false) |
return natural; |
|
function calc_block_length ( |
k : natural; |
ONE_PARITY_BIT : boolean := false) |
return natural; |
|
procedure check_parameters ( |
constant BLOCK_LENGTH : in natural; |
constant NPARITY_BITS : in natural; |
constant MESSAGE_LENGTH : in natural; |
constant EXTRA_PARITY_BIT : in natural; |
constant ONE_PARITY_BIT : in boolean; |
constant CORRECT : in boolean := false |
); |
|
function xor_multiply ( |
A : matrix_t; |
B : matrix_t) |
return matrix_t; |
|
function xor_multiply_vec ( |
A : matrix_t; |
x : bit_vector) |
return bit_vector; |
|
function get_form_swap_matrix ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY : natural; |
ONE_PARITY_BIT : boolean := false) |
return matrix_t; |
|
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 |
-- transposed = S^-1). Use as as MS = M x S. |
-- Also works for M with extra parity bit: set EXTRA_PARITY to 1 and |
-- the swap matrix increases of one extra column and one extra row |
-- (as the parity check matrix) and the extra column is not swapped. |
function get_form_swap_matrix ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY : natural; |
ONE_PARITY_BIT : boolean := false) |
return matrix_t is |
|
constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT); |
constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT); |
|
variable idmatrix : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY - 1, 0 to BLOCK_LENGTH + EXTRA_PARITY - 1) := (others => (others => '0')); |
variable swap_matrix : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY - 1, 0 to BLOCK_LENGTH + EXTRA_PARITY - 1); -- output |
|
begin -- function get_systematic_swap_matrix |
|
-- Fill up the identity matrix idmatrix. It's initialized to zeros, so |
-- just write ones on the diagonal. |
for irow in idmatrix'range(1) loop |
for icol in idmatrix'range(2) loop |
if irow = icol then |
idmatrix(irow, icol) := '1'; |
end if; |
end loop; |
end loop; |
|
-- Swap columns corresponding to parity bits position in the |
-- parity check matrix (0, 1, 3, 7 etc...) with the right-most |
-- columns (starting with inner possibile rightmost). E.g. let's |
-- say that, with the given message length, BLOCK_LENGTH is 7 and |
-- the parity bits are in positions 0, 1 and 3. The swap will be: |
-- 0 <-> 5 |
-- 1 <-> 6 |
-- 3 <-> 7 |
-- |
-- Note: if EXTRA_PARITY is set, last colum is ignored because is not to be |
-- swapped. |
swap_matrix := idmatrix; |
for np in 0 to NPARITY_BITS-1 loop |
swap_cols(swap_matrix, 2**np - 1, BLOCK_LENGTH - NPARITY_BITS + np); |
end loop; -- np |
|
return swap_matrix; |
|
end function get_form_swap_matrix; |
|
-- purpose: Return the result of the matrix M x vector v product. Internal sums are |
-- replaced by xor operations. E.g.: |
-- [1 1; 0 1] * [a; b] = [a xor b; b] |
-- [1 1; 0 1] * [1 1; 1 0] = [0 1; 1 0] |
function xor_multiply ( |
A : matrix_t; |
B : matrix_t) |
return matrix_t is |
|
--variable y : bit_vector(A'reverse_range(1)); |
variable y : matrix_t(A'range(1), B'range(2)); |
variable element : bit; |
|
begin -- function matrix_multiply |
|
--report "xor_multiply: Matrix A sized " |
-- & integer'image(A'length(1)) & "x" & integer'image(A'length(2)) |
-- & ". Matrix B sized " |
-- & integer'image(B'length(1)) & "x" & integer'image(B'length(2)) & "." |
-- severity note; |
|
assert A'length(2) = B'length(1) |
report "Cannot multiply matrix A sized " |
& integer'image(A'length(1)) & "x" & integer'image(A'length(2)) |
& " with matrix B sized " |
& integer'image(B'length(1)) & "x" & integer'image(B'length(2)) & "." |
severity error; |
|
for Arow in A'range(1) loop |
for Bcol in B'range(2) loop |
|
element := '0'; |
for Acol in A'range(2) loop |
element := element xor (A(Arow, Acol) and B(Acol, Bcol)); |
end loop; -- i |
|
y(Arow, Bcol) := element; |
|
--report |
-- "(" & integer'image(Arow) & ", " & integer'image(Bcol) & "): " & |
-- "y(Arow, Bcol) := " & bit'image(element) |
-- severity note; |
|
end loop; -- Bcol |
|
--assert false report "y(" & integer'image(y'length-Arow-1) & ") := " & bit'image(y(y'length-Arow-1)) severity note; |
end loop; |
|
--pretty_print_matrix(A); |
--pretty_print_matrix(B); |
--pretty_print_matrix(y); |
|
return y; |
|
end function xor_multiply; |
|
|
-- purpose: Return the result of the matrix operation y = A*x using |
-- xor_multiply function. See xor_multiply comment for details. |
function xor_multiply_vec ( |
A : matrix_t; |
x : bit_vector) |
return bit_vector is |
|
variable B : matrix_t(x'range, 0 to 0); |
variable C : matrix_t(A'range(1), 0 to 0); |
|
variable y : bit_vector(A'reverse_range(1)); -- output |
|
begin -- function matrix_multiply |
|
assert A'length(2) = x'length |
report "Cannot multiply matrix A sized " |
& integer'image(A'length(1)) & "x" & integer'image(A'length(2)) |
& " with vector x of length " |
& integer'image(x'length) & "." |
severity error; |
|
-- Transform bit_vector x into a 1-column matrix_t. |
for i in x'range loop |
B(i, 0) := x(i); |
end loop; -- i |
|
C := xor_multiply(A, B); |
|
-- Transform the 1-column matrix_t C into a bit_vector. |
for i in C'range(1) loop |
y(i) := C(i, 0); |
end loop; -- i |
|
--report "xor_multiply_vec: Matrix A sized " |
-- & integer'image(A'length(1)) & "x" & integer'image(A'length(2)) |
-- & ". Matrix B sized " |
-- & integer'image(B'length(1)) & "x" & integer'image(B'length(2)) & "." |
-- severity note; |
|
--pretty_print_matrix(A); |
--pretty_print_matrix(B); |
--pretty_print_matrix(C); |
--pretty_print_vector(y); |
|
return y; |
|
end function xor_multiply_vec; |
|
-- purpose: Generate the parity check matrix for a given message length. The |
-- matrix is in non-systematic form. |
function get_parity_check_matrix ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY : natural range 0 to 1 := 1; -- increase hamming distance to 4 |
ONE_PARITY_BIT : boolean := false) |
return matrix_t is |
|
constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT); |
constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT); |
|
variable m : matrix_t(0 to NPARITY_BITS-1, 0 to BLOCK_LENGTH-1); |
variable parity, bit_pos : natural; |
variable ubit_pos : unsigned(BLOCK_LENGTH - 1 downto 0); |
|
-- add 1 row and 1 column respect to m to build a parity check |
-- matrix with extra parity bit. |
variable m_extra : matrix_t(0 to m'length(1), 0 to m'length(2)); |
variable hecol : bit_vector(m_extra'range(1)); |
|
begin -- function get_parity_check_matrix |
|
if ONE_PARITY_BIT then |
m := (0 => (others => '1')); |
return m; |
end if; |
|
for iparity in m'range(1) loop |
parity := 2**iparity; |
|
if parity >= 2 then |
for bit_pos in 0 to parity-2 loop |
m(iparity, bit_pos) := '0'; |
end loop; |
end if; |
|
for bit_pos in parity-1 to m'length(2)-1 loop |
ubit_pos := to_unsigned(bit_pos+1, BLOCK_LENGTH); |
|
m(iparity, bit_pos) := to_bit(ubit_pos(iparity)); |
|
end loop; -- bit_pos |
end loop; -- iparity |
|
if EXTRA_PARITY = 0 then |
return m; |
else |
-- m_extra is the parity check matrix with extra parity bits. |
-- It is constructed from m in 2 steps. m_extra has an extra |
-- row and extra column respect to m. |
|
-- 1. copy m in m_extra. |
for irow in m'range(1) loop |
for icol in m'range(2) loop |
m_extra(irow, icol) := m(irow, icol); |
end loop; |
end loop; |
|
-- 2. Add extra row with '1'. |
for icol in m_extra'range(2) loop |
m_extra(m_extra'high(1), icol) := '1'; |
end loop; |
|
return m_extra; |
end if; |
|
end function get_parity_check_matrix; |
|
-- purpose: Create the code generator matrix in systematic form. |
function get_code_generator_matrix ( |
MESSAGE_LENGTH : natural; |
EXTRA_PARITY : natural range 0 to 1 := 1; -- increase hamming ndistance to 4 |
ONE_PARITY_BIT : boolean := false) |
|
return matrix_t is |
|
constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT); |
constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT); |
|
-- The only reason the code generator matrix is systematic is because H |
-- returned from get_code_generator_matrix is systematic (see |
-- make_systematic in code_generator_matrix). |
variable H : matrix_t(0 to NPARITY_BITS + EXTRA_PARITY - 1, |
0 to BLOCK_LENGTH + EXTRA_PARITY - 1) := get_parity_check_matrix(MESSAGE_LENGTH, |
EXTRA_PARITY, |
ONE_PARITY_BIT); |
|
-- G is the code generator matrix. |
variable G : matrix_t(0 to BLOCK_LENGTH - NPARITY_BITS - 1, 0 to BLOCK_LENGTH + EXTRA_PARITY - 1); |
-- GT is G transposed. |
variable GT : matrix_t(G'range(2), G'range(1)); |
|
variable gcol : bit_vector(H'range(2)); -- G matrix column |
variable hcol : bit_vector(H'range(1)); -- H matrix column |
|
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'); |
gcol(col) := '1'; |
set_col(G, col, gcol); |
end loop; -- col |
|
-- transform H in systematic form |
swap_matrix := get_form_swap_matrix(MESSAGE_LENGTH, EXTRA_PARITY, ONE_PARITY_BIT); |
H := xor_multiply(H, swap_matrix); |
|
if EXTRA_PARITY = 1 then |
-- This is a trick that avoids a very tedious row reduction. |
|
for icol in H'range(2) loop |
hcol := get_col(H, icol); |
if xor_reduce(hcol) = '0' then |
H(H'high(1), icol) := '0'; |
end if; |
end loop; -- icol |
|
end if; |
|
--pretty_print_matrix(H); |
--pretty_print_matrix(xor_multiply(H, swap_matrix)); |
|
-- Submatrix A transposed. |
for col in BLOCK_LENGTH - NPARITY_BITS to BLOCK_LENGTH + EXTRA_PARITY - 1 loop |
for row in 0 to BLOCK_LENGTH - NPARITY_BITS - 1 loop |
G(row, col) := H(col-(BLOCK_LENGTH-NPARITY_BITS), row); |
end loop; |
end loop; |
|
-- transpose G |
for irow in G'range(1) loop |
for icol in G'range(2) loop |
GT(icol, irow) := G(irow, icol); |
end loop; |
end loop; |
|
return GT; |
|
end function get_code_generator_matrix; |
|
-- purpose: Calculate the number of parity bits (r) needed for the |
-- specified message length (k). The code has m = 2^r - r - 1 for r >= 2. |
function calc_nparity_bits ( |
k : natural; |
ONE_PARITY_BIT : boolean := false) |
return natural is |
variable r : natural := 0; |
begin -- function calc_nparity_bits |
|
-- assert k > 0 report "Code construction not implement for message length 0." severity failure; |
|
if ONE_PARITY_BIT then |
return 1; |
end if; |
|
r := 0; |
while true loop |
if 2**r - r - 1 >= k then |
return r; |
end if; |
|
r := r + 1; |
end loop; |
|
report "This should never happen." severity failure; |
return 0; |
|
end function calc_nparity_bits; |
|
-- 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 ( |
k : natural; |
ONE_PARITY_BIT : boolean := false) |
return natural is |
variable r : natural := 0; |
begin -- function calc_nparity_bits |
|
-- assert k > 0 report "Code construction not implement for message length 0." severity failure; |
|
if ONE_PARITY_BIT then |
return k + 1; |
end if; |
|
r := calc_nparity_bits(k); |
|
return 2**r - 1; |
|
end function calc_block_length; |
|
procedure check_parameters ( |
constant BLOCK_LENGTH : in natural; |
constant NPARITY_BITS : in natural; |
constant MESSAGE_LENGTH : in natural; |
constant EXTRA_PARITY_BIT : in natural; |
constant ONE_PARITY_BIT : in boolean; |
constant CORRECT : in boolean := false) is |
begin |
assert BLOCK_LENGTH = calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT) report "Invalid parameter value BLOCK_LENGTH := " & natural'image(BLOCK_LENGTH) severity failure; |
assert NPARITY_BITS = calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT) report "Invalid parameter value NPARITY_BITS := " & natural'image(NPARITY_BITS) severity failure; |
|
if ONE_PARITY_BIT then |
assert EXTRA_PARITY_BIT = 0 report "EXTRA_PARITY_BIT 1 is not compatible with ONE_PARITY_BIT true." severity failure; |
assert CORRECT = false report "CORRECT true is not compatible with ONE_PARITY_BIT true." severity failure; |
end if; |
|
end procedure check_parameters; |
|
end package body yahamm_pkg; |
/sim/Makefile
File deleted
/sim/yahamm_tb0.vhd
File deleted
/sim/yahamm_tb1.vhd
File deleted
/sim/yahamm_tb2.vhd
File deleted
/sim/yahamm_tb3.vhd
File deleted