1 |
4 |
ndesimone |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Yahamm IP core
|
3 |
|
|
--
|
4 |
|
|
-- This file is part of the Yahamm project
|
5 |
|
|
-- http://www.opencores.org/cores/yahamm
|
6 |
|
|
--
|
7 |
|
|
-- Description
|
8 |
|
|
-- A hamming encoder and decoder with single-error correcting and
|
9 |
|
|
-- double-error detecting capability. The message length can be configured
|
10 |
|
|
-- through a generic. Both the code generator matrix and the parity-check
|
11 |
|
|
-- matrix are computed in the VHDL itself.
|
12 |
|
|
--
|
13 |
|
|
-- Author:
|
14 |
|
|
-- - Nicola De Simone, ndesimone@opencores.org
|
15 |
|
|
--
|
16 |
|
|
-------------------------------------------------------------------------------
|
17 |
|
|
--
|
18 |
|
|
-- Copyright (C) 2017 Authors and OPENCORES.ORG
|
19 |
|
|
--
|
20 |
|
|
-- This source file may be used and distributed without
|
21 |
|
|
-- restriction provided that this copyright statement is not
|
22 |
|
|
-- removed from the file and that any derivative work contains
|
23 |
|
|
-- the original copyright notice and the associated disclaimer.
|
24 |
|
|
--
|
25 |
|
|
-- This source file is free software; you can redistribute it
|
26 |
|
|
-- and/or modify it under the terms of the GNU Lesser General
|
27 |
|
|
-- Public License as published by the Free Software Foundation;
|
28 |
|
|
-- either version 2.1 of the License, or (at your option) any
|
29 |
|
|
-- later version.
|
30 |
|
|
--
|
31 |
|
|
-- This source is distributed in the hope that it will be
|
32 |
|
|
-- useful, but WITHOUT ANY WARRANTY; without even the implied
|
33 |
|
|
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
34 |
|
|
-- PURPOSE. See the GNU Lesser General Public License for more
|
35 |
|
|
-- details.
|
36 |
|
|
--
|
37 |
|
|
--- You should have received a copy of the GNU Lesser General
|
38 |
|
|
-- Public License along with this source; if not, download it
|
39 |
|
|
-- from http://www.opencores.org/lgpl.shtml
|
40 |
|
|
--
|
41 |
|
|
-------------------------------------------------------------------------------
|
42 |
|
|
|
43 |
2 |
ndesimone |
-- CORRECT: set to true to correct errors at the cost of decreasing error
|
44 |
|
|
-- detection (see table).
|
45 |
|
|
--
|
46 |
|
|
-- SEC = single bit error corrected
|
47 |
|
|
-- SED = single bit error detected
|
48 |
|
|
-- DED = double bit error detected
|
49 |
|
|
-- TED = triple bit error detected
|
50 |
|
|
--
|
51 |
|
|
-- EXTRA_PARITY_BIT | CORRECT FALSE TRUE
|
52 |
|
|
-------------------------------------------------------------------------------
|
53 |
|
|
-- FALSE | SED-DED SEC
|
54 |
|
|
-- -----------------------------------------------------------
|
55 |
|
|
-- TRUE | SED-DED-TED SEC-DED
|
56 |
|
|
-------------------------------------------------------------------------------
|
57 |
|
|
--
|
58 |
|
|
-- Note that, for example, SEC-DED (EXTRA_PARITY_BIT = true, CORRECT =
|
59 |
|
|
-- true) means that triple bit errors are not detected and messages
|
60 |
|
|
-- will be wrongly corrected because the correction corrects toward
|
61 |
|
|
-- the code word within the smaller hamming distance. Practically you
|
62 |
|
|
-- usually know that something is very wrong with your communication
|
63 |
|
|
-- channel because you will also see double bit errors. Then you
|
64 |
|
|
-- should not trust corrected data at all.
|
65 |
|
|
|
66 |
|
|
library ieee;
|
67 |
|
|
use ieee.std_logic_1164.all;
|
68 |
|
|
|
69 |
|
|
library yahamm;
|
70 |
|
|
use yahamm.matrix_pkg.all;
|
71 |
4 |
ndesimone |
use yahamm.yahamm_pkg.all;
|
72 |
2 |
ndesimone |
|
73 |
|
|
entity yahamm_enc is
|
74 |
|
|
generic (
|
75 |
|
|
MESSAGE_LENGTH : natural := 5;
|
76 |
|
|
EXTRA_PARITY_BIT : natural range 0 to 1 := 1;
|
77 |
|
|
ONE_PARITY_BIT : boolean := false
|
78 |
|
|
);
|
79 |
|
|
port(
|
80 |
5 |
ndesimone |
clk_i, rst_i : in std_logic;
|
81 |
|
|
en_i : in std_logic := '1'; -- Synchronous output enable .
|
82 |
|
|
data_i : in std_logic_vector(MESSAGE_LENGTH - 1 downto 0); -- Input data.
|
83 |
|
|
data_o : out std_logic_vector(MESSAGE_LENGTH - 1 downto 0); -- Out data.
|
84 |
8 |
ndesimone |
data_valid_o : out std_logic; -- High when data_o is valid.
|
85 |
5 |
ndesimone |
parity_o : out std_logic_vector(calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT) + EXTRA_PARITY_BIT - 1 downto 0) -- Parity bits.
|
86 |
2 |
ndesimone |
);
|
87 |
|
|
|
88 |
|
|
end yahamm_enc;
|
89 |
|
|
|
90 |
|
|
architecture std of yahamm_enc is
|
91 |
|
|
|
92 |
|
|
constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT);
|
93 |
|
|
constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT);
|
94 |
|
|
|
95 |
|
|
constant G : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY_BIT - 1,
|
96 |
|
|
|
97 |
|
|
get_code_generator_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT);
|
98 |
|
|
|
99 |
4 |
ndesimone |
-- G'reverse_range(1) doesn't work in ghdl 0.34
|
100 |
|
|
--signal code_sys : std_ulogic_vector(G'reverse_range(1)); -- systematic code
|
101 |
|
|
signal code_sys : std_ulogic_vector(BLOCK_LENGTH + EXTRA_PARITY_BIT -1 downto 0); -- systematic code
|
102 |
|
|
|
103 |
5 |
ndesimone |
signal data_i_padded : bit_vector(BLOCK_LENGTH - NPARITY_BITS - 1 downto 0);
|
104 |
2 |
ndesimone |
|
105 |
4 |
ndesimone |
|
106 |
2 |
ndesimone |
begin
|
107 |
|
|
|
108 |
|
|
check_parameters(BLOCK_LENGTH, NPARITY_BITS, MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT);
|
109 |
|
|
|
110 |
5 |
ndesimone |
data_i_padded(MESSAGE_LENGTH - 1 downto 0) <= to_bitvector(data_i);
|
111 |
2 |
ndesimone |
pad_gen: if MESSAGE_LENGTH < BLOCK_LENGTH - NPARITY_BITS generate
|
112 |
5 |
ndesimone |
-- Pad data_i with zeros on the left, so that data_i_padded'length = BLOCK_LENGTH.
|
113 |
|
|
-- This allow the user to reduce data_i width.
|
114 |
|
|
data_i_padded(BLOCK_LENGTH - NPARITY_BITS - 1 downto MESSAGE_LENGTH) <= (others => '0');
|
115 |
2 |
ndesimone |
end generate pad_gen;
|
116 |
|
|
|
117 |
5 |
ndesimone |
-- Wire systematic code signal code_sys on data_o and parity_o output ports.
|
118 |
2 |
ndesimone |
-- Because of the form of the code generator matrix G, data are the LSB part
|
119 |
|
|
-- of code and parity the MSB part.
|
120 |
5 |
ndesimone |
parity_o <= to_slv(code_sys(code_sys'high downto code_sys'high - (EXTRA_PARITY_BIT + NPARITY_BITS) + 1));
|
121 |
|
|
data_o <= to_slv(code_sys(MESSAGE_LENGTH - 1 downto 0));
|
122 |
2 |
ndesimone |
|
123 |
|
|
-- purpose: Sequentially encode input with output enable.
|
124 |
|
|
-- type : sequential
|
125 |
5 |
ndesimone |
-- inputs : clk_i, rst_i, d_sig
|
126 |
2 |
ndesimone |
-- outputs: msg_sys
|
127 |
5 |
ndesimone |
encode_proc: process (clk_i, rst_i) is
|
128 |
2 |
ndesimone |
begin -- process encode_proc
|
129 |
5 |
ndesimone |
if rst_i = '1' then -- asynchronous reset (active high)
|
130 |
2 |
ndesimone |
code_sys <= (others => '0');
|
131 |
5 |
ndesimone |
data_valid_o <= '0';
|
132 |
|
|
elsif rising_edge(clk_i) then -- rising clock edge
|
133 |
2 |
ndesimone |
|
134 |
5 |
ndesimone |
if en_i = '0' then -- syncronous output enable
|
135 |
2 |
ndesimone |
code_sys <= (others => '0');
|
136 |
5 |
ndesimone |
data_valid_o <= '0';
|
137 |
2 |
ndesimone |
else
|
138 |
5 |
ndesimone |
code_sys <= To_StdULogicVector(xor_multiply_vec(G, data_i_padded));
|
139 |
|
|
data_valid_o <= '1';
|
140 |
2 |
ndesimone |
end if;
|
141 |
|
|
|
142 |
|
|
end if;
|
143 |
|
|
end process encode_proc;
|
144 |
|
|
|
145 |
|
|
end architecture std;
|