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

Subversion Repositories yahamm

[/] [yahamm/] [trunk/] [doc/] [src/] [design.tex] - Blame information for rev 11

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 ndesimone
\documentclass[twoside,a4paper]{refart}
2 11 ndesimone
\usepackage{ae}
3 9 ndesimone
\usepackage{makeidx}
4
\usepackage{ifthen}
5
\usepackage{url}
6 11 ndesimone
\usepackage[outputdir=..]{minted}
7 9 ndesimone
\usepackage{graphicx}
8
\usepackage{svg}
9
\usepackage{makecell}
10
\usepackage{multirow}
11
\usepackage{pbox}
12
 
13
%% \def\bs{\char'134 } % backslash in \tt font.
14
%% \newcommand{\ie}{i.\,e.,}
15
%% \newcommand{\eg}{e.\,g..}
16
%% \DeclareRobustCommand\cs[1]{\texttt{\char`\\#1}}
17
 
18
\title{YAHAMM\\
19
  Yet Another Hamming Encoder and Decoder\\
20
  ---\\
21
  Design
22
}
23
\author{Nicola De Simone (ndesimone@opencores.org)\\
24
Version 0.1}
25
\date{}
26
\emergencystretch1em  %
27
 
28
\pagestyle{myfootings}
29
\markboth{YAHAMM Design}%
30
         {YAHAMM Design}
31
 
32
\makeindex
33
 
34
\setcounter{tocdepth}{2}
35
% \settextfraction{0.7}
36
 
37
 
38
\begin{document}
39
 
40
\maketitle
41
 
42
\tableofcontents
43
 
44
\newpage
45
 
46
 
47
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48
 
49
The present document assumes that the reader is familiar with the Specification Document and with the references \textit{Hamming code} \cite{ham} and \textit{Hamming(7,4)} \cite{ham74} and with the terminology used therein.  No additional knowledge is needed, apart from basic matrix algebra.  Information already included in those documents are not be duplicated.
50
 
51
\section{General structure}
52
 
53
The user connects the encoder entity in \verb|yahamm_enc| to the decoder entity \verb|yahamm_dec|, as described by the specification document.  No other logic is needed.  The amount of code in those two entities is kept to the minimal by choice.  In the encoder the core functionality is in the synchronous logic:
54
 
55
\begin{verbatim}
56
        code_sys <= to_slv(xor_multiply_vec(G, data_i_padded));
57
\end{verbatim}
58
 
59
corresponding to the math operation:
60
\begin{displaymath}
61
\mathbf{code\_sys} = \mathbf{G} \; \mathbf{data\_i\_padded}
62
\end{displaymath}
63
where \verb|G| is the code generator matrix in systematic form, \verb|data_i_padded| the input data and \verb|code_sys| the code word in systematic form.
64
 
65
Similarly, in the decoder the core functionality is in the synchronous logic:
66
 
67
\begin{verbatim}
68
      syndrome <= xor_multiply_vec(H, code_nonsys);
69
\end{verbatim}
70
 
71
corresponding to the math operation:
72
\begin{displaymath}
73
\mathbf{syndrome} = \mathbf{H} \; \mathbf{code\_nonsys}
74
\end{displaymath}
75
where \verb|H| is the parity-check matrix in non-systematic form, \verb|code_non_sys| the input data in non-systematic form and \verb|syndrome| the error syndrome vector that identifies the patterns of errors.
76
 
77
There is some more logic in the decoder entity \verb|yahamm_dec| to implement the counters of errors corrected or detected and the position of the error.
78
 
79
The higher complexity is hidden inside the package \verb|yahamm_pkg| where there are the functions to create the code generator matrix and the parity-check-matrix, to calculate the number of parity bits, block length, to swap between systematic and non-systematic form, to multiply two matrices or matrix and vector.  \verb|matrix_pkg| contains some help functions for \verb|yahamm_pkg|.
80
 
81
\paragraph{One parity bit}
82
If the encoder and the decoder are configured with the generic \verb|ONE_PARITY_BIT| set to true, their behavior change to a simple one parity bit encoder and decoder.  This is still described and handled with same matrix formalism of the Hamming code, so all math functions accept a parameter \verb|ONE_PARITY_BIT| and behave differently in this case.
83
 
84
\paragraph{Additional parity bit (SECDED)}
85
Hamming codes can be extended by an extra parity bit. This way, it is possible to increase the minimum distance of the Hamming code to 4, which allows the decoder to distinguish between single bit errors and two-bit errors. Thus the decoder can detect and correct a single error and at the same time detect (but not correct) a double error. If the decoder does not attempt to correct errors, it can detect up to three errors \cite{ham}.
86
 
87
\verb|EXTRA_PARITY_BIT| adds an extra row and extra column to the parity-check matrix and it's handled as a special case in the construction of the code generator matrix.
88
 
89
\paragraph{Bus padding}
90
Incoming data bus \verb|data_i| are zero-padded on the most significant bit to length $2^r - r - 1$, where $r$ is the number of parity bits \verb|NPARITY_BITS| specified by generic.  This allow the user to use a data bus of any width, ideally the smallest necessary in order to economize routing resources, while the logic for the Hamming code can operate with the standard block length for any given number of parity bits.
91
 
92
\section{matrix\_pkg}
93
File matrix\_pkg.vhd.
94
 
95
\section{Encoder}
96
See Fig.~\ref{fig:encoder}.  Entity \verb|yahamm_enc|, file yahamm\_enc.vhd.  Latency 1.
97
 
98
\begin{figure}[!ht]
99
  \centering
100
  \includesvg[width=1.1\textwidth]{yahamm_enc}
101
  \caption{Encoder structure.}
102
  \label{fig:encoder}
103
\end{figure}
104
 
105
Input data \verb|data_i| are zero-padded, then multiplied by the code generator matrix $\mathbf{G}$ in systematic form (see Sec.~\ref{sec:codegen}) to compute the code word in systematic form.  Note that the only synthesized logic up to this point are the xor operations used to perform the product with the code generator matrix.
106
 
107
The code word in systematic form had the data in lower significant bits, routed on the output port \verb|data_o|, and the parity bits in the highest significant bits, route on the output port \verb|parity_o|.  \verb|data_valid_o| is the synchronous clear signal \verb|en_i| delayed.
108
 
109
\section{Decoder}
110
See Fig.~\ref{fig:decoder}.  Entity \verb|yahamm_dec|, file yahamm\_dec.vhd.  Latency 2.
111
 
112
\begin{figure}[!ht]
113
  \centering
114
  \includesvg[scale=.30,angle=90]{yahamm_dec}
115
  \caption{Decoder structure.}
116
  \label{fig:decoder}
117
\end{figure}
118
 
119
Input parity bits \verb|parity_i| together with zero-padded input data \verb|data_i| form the systematic code word.  This is swapped to non-systematic form multiplying for the swapping matrix $\mathbf{S}$ (see Sec.~\ref{sec:swap}).   The non-systematic code word is multiplied by the parity-check matrix $\mathbf{H}$ in non-systematic form (see Sec.~\ref{sec:paritycheck}) to compute the syndrome.  Note that the only synthesized logic up to this point are the xor operations used to perform the product with the parity-check matrix.
120
 
121
A non zero syndrome means indicates an error.  There are different possibilities, depending on the user choice of the value of the generics \verb|CORRECT| and \verb|EXTRA_PARITY_BIT|, as show by Table~\ref{tab:secded}.  A combinatorial logic (see \emph{Correction Assessment} in Fig.~\ref{fig:decoder}) determines if the correction has to be done (\verb|correction_en| signal|) and the position of the wrong bit (\verb|wrong_bit| signal).  In the SECDED configuration (\verb|CORRECT| true and \verb|EXTRA_PARITY_BIT| 1), a double error can be detected observing that the syndrome is odd with only the extra parity bit '1', and no correction is done.
122
 
123
In the Single Event Detected case (SEC), and with \verb|CORRECT| generic set to \verb|true|, the wrong bit is then corrected in the non-systematic form of the code word.  This is then swapped to systematic form and \verb|data_o| data output is the least signal part of this code word.
124
 
125 11 ndesimone
Single Error and Double Error are counted (\verb|cnt_proc| process) and the counters connected to the output ports \verb|cnt_errors_corrected_o| and \verb|cnt_errors_detected_o|.  \verb|cnt_errors_corrected_o| increments only in the SEC case (see Table~\ref{tab:secded}).   In all other cases errors, if any, are not corrected and are counted by \verb|cnt_errors_detected_o|.  Counters can be synchronously cleared with the input \verb|cnt_clr_i|.
126 9 ndesimone
 
127 11 ndesimone
In the SEC case (see Table~\ref{tab:secded}) the position of the wrong bit in case of Single Error is used to flip the corresponding bit in the internal \verb|log_wrong_bit_pos_data_o_nonsys| that, after form swapping and slicing, is mapped to the output ports \verb|log_wrong_bit_pos_data_o| and \verb|log_wrong_bit_pos_parity_o|.  They can be synchronously cleared with the input \verb|cnt_clr_i|.
128 9 ndesimone
 
129
 
130
\begin{table}
131
\hspace{-6cm}
132
\begin{tabular}{cc|c|c|}
133
  \cline{3-4}
134
  \multicolumn{1}{c}{} & & \multicolumn{2}{c|}{\texttt{CORRECT}}\\\cline{3-4}
135
  \multicolumn{1}{c}{} &  & false & true\\\hline
136
  \multicolumn{1}{ |c }{\multirow{2}{*}{\texttt{EXTRA\_PARITY\_BIT}}} &
137
                                                                        \multicolumn{1}{ |c| }{0} & \multicolumn{1}{c|}{\multirow{2}{*}{\makecell{Correction disabled }}} & \makecell{\emph{(SEC)}\\\begin{tabular}{c|c|c|}\hline\multicolumn{1}{|c|}{\multirow{2}{*}{\texttt{syndrome}}} & 0 & no error\\\cline{2-3}\multicolumn{1}{|c|}{} & $\neq 0$ & \texttt{wrong\_bit <= syndrome}\\\hline\end{tabular}\\\\}\\\cline{2-2}\cline{4-4}
138
  \multicolumn{1}{ |c }{} &
139
                            \multicolumn{1}{ |c| }{1} & &
140
  \makecell{\emph{(SECDED)}\\\begin{tabular}{cc|c|c|}
141
    \cline{3-4}
142
    \multicolumn{1}{c}{} & & \multicolumn{2}{c|}{\texttt{syndrome's MSB}}\\\cline{3-4}
143
    \multicolumn{1}{c}{} &  & '0' & '1' \\\hline
144
    \multicolumn{1}{ |c }{\multirow{2}{*}{\texttt{syndrome's LSBs}}} &
145
                                                                          \multicolumn{1}{ |c| }{0} & no error & \makecell{SEC\\\texttt{wrong\_bit <= extra\_bit}} \\\cline{2-2}\cline{3-4}
146
    \multicolumn{1}{ |c }{} &
147
                               \multicolumn{1}{ |c| }{$\neq 0$} & \makecell{DED\\no correction} & \makecell{SEC\\\texttt{wrong\_bit <= syndrome LSBs}}\\\hline\end{tabular}\\\\}
148
 
149
  % % %   \makecell{syndrome's MSB\\(extra bit)} & \multicolumn{2}{c|}{syndrome's LSBs}\\
150
  % % %   % && \multicolumn{2}{c|}{syndrome's LSBs}\\
151
  % % %   % \cline{2-3}
152
  % % %   % '0' & \makecell{Double error\\\makecell{\texttt{correction\_en <= false} \\ \texttt{wrong\_bit <= 0}}}&\\\hline '1' &\makecell{Single error\\\makecell{\texttt{correction\_en <= true} \\\\ \pbox{5cm}{The wrong bit is the syndrom MSB itself if the remaining part of the syndrome is zero, otherwise it is the one corresponding to the remaining part of the syndrome.}}}&\\\hline
153
  % \end{tabular}}
154
  \\\hline
155
\end{tabular}
156
\caption{}
157
  \label{tab:secded}
158
\end{table}
159
 
160
% The codeword in systematic form had the data in lower significant bits, routed on the output port \verb|data_o|, and the parity bits in the highest significant bits, route on the output port \verb|parity_o|.  \verb|data_valid_o| is the synchronous clear signal \verb|en_i| delayed.
161
 
162
\section{yahamm\_pkg}
163
File yahamm\_pkg.vhd.
164
 
165
\paragraph{function calc\_nparity\_bits}
166
\begin{minted}{vhdl}
167
  function calc_nparity_bits (
168
    k : natural;
169
    ONE_PARITY_BIT : boolean := false)
170
    return natural;
171
\end{minted}
172
 
173
$r$ parity bits can cover up to $2^r - 1$ bits, including data and parity bits.  That is $2^r - r - 1$ data bits.  The function returns the smallest $r$ such that $2^r - r - 1 \geq k$, where $k$ is the message length (number of data bits).  It returns 1 if \verb|ONE_PARITY_BIT| is true, by definition.
174
 
175
\paragraph{function calc\_block\_length}
176
\begin{minted}{vhdl}
177
  function calc_block_length (
178
    k : natural;
179
    ONE_PARITY_BIT : boolean := false)
180
    return natural;
181
\end{minted}
182
Length of message bits plus parity bits.   $r$ parity bits can cover up to $2^r - 1$ bits, including data and parity bits.  The function returns $2^r - 1$ where \verb|r := calc_nparity_bits(k)|.  It returns $k+1$ if \verb|ONE_PARITY_BIT| is true.
183
 
184
\paragraph{function calc\_block\_length}
185
\begin{minted}{vhdl}
186
  function calc_block_length (
187
    k : natural;
188
    ONE_PARITY_BIT : boolean := false)
189
    return natural;
190
  \end{minted}
191
Length of message bits plus parity bits.   $r$ parity bits can cover up to $2^r - 1$ bits, including data and parity bits.  The function returns $2^r - 1$ where \verb|r := calc_nparity_bits(k)|.  It returns $k+1$ if \verb|ONE_PARITY_BIT| is true.  Note that block length does not depend from \verb|EXTRA_PARITY_BIT|; this is an arbitrary choice to simplify the code.
192
 
193
\paragraph{function check\_parameters}
194
Sanity check on the generic settings for \verb|yahamm_enc| and \verb|yahamm_dec| entities.  It works in both synthesis and simulation.
195
 
196
\paragraph{function get\_parity\_check\_matrix}
197
\label{sec:paritycheck})
198
\begin{minted}{vhdl}
199
  function get_parity_check_matrix (
200
    MESSAGE_LENGTH : natural;
201
    EXTRA_PARITY : natural range 0 to 1  := 1;
202
    ONE_PARITY_BIT : boolean := false)
203
    return matrix_t;
204
  \end{minted}
205
 
206
  It returns the non-systematic form of parity check matrix, built following the general algorithm described in \cite{ham}.
207
 
208
  E.g. we want to get the parity-check matrix for the code Hamming(7,4) that encodes four bits of data into seven bits by adding three parity bits.  The matrix has dimension 3x7 if no extra parity bit is added.  The following snippet of test-bench:
209
 
210
  \begin{minted}{vhdl}
211
entity test is
212
end entity test;
213
 
214
architecture std of test is
215
 
216
  constant MESSAGE_LENGTH   : natural              := 4;
217
  constant EXTRA_PARITY_BIT : natural range 0 to 1 := 0;
218
  constant ONE_PARITY_BIT   : boolean              := false;
219
 
220
  constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT);
221
  constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT);
222
 
223
  constant H : matrix_t(0 to NPARITY_BITS + EXTRA_PARITY_BIT - 1,
224
 
225
    get_parity_check_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT);
226
 
227
begin
228
 
229
  process is
230
  begin
231
 
232
    pretty_print_matrix(H);
233
 
234
    stop(0);
235
  end process;
236
 
237
end architecture std;
238
\end{minted}
239
 
240
outputs the parity-check matrix $\textbf{H}$: in non-systematic form:
241
\begin{verbatim}
242
1 0 1 0 1 0 1
243
 
244
 
245
\end{verbatim}
246
 
247
If in the above code, \verb|EXTRA_PARITY_BIT| is 1, the output is:
248
\begin{verbatim}
249
1 0 1 0 1 0 1 0
250
 
251
 
252
1 1 1 1 1 1 1 1
253
\end{verbatim}
254
A right-most column and a bottom row has been added to the previous parity-check matrix.  The addition of '1' in the bottom row means that the forth parity bit encodes the parity for the entire code word.  No change on the existing parity bits ('0' in the last column for those parity bits).
255
 
256
If in the above code, \verb|ONE_PARITY_BIT| is true, the output is:
257
\begin{verbatim}
258
1 1 1 1 1
259
\end{verbatim}
260
That means that the only parity bit encodes the parity of the entire code word.
261
 
262
\paragraph{function get\_form\_swap\_matrix}
263
\label{sec:swap})
264
\begin{minted}{vhdl}
265
  function get_form_swap_matrix (
266
    MESSAGE_LENGTH : natural;
267
    EXTRA_PARITY : natural;
268
    ONE_PARITY_BIT : boolean := false)
269
    return matrix_t;
270
\end{minted}
271
Returns a $n \times n$ matrix $\textbf{S}$ to convert a $n$-row matrix or vector from non-systematic form $\mathbf{M}_{ns}$ to systematic form $\mathbf{M}_b{s}$ and vice-versa:
272
\begin{displaymath}
273
  \mathbf{M}_{s} = \mathbf{M}_{ns} \; \mathbf{S}
274
\end{displaymath}
275
 
276
The construction of the matrix can be understood by noticing that the systematic form of the parity-check matrix $\textbf{H}$ for the $Hamming(n,k)$ code is:
277
\begin{equation}
278
  \label{eq:h}
279
  \mathbf{H} := ( \mathbf{A} | \mathbf{I}_{n-k} )
280
\end{equation}
281
where $\mathbf{I_{n-k}}$ is the $(n-k) \times (n-k)$ identify matrix .  This can be obtained by swapping the columns $2^r - 1$-th of the identify matrix $\mathbf{I}_n$ corresponding to the position, in the non-systematic form, of the parity bits $r$ with the column $n-k+r$.  Note that since $\textbf{S} = \textbf{S}^T = \textbf{S}^{-1}$, the matrix can be used to transform from systematic to non-systematic form and vice-versa.
282
 
283
Example:
284
\begin{minted}{vhdl}
285
entity test is
286
end entity test;
287
 
288
architecture std of test is
289
 
290
  constant MESSAGE_LENGTH   : natural              := 4;
291
  constant EXTRA_PARITY_BIT : natural range 0 to 1 := 0;
292
  constant ONE_PARITY_BIT   : boolean              := false;
293
 
294
  constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT);
295
  constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT);
296
 
297
  constant H : matrix_t(0 to NPARITY_BITS + EXTRA_PARITY_BIT - 1,
298
 
299
    get_parity_check_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT);
300
 
301
  constant swap_matrix : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY_BIT - 1,
302
 
303
    get_form_swap_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT);
304
 
305
begin
306
 
307
  process is
308
  begin
309
 
310
    pretty_print_matrix(H);
311
    pretty_print_matrix(swap_matrix);
312
    pretty_print_matrix(xor_multiply(H, swap_matrix));
313
    pretty_print_matrix(xor_multiply(xor_multiply(H, swap_matrix), swap_matrix));
314
 
315
    stop(0);
316
  end process;
317
 
318
end architecture std;
319
\end{minted}
320
Outputs:
321
\begin{verbatim}
322
-- parity-check matrix, non-systematic form
323
1 0 1 0 1 0 1
324
 
325
 
326
 
327
-- form-swap matrix
328
 
329
 
330
 
331
 
332
1 0 0 0 0 0 0
333
 
334
 
335
 
336
-- parity-check matrix, systematic form
337
1 0 1 1 1 0 0
338
 
339
1 1 0 1 0 0 1
340
 
341
-- parity-check matrix, non-systematic form
342
1 0 1 0 1 0 1
343
 
344
 
345
\end{verbatim}
346
The first three matrices are: the parity-check matrix for Hamming(7,4) in non-systematic form, the form swapping matrix, the parity-check matrix in systematic form.  Note the identity matrix in the right-most columns in the systematic form of the parity-check matrix.  The forth matrix is the parity-check matrix obtained by multiplying its systematic form for the form-swap matrix.
347
 
348
If \verb|EXTRA_PARITY_BIT| is 1, the matrix has an additional column and row.  Last column is the same as in the identity matrix (no swapping).
349
 
350
\paragraph{function get\_code\_generator\_matrix}
351
\label{sec:codegen}
352
\begin{minted}{vhdl}
353
  function get_code_generator_matrix (
354
    MESSAGE_LENGTH : natural;
355
    EXTRA_PARITY : natural range 0 to 1 := 1;
356
    ONE_PARITY_BIT : boolean := false)
357
    return matrix_t;
358
\end{minted}
359
Returns the code generator matrix in systematic form.  The construction algorithm, as suggested in \cite{ham}, Sec. \emph{Construction of G and H}, is based on the comparison of G in systematic form:
360
\begin{equation}
361 11 ndesimone
  \label{eq:g}
362 9 ndesimone
  \mathbf{G} := ( \mathbf{I}_{k} | \mathbf{A}^T )
363
\end{equation}
364
with the expression of the parity-check matrix in systematic form in Eq.~\ref{eq:h}.  So the left hand side of $\mathbf{H}$ in systematic form can be transposed and combined with the $\mathbf{I}_{k}$ identity matrix.
365
 
366
E.g. we want to get the code generator matrix for the code Hamming(7,4) that encodes four bits of data into seven bits by adding three parity bits.  The matrix has dimension 7x4 if no extra parity bit is added.  The following snippet of test-bench:
367
 
368
  \begin{minted}{vhdl}
369
architecture std of test is
370
 
371
  constant MESSAGE_LENGTH   : natural              := 4;
372
  constant EXTRA_PARITY_BIT : natural range 0 to 1 := 0;
373
  constant ONE_PARITY_BIT   : boolean              := false;
374
 
375
  constant NPARITY_BITS : natural := calc_nparity_bits(MESSAGE_LENGTH, ONE_PARITY_BIT);
376
  constant BLOCK_LENGTH : natural := calc_block_length(MESSAGE_LENGTH, ONE_PARITY_BIT);
377
 
378
  constant G : matrix_t(0 to BLOCK_LENGTH + EXTRA_PARITY_BIT - 1,
379
 
380
    get_code_generator_matrix(MESSAGE_LENGTH, EXTRA_PARITY_BIT, ONE_PARITY_BIT);
381
 
382
begin
383
 
384
  process is
385
  begin
386
 
387
    pretty_print_matrix(G);
388
 
389
    stop(0);
390
  end process;
391
 
392
end architecture std;
393
\end{minted}
394
Outputs:
395
\begin{verbatim}
396
1 0 0 0
397
 
398
 
399
 
400
1 0 1 1
401
 
402
1 1 0 1
403
\end{verbatim}
404
 
405
If in the above code, \verb|EXTRA_PARITY_BIT| is 1, the output is:
406
\begin{verbatim}
407
1 0 0 0
408
 
409
 
410
 
411
1 0 1 1
412
 
413
1 1 0 1
414
1 1 1 0
415
\end{verbatim}
416
A bottom row has been added to the previous code generator matrix, based on the parity of the rows of the parity-check matrix.
417
 
418
If in the above code, \verb|ONE_PARITY_BIT| is true, the output is:
419
\begin{verbatim}
420
1 0 0 0
421
 
422
 
423
 
424
1 1 1 1
425
\end{verbatim}
426
Where the result is a row of '1' at the bottom of an identity matrix.  That means that the code word is the message plus its parity bit.
427
 
428
\printindex
429
 
430
\bibliographystyle{abbrv}
431
\bibliography{design}
432
 
433
\end{document}

powered by: WebSVN 2.1.0

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