um estudo sobre a construção, desempenho e …
TRANSCRIPT
UNIVERSIDADE ESTADUAL DE CAMPINAS
FACULDADE DE ENGENHARIA ELÉTRICA E DE COMPUTAÇÃO
ANTÔNIO UNIAS DE LUCENA
Um estudo sobre a construção, desempenho e implementação em VHDL de códigos
LDPC binários, irregulares e estruturados para aplicação em comunicações ópticas
CAMPINAS
2015
ANTÔNIO UNIAS DE LUCENA
Um estudo sobre a construção, desempenho e implementação em VHDL de códigos
LDPC binários, irregulares e estruturados para aplicação em comunicações ópticas
CAMPINAS
2015
Dissertação apresentada à Faculdade de Engenharia Elétrica e Computação da Universidade Estadual de Campinas como parte dos requisitos exigidos para a obtenção do título de mestre em Engenharia Elétrica. Área de concentração: Telecomunicações e Telemática.
Este exemplar corresponde à vesão final da dissertação defendida pelo aluno Antônio Unias de Lucena e orientada pelo Prof. Dr. Renato Baldini Filho. Assinatura do Orientador:
Agência(s) de fomento e nº(s) de processo(s): Não se aplica.
Ficha catalográficaUniversidade Estadual de Campinas
Biblioteca da Área de Engenharia e ArquiteturaLuciana Pietrosanto Milla - CRB 8/8129
Lucena, Antônio Unias de, 1981- L963e LucUm estudo sobre a construção, desempenho e implementação em VHDL
de códigos LDPC binários, irregulares e estruturados para aplicação emcomunicações ópticas / Antônio Unias de Lucena. – Campinas, SP : [s.n.],2015.
LucOrientador: Renato Baldini Filho. LucDissertação (mestrado) – Universidade Estadual de Campinas, Faculdade
de Engenharia Elétrica e de Computação.
Luc1. Comunicações ópticas. 2. Códigos corretores de erro (Teoria da
informação). 3. VHDL (Linguagem descritiva de hardware). 4. FPGA. I. Filho,Renato Baldini,1956-. II. Universidade Estadual de Campinas. Faculdade deEngenharia Elétrica e de Computação. III. Título.
Informações para Biblioteca Digital
Título em outro idioma: A study of construction, performance and VHDL implementation ofirregular, structured and binary LDPC codes for optical communications.Palavras-chave em inglês:Optical communicationsError-correcting codes (Information theory)VHDL (Hardware descriptive language)FPGAÁrea de concentração: Telecomunicações e TelemáticaTitulação: Mestre em Engenharia ElétricaBanca examinadora:Renato Baldini Filho [Orientador]Lucas Heitzmann GabrielliFabbryccio Akkazzha Chaves Machado CardosoData de defesa: 15-10-2015Programa de Pós-Graduação: Engenharia Elétrica
Powered by TCPDF (www.tcpdf.org)
COMISSÃO JULGADORA - DISSERTAÇÃO DE MESTRADO
Candidato: Antônio Unias de Lucena RA: 075031
Data da Defesa: 15 de outubro de 2015
Título da Tese: "Um Estudo Sobre a Construção, Desempenho e Implementação em
VHDL de Códigos LDPC Binários, Irregulares e Estruturados para Aplicação em
Comunicações Ópticas”.
Prof. Dr. Renato Baldini Filho (Presidente, FEEC/Unicamp)
Dr. Fabbryccio Akkazzha Chaves Machado Cardoso (CPqD)
Prof. Dr. Lucas Heitzmann Gabrielli (FEEC/UNICAMP)
A ata de defesa, com as respectivas assinaturas dos membros da Comissão
Julgadora, encontra-se no processo de vida acadêmica do aluno.
DEDICATÓRIA
Aos meus pais
AGRADECIMENTOS
Agradeço à minha família, ao meu orientador, Renato Baldini Filho, pela paciência e apoio
durante o mestrado, e aos meus amigos pelas ideias e auxílio nas correções desta dissertação.
RESUMO
O emprego de códigos LDPC em comunicações ópticas vem recebendo especial atenção nos últimos
anos devido à sua elevada capacidade de correção de erros, fato que possibilita enlaces mais longos e
com maior capacidade de transmissão. A presente dissertação apresenta um estudo de códigos LDPC
binários, irregulares e estruturados (IE-LDPC), bem como, uma comparação do desempenho de dois
algoritmos de decodificação comumente utilizados na decodificação de códigos LDPC: o algoritmo
soma-produto utilizando razões logarítmicas (log-SP) e o algoritmo soma-mínimo (SM), para um
conjunto de códigos IE-LDPC construídos. Além disso, a presente dissertação apresenta uma
implementação em VHDL de um codificador e de um decodificador para códigos IE-LDPC e os
resultados da síntese em FPGA desta implementação em VHDL. A comparação do desempenho dos
algoritmos de decodificação foi importante para determinar que o algoritmo SM, uma simplificação do
algoritmo log-SP, pode ser utilizado no lugar deste último sem perdas significativas de desempenho.
Por sua vez, a síntese em FPGA do codificador e do decodificador dos códigos IE-LDPC construídos
mostrou-se factível, mas a arquitetura do decodificador implementado do algoritmo SM ainda utiliza
grande quantidade de elementos lógicos.
Palavras-chave: comunicações ópticas, códigos corretores de erro, VHDL (linguagem descritiva de
hardware), FPGA.
ABSTRACT
The use of LDPC codes on optical communications has received special attention in recent years due to
its error correction capability, permitting longer and higher capacity optical links. This dissertation
presents a study of binary irregular structured LDPC codes (IS-LDPC), as well as a performance
comparison between two LDPC decoding algorithms: logarithm domain sum-product (log-SP) and
minimum-sum (MS) for a set of constructed IS-LDPC codes. Besides, this dissertation presents a
VHDL implementation of an encoder and a decoder for IS-LDPC codes and the FPGA synthesis results
of this VHDL implementation. The performance comparison has determined that the MS algorithm can
be a substitute to the log-SP algorithm with a significant reduction in logical elements in FPGA
implementation, without significant loss in decoding performance. The FPGA synthesis results have
shown that the encoder and the decoder IS-LDPC implementations are feasible, but the current MS
decoder still uses a considerable amount of logical elements.
Keywords: optical communications, error-correcting codes, VHDL, FPGA.
LISTA DE FIGURAS
Figura 1.1 – Comparativo entre o desempenho de vários códigos corretores de erros utilizados em
comunicações ópticas [2]. ............................................................................................................... 20
Figura 2.1 – Exemplo de um gráfico de Tanner para um código LDPC (8, 4). ..................................... 23
Figura 2.2 – Exemplo de uma matriz H com girth igual a 4 e seu respectivo gráfico de Tanner. ......... 24
Figura 2.3 – Matrizes circulantes obtidas a partir da rotação de I 8. ....................................................... 25
Figura 2.4 – Matriz de verificação de paridade de um código IE-LDPC (32, 16). ................................ 26
Figura 2.5 – Matriz de verificação de paridade de um código IE-LDPC (24, 16). ................................ 26
Figura 2.6 – Passo Horizontal da decodificação LDPC. ........................................................................ 30
Figura 2.7 – Passo Vertical da decodificação LDPC. ............................................................................ 30
Figura 2.8 – Fluxograma da decodificação LDPC. ................................................................................ 32
Figura 2.9 – Conjunto de trilhas e portas lógicas de FPGA antiga. ....................................................... 36
Figura 2.10 – FPGA e seus componentes internos [10]. ........................................................................ 37
Figura 2.11 – Célula básica da Virtex-5 [10]. ......................................................................................... 38
Figura 2.12 – Diagrama de um sistema de comunicações ópticas. ........................................................ 39
Figura 2.13 – Notação em ponto fixo empregada na presente dissertação. ........................................... 42
Figura 2.14 – Interface óptica-elétrica. .................................................................................................. 42
Figura 2.15 – Visão global do contexto em que o codificador e decodificador LDPC é empregado. ... 43
Figura 3.1 – Componentes da Virtex-5 interligados por trilhas internas [10]. ....................................... 45
Figura 3.2 – Atraso dentro da Virtex-5 devido ao caminho combinacional. .......................................... 46
Figura 3.3 – Codificador LDPC. ............................................................................................................ 47
Figura 3.4 – Blocos do decodificador LDPC. ........................................................................................ 48
Figura 3.5 – Matrizes auxiliares obtidas a partir da matriz H. .............................................................. 49
Figura 3.6 – Passo Horizontal do decodificador LDPC. ........................................................................ 51
Figura 3.7 – Passo Vertical do decodificador LDPC. ............................................................................ 52
Figura 3.8 – Calculador de �(��). ......................................................................................................... 54
Figura 3.9 – Calculador de síndrome do decodificador LDPC. ............................................................. 55
Figura 3.10 – Propagação dos dados ao longo dos vários blocos do decodificador.. ............................ 57
Figura 4.1 – Cenário da simulação dos códigos IE-LDPC. ................................................................... 59
Figura 4.2 – Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 50. ...................................................................................................... 60
Figura 4.3 - Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 100. .................................................................................................... 61
Figura 4.4 - Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 200. .................................................................................................... 62
Figura 4.5 - Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 500. .................................................................................................... 63
Figura 4.6 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma
matriz identidade de ordem igual a 50. ........................................................................................... 64
Figura 4.7 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma
matriz identidade de ordem igual a 100. ......................................................................................... 65
Figura 4.8 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma
matriz identidade de ordem igual a 200. ......................................................................................... 66
Figura 4.9 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma
matriz identidade de ordem igual a 500. ......................................................................................... 67
Figura 4.10 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma
matriz identidade de ordem igual a 1000. ....................................................................................... 68
LISTA DE TABELAS
Tabela 4.1- Parâmetros do codificador e do decodificador do código IE-LDPC (40, 20) na FGPA ..... 69
Tabela 4.2 - Parâmetros do codificador e do decodificador do código IE-LDPC (200, 100) na FGPA 69
LISTA DE SIGLAS E ABREVIATURAS
ASIC - Application Specific Integrated Circuit
AWGN - Additive White Gaussian Noise
BCH - Bose-Chaudhuri-Hocquenghem
BER - Bit Error Rate
BI-AWGN - Binary Input Additive White Gaussian Noise
CLB - Configurable Logic Blocks
DLL - Delay-locked Loop
FPGA - Field Programmable Gate Array
Gbps - Gigabit por segundo
IE-LDPC - Códigos LDPC irregulares e estruturados
IS-LDPC - Irregular and structured LDPCcodes
ITU-T - International Telecommunication Union
LDPC - Low-Density Parity-Check
log-SP - Soma-Produto utilizando razões logarítmicas
LUT - Look-up table
MS - Minimum-Sum
OFDM - Orthogonal Frequency-Division Multiplexing
PLL - Phase-Locked Loop
PSK - Phase Shift Keying
QAM - Quadrature Amplitude Modulation
QC-LDPC - Códigos LDPC quase-cíclicos
RAM - Random Access Memory
RS - Reed-Solomon
SP - Soma-Produto
SM - Soma-Mínimo
VHDL - VHSIC Hardware Description Language
WDM - Wavelength Division Multiplexing
WIMAX - Worldwide Interoperability for Microwave Access
Wi-Fi - Wireless Fidelity
LISTA DE SÍMBOLOS
�� - j-ésimo nó de verificação
c(i) - Bit i da palavra transmitida pelo codificador LDPC �̂(�) - Bit i da palavra decodificada pelo código LDPC
c - Palavra codificada pelo código LDPC ̂ - Palavra decodificada pelo código LDPC
Cl,j - Matriz circulante de ordem l e com j colunas rotacionadas à direita
C - Submatriz formada por todas as matrizes circulantes que formam a matriz H � - Conjunto dos nós de verificação conectados ao nó de variável �� �\� - Conjunto de nós de verificação conectados ao nó de variável �� excetuando o
nó de verificação �� �� - Energia por bit
Eb/N0 - Razão entre a energia por bit e a densidade espectral de potência do ruído
�(�, �) - Elemento da linha j e coluna i da matriz G
G - Matriz geradora do código LDPC ℎ(�, �) - Elemento da linha j e coluna i da matriz H
H - Matriz de verificação de paridade do código LDPC �� - Matriz H após a transformação utilizando-se o algoritmo de Gauss-Jordan �� - Matriz H transposta ���� - Matriz formada com os números das colunas e das linhas da matriz H em que ℎ(�, �) = 1 ���� - Matriz formada com os números das linhas e das colunas da matriz H em que ℎ(�, �) = 1 �� - Matriz identidade de ordem k �(� �) - Matriz identidade de ordem (n-k)
k - Número de bits da palavra a ser codificada !� - Fator de normalização para garantir ��(0) + ��(1) = 1 !�� - Fator de normalização para garantir &��(0) + &��(1) = 1 �(��) - Logaritmo da razão de verossimilhança da informação intrínseca recebida pelo
decodificador �(&��) - Logaritmo da razão de verossimilhança da mensagem envidada do nó de
variável �� para o nó de verificação �� �('��) - Logaritmo da razão de verossimilhança da mensagem enviada do nó de
verificação �� para o nó de variável �� �(��) - Logaritmo da razão de verossimilhança da probabilidade a posteriori para cada
nó de variável �� m - Palavra a ser codificada
n - Número de bits da palavra codificada () - Densidade espectral de potência de ruído *+ - Conjunto formado pelos números primos naturais
p - Fator de paralelismo da interface óptico-elétrico
P - Matriz de paridade do código LDPC ,� - Matriz de paridade transposta do código LDPC -� - Pr (�� = 1|1�), probabilidade a posteriori de que o bit c(i) seja 1, dado que o bit 1� foi recebido 2� - Matriz nula de ordem k
q - Quantidade de bits empregados para quantizar o valor do sinal óptico &�� - Mensagem do nó de variável �� para o nó de verificação �� �� - Probabilidade a posteriori para cada nó de variável �� '�� - Mensagem do nó de verificação �� para o nó de variável �� s(j) - Bit j da síndrome da palavra decodificada
s - Síndrome da palavra decodificada
t - instante de tempo t �� - i-ésimo nó de variável 3� - Conjunto dos nós de variável conectados ao nó de verificação �� 3�\� - Conjunto de nós de variável conectados ao nó de verificação �� excetuando o nó
de variável �� 45 - Quantidade de 1s por coluna da matriz H 46 - Quantidade de 1s por linha da matriz H
1� - Bit i da palavra recebida pelo decodificador
y - Palavra recebida pelo decodificador LDPC
7�� - sinal de �(&��) 8�� - magnitude de �9&��: ;< - variância do ruído do canal de transmissão
SUMÁRIO
1 INTRODUÇÃO .................................................................................................................. 19
2 FUNDAMENTAÇÃO TEÓRICA ...................................................................................... 22
2.1 Códigos LDPC ............................................................................................................ 22
2.1.1 Representação gráfica de códigos LDPC ................................................................ 22
2.1.2 Construção de códigos LDPC ................................................................................. 23
2.1.2.1 Códigos LDPC binários, irregulares e estruturados ......................................... 24
2.1.3 Codificação ............................................................................................................. 27
2.1.4 Decodificação .......................................................................................................... 28
2.1.4.1 Algoritmo soma-produto (SP) .......................................................................... 28
2.1.4.2 Algoritmo soma-produto utilizando razões logarítmicas (log-SP) ................... 32
2.1.4.3 Algoritmo soma-mínimo (SM) ......................................................................... 35
2.2 FPGA - Field-Programmable Gate Array.................................................................... 35
2.3 Códigos corretores de erro para comunicações ópticas .............................................. 38
2.3.1 Interface óptica-elétrica para utilizar códigos LDPC em comunicações ópticas .... 41
3 IMPLEMENTAÇÃO .......................................................................................................... 44
3.1 Influências dos componentes da Virtex-5 na implementação do codificador e do
decodificador IE-LDPC ...................................................................................................................... 44
3.1.1 Trilhas internas e frequência máxima de operação ................................................. 45
3.1.2 Memórias internas ................................................................................................... 46
3.2 Implementação do código IE-LDPC ........................................................................... 46
3.2.1 Codificador.............................................................................................................. 46
3.2.2 Decodificador .......................................................................................................... 47
3.2.2.1 Calculador do Passo Horizontal ........................................................................ 50
3.2.2.2 Calculador do Passo Vertical ............................................................................ 52
3.2.2.3 Decisão ............................................................................................................. 53
3.2.2.4 Propagação dos dados dentro do decodificador ................................................ 55
4 RESULTADOS ................................................................................................................... 58
4.1 Comparação do desempenho dos algoritmos de decodificação log-SP e SM para os
códigos IE-LDPC construídos ............................................................................................................ 58
4.1.1 Resultados da comparação do desempenho dos algoritmos log-SP e SM para os
códigos IE-LDPC (2000, 1000) ...................................................................................................... 59
4.1.1.1 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 50 ................................................................................................... 59
4.1.1.2 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 100 ................................................................................................. 60
4.1.1.3 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 200 ................................................................................................. 61
4.1.1.4 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 500 ................................................................................................. 62
4.1.2 Resultados da comparação do desempenho dos algoritmos log-SP e SM para os
códigos IE-LDPC (4000, 2000) ...................................................................................................... 63
4.1.2.1 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 50 ................................................................................................... 64
4.1.2.2 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 100 ................................................................................................. 64
4.1.2.3 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 200 ................................................................................................. 65
4.1.2.4 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 500 ................................................................................................. 66
4.1.2.5 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 1000 ............................................................................................... 67
4.2 Resultados da síntese em FPGA do codificador e do decodificador LDPC ............... 68
5 CONCLUSÃO E TRABALHOS FUTUROS ..................................................................... 71
5.1 Conclusão .................................................................................................................... 71
5.2 Trabalhos Futuros ........................................................................................................ 71
REFERÊNCIAS BIBLIOGRÁFICAS ........................................................................................ 73
ANEXOS ..................................................................................................................................... 76
ANEXO A – Código-fonte dos arquivos desenvolvidos para realizar a análise do desempenho
dos algoritmos log-SP e SM utilizando os códigos IE-LDPC construídos ............................................. 77
ANEXO B - Código-fonte dos arquivos desenvolvidos para a implementação em VHDL do
codificador e do decodificador dos códigos IE-LDPC construídos ........................................................ 91
ANEXO C – Código-fonte dos arquivos utilizados na validação da simulação dos codificadores
e decodificadores implementados em VHDL. ...................................................................................... 121
19
1 INTRODUÇÃO
O crescimento da Internet mediante o aumento no número de seus usuários, o surgimento de
novos serviços como comunicação em vídeo, televisão de alta definição, computação em nuvem e
vídeos de alta definição, bem como, o crescimento do número de usuários em redes de comunicações
móveis têm criado a necessidade de aumentar a capacidade de transmissão de dados das redes de
comunicações ópticas existentes.
Uma rede de comunicações ópticas é uma de rede de transporte de telecomunicações em que a
transmissão de dados é feita no domínio óptico, utilizando como meio de transmissão as fibras ópticas.
Os maiores desafios atuais enfrentados por estas redes são: aumento das taxas de transmissão, o
número de comprimentos de onda multiplexados numa fibra óptica e a extensão dos enlaces ópticos.
Associados a estes desafios estão o desenvolvimento de novos formatos de modulação, de técnicas de
detecção coerente e de métodos de controle dos efeitos da atenuação, dispersão e não linearidade nas
fibras.
Uma forma de aumentar a capacidade de transmissão de uma rede de comunicações ópticas é
utilizando novos formatos de modulação associados a códigos corretores de erro. Os códigos corretores
de erro são empregados com a função de permitir o aumento do alcance e da capacidade de transmissão
do enlace óptico sem as degradações dos dados transmitidos ocasionadas pelo canal de transmissão
óptica através da fibra. Entre estas degradações destacam-se fatores como dispersão cromática,
dispersão do modo de polarização, interferência entre símbolos e atenuação devido à fibra em que o
dado é transmitido.
Atualmente códigos corretores de erro utilizados em conjunto com a modulação do sinal óptico
possibilitam a transmissão de dados a taxas acima de 100 Gbps com detecção coerente.
Os primeiros códigos corretores de erros utilizados em comunicações ópticas foram os códigos
Reed-Solomon (RS) [1], com destaque para o código RS(255,239), especificado pela norma ITU-T
G.709. Objetivando melhor desempenho, novos códigos foram introduzidos, bem como o uso de
códigos concatenados [1], conforme determina a norma ITU-T G.975.1, sendo estes considerados a
segunda geração de códigos corretores de erros para comunicações ópticas. Os códigos LDPC (Low-
Density Parity-Check) [1], devido ao seu alto desempenho, são considerados a terceira geração de
códigos corretores de erros para comunicações ópticas.
A Figura 1.1 mostra o desempenho de vários códigos em função da redundância (redundancy)
20
adicionada aos dados transmitidos. Net coding gain (ganho de codificação) é a medida da diferença em
dB da relação sinal-ruído para um sistema óptico com código corretor de erro e do mesmo sistema sem
codificação para uma mesma taxa de erro. Redundância é a razão entre a quantidade de bits que é
adicionada à mensagem transmitida pela quantidade total de bits transmitidos.
Figura 1.1 – Comparativo entre o desempenho de vários códigos corretores de erros utilizados em comunicações
ópticas [2].
O ideal para um sistema óptico de comunicações é um código corretor de erro com alto ganho
de codificação e baixa redundância. O código RS(255, 239), por exemplo, possui 5,6 dB de ganho de
codificação e 6,67% de redundância. O código BCH(1020, 988) tem a mesma redundância de 6,67% e
ganho de codificação em torno de 8 dB. A vantagem deste último código sobre o anterior é que ele
proporciona um enlace de alcance maior e robustez a ruídos a um sistema de comunicações ópticas.
Os esforços atuais na área de códigos LDPC para comunicações concentram-se no
desenvolvimento de códigos mais eficazes [1], no desenvolvimento de arquiteturas que utilizem menor
número de elementos lógicos para seus codificadores e decodificadores [1] e no estudo do uso de
códigos LDPC conjuntamente com modulação [1].
Sabendo da importância de códigos LDPC para comunicações ópticas, esta dissertação tem por
objetivo a:
21
a) Construção de códigos LDPC binários, irregulares e estruturados (IE-LDPC);
b) Comparação do desempenho de dois algoritmos de decodificação de códigos LDPC: o algo-
ritmo soma-produto utilizando razões logarítmicas (log-SP) e o algoritmo soma-mínimo
(SM);
c) Implementação em VHDL (VHSIC Hardware Description Language) de um codificador e
de um decodificador baseado no algoritmo SM para códigos IE-LDPC;
d) Síntese em FPGA (Field Programmable Gate Array) do codificador e do decodificador IE-
LDPC descritos em VHDL.
A presente dissertação está organizada da seguinte forma. O capítulo 2 fornece a fundamentação
teórica da construção de códigos LDPC, uma introdução sobre FPGAs e comunicações ópticas. O
capítulo 3 descreve os detalhes da implementação em VHDL da arquitetura do codificador e do
decodificador dos códigos IE-LDPC construídos. O capítulo 4, por sua vez, apresenta os resultados da
comparação do desempenho dos algoritmos de decodificação log-SP e SM para os códigos IE-LDPC e,
também, os resultados da síntese em FPGA de codificadores e decodificadores IE-LDPC. Por fim, o
capítulo 5 é a conclusão e a descrição dos trabalhos futuros.
Existe ainda um apêndice com o código-fonte dos arquivos desenvolvidos para realizar a análise
do desempenho dos algoritmos log-SP e SM utilizando os códigos IE-LDPC construídos, um apêndice
com o código-fonte dos arquivos desenvolvidos para realizar a implementação em VHDL do
codificador e do decodificador IE-LDPC e outro apêndice com o código-fonte dos arquivos utilizados
na validação da simulação dos codificadores e decodificadores implementados em VHDL.
22
2 FUNDAMENTAÇÃO TEÓRICA
Este capítulo tem por objetivo fornecer uma fundamentação teórica sobre códigos LDPC (Low-
Density Parity-Check) e também noções básicas sobre FPGA (Field Programmable Gate Array).
2.1 Códigos LDPC
Os códigos LDPC foram desenvolvidos por Gallager na década de 1960 [3], mas permaneceram
esquecidos devido ao fato de sua complexa implementação estar além das capacidades computacionais
da época.
Eles foram redescobertos por MacKay na década de 1990 [3], e, atualmente, vêm recebendo
muita atenção, por ser o código corretor de erro que mais se aproxima do limite teórico de Shannon [4].
Tal fato levou os códigos LDPC a serem utilizados como o código padrão do WIMAX e da norma Wi-
Fi 802.11n e 802.11ac [5].
Os códigos LDPC são códigos lineares de bloco gerados a partir de uma matriz de verificação
de paridade H esparsa, ou seja, com baixa quantidade de 1s em relação ao número de 0s. Um código
LDPC (n, k) é caracterizado por uma matriz H de n colunas e n-k linhas.
De acordo com a construção desta matriz de verificação de paridade, os códigos LDPC podem
ser classificados em regulares, quando a matriz H possui quantidade constante de 1s para suas linhas e
colunas, ou irregulares, caso a matriz H não tenha esta característica. Códigos irregulares provaram ter
melhor desempenho que códigos regulares, apesar de sua maior complexidade de implementação e
decodificação [3].
2.1.1 Representação gráfica de códigos LDPC
Os códigos LDPC são comumente apresentados em sua forma gráfica, conhecida como grafos
de Tanner [3], que auxilia na visualização da implementação da decodificação destes códigos.
Grafos de Tanner são grafos bipartidos obtidos a partir da matriz de verificação de paridade H
23
de um código de bloco linear. Para um código LDPC de dimensões (n, k), seu grafo de Tanner possui n
nós de variável correspondentes às colunas da matriz H, e n-k nós de verificação correspondentes às
linhas da matriz H. Haverá conexão entre o nó de verificação �� e o nó de variável �� sempre que um
elemento ℎ(�, �) da matriz de H for igual a 1, sendo j correspondente à linha e i à coluna.
Na Figura 2.1 é apresentada uma matriz de verificação de paridade para um código de bloco (8,
4) e seu grafo de Tanner correspondente.
Figura 2.1 – Exemplo de um gráfico de Tanner para um código LDPC (8, 4).
2.1.2 Construção de códigos LDPC
Quanto à sua construção, os códigos LDPC podem ser classificados em regulares ou irregulares
e em estruturados ou aleatórios. Um código é dito regular quando todas as linhas de sua matriz H
possuem a mesma quantidade 46 de uns e todas as colunas possuem a mesma quantidade 45 de uns; o
código é dito irregular quando isto não é observado. Um código é dito estruturado quando as conexões
entre os nós do grafo de Tanner dadas pelos elementos da matriz H seguem determinado padrão
geométrico ou algébrico; o código é aleatório quando esta lei definindo conexões entre os nós não
existe.
Um dos principais conceitos que deve ser levado em conta na construção da matriz H de um
código LDPC é o girth desta matriz. Ele é definido como o menor número de transições necessárias
para se sair de um nó e retornar a ele. Matrizes de verificação de paridade com girth pequeno devem
ser evitadas, pois códigos LDPC cuja matriz H possui esta característica não possuem bom
desempenho [3]. A Figura 2.2 apresenta um exemplo de um código com girth igual a 4.
24
Figura 2.2 – Exemplo de uma matriz H com girth igual a 4 e seu respectivo gráfico de Tanner.
Códigos cuja matriz H é construída de forma aleatória alcançam melhor desempenho do que
códigos estruturados, porém são mais difíceis de serem implementados e sua decodificação é mais
complexa [3]. Assim, devido à facilidade de implementação dos códigos estruturados, a presente
dissertação faz uso destes. Na seção 2.1.2.1, uma classe especial de códigos LDPC binários, irregulares
e estruturados é discutida.
2.1.2.1 Códigos LDPC binários, irregulares e estruturados
Existem vários métodos de gerar a matriz H de um código LDPC. Na presente dissertação, a
matriz de verificação de paridade foi gerada a partir do agrupamento de submatrizes obtidas através do
deslocamento cíclico à direita das colunas de uma matriz identidade [6]. As vantagens dos códigos
assim gerados são a possibilidade de construir códigos com taxas múltiplas apenas modificando a
quantidade de submatrizes agrupadas e a facilidade de criação da matriz H.
A Figura 2.3 mostra como as submatrizes circulantes são geradas através do deslocamento
cíclico de uma matriz identidade de ordem 8, �=. O índice l da submatriz indica a ordem da matriz
identidade da qual ela foi gerada e o índice j, por sua vez, indica quantas colunas foram deslocadas
ciclicamente à direita a fim de se obter a submatriz circulante Cl,j . Para valores de j maiores que l, a
matriz identidade é rotacionada de j mod l.
25
Figura 2.3 – Matrizes circulantes obtidas a partir da rotação de I8.
Os códigos IE-LDPC construídos tiveram sua matriz H construída da seguinte forma. Seja *+ o
conjunto formado pelos números primos naturais. Os valores do conjunto *+ foram utilizados para
definir as matrizes circulantes obtidas através da rotação da matriz identidade, que serve de elemento-
base da matriz H do código IE-LDPC. Valores primos foram utilizados para gerar as matrizes
circulantes, pois, desta forma, é mais provável que a matriz de verificação de paridade gerada não tenha
ciclos ou girths pequenos [7].
A Figura 2.4 mostra o exemplo de como uma matriz H de um código IE-LDPC (32, 16) é
construída por meio do agrupamento de submatrizes circulantes obtidas através da rotação de uma
matriz identidade de ordem l = 8. Note que as submatrizes circulantes foram geradas utilizando-se os
quatro primeiros elementos do conjunto *+. Note também que a matriz H construída do código IE-
LDPC é irregular e também é formada por uma matriz identidade de ordem igual a 16, �>?. A matriz H
do código IE-LDPC é construída tendo uma matriz identidade com submatriz para simplificar a
codificação do código gerado a partir dela.
26
Figura 2.4 – Matriz de verificação de paridade de um código IE-LDPC (32, 16).
A Figura 2.5 mostra como a matriz H de um código IE-LDPC (24, 16) também foi construída a
partir de uma matriz identidade de ordem l = 8.
Figura 2.5 – Matriz de verificação de paridade de um código IE-LDPC (24, 16).
27
As matrizes de verificação de paridade dos códigos IE-LDPC (32, 16) e IE-LDPC (24, 16)
poderiam ter sido construídas tendo como elemento-base uma matriz identidade de ordem diferente,
l = 6, por exemplo. Assim, por causa dessa possibilidade de várias formas de construção da matriz de
verificação de paridade de um código IE-LDPC, só é possível determinar qual matriz H vai gerar um
código com melhor desempenho através de simulações.
2.1.3 Codificação
A codificação de códigos LDPC é realizada através de multiplicação de matrizes. A codificação
é realizada obtendo-se a matriz geradora, G, de um código LDPC a partir da matriz de verificação de
paridade deste código. A palavra codificada, c, é então derivada a partir da palavra m conforme descrito
na equação (2.1).
= @A (2.1)
Tradicionalmente, a matriz geradora de um código LDPC é obtida a partir da matriz de
verificação H. Utilizando-se o método de eliminação de Gauss-Jordan, uma nova matriz, ��, é derivada
da matriz H de tal forma que ela se apresente sob o formato sistemático descrito na equação (2.2), onde ,� é a transposta da submatriz de paridade do código LDPC e �(� �) é a matriz identidade de ordem (n-
k).
�� = [�(� �) ,�] (2.2)
A partir da matriz P, a matriz geradora G é obtida através da equação
A = [, ��]. (2.3)
A matriz de verificação de paridade H do código LDPC é esparsa, mas a matriz geradora G do
código LDPC geralmente não tem esta propriedade e, além disso, mesmo a matriz H tendo todas as
suas linhas linearmente independentes, isso pode não ocorrer com a matriz G. A consequência disso é
que a implementação do codificador do código LDPC utilizando a matriz G obtida a partir do método
de eliminação de Gauss-Jordan exige a realização de um número elevado de operações e pode levar a
um código de baixo desempenho quando as linhas desta matriz não são linearmente independentes.
Para evitar o processo de se obter a matriz G a partir da matriz H utilizando-se o método de
eliminação de Gauss-Jordan, alguns códigos LDPC modernos têm sido construídos conforme descrito
na seção 2.1.2.1 [6], onde a matriz de verificação de paridade H é construída de forma a já ser
28
constituída por uma matriz identidade de ordem (n-k) e pela submatriz C, como descrito na equação
(2.4).
� = [�(� �) E] (2.4)
A submatriz C é formada por submatrizes circulantes e é igual à transposta da matriz paridade P,
sendo, desta forma, a matriz G obtida com facilidade.
2.1.4 Decodificação
Quando Gallager introduziu os códigos LDPC, ele também apresentou um algoritmo para a
decodificação destes códigos denominado algoritmo soma-produto. Diferentemente dos códigos BCH e
Reed-Solomon que possuem soluções algébricas para decodificação, os códigos LDPC são
decodificados a partir da troca de mensagens entres os nós de variável e de verificação do grafo de
Tanner deste código LDPC. Os nós de verificação estimam a probabilidade de que uma dada equação
de verificação de paridade é satisfeita dadas as estimativas recebidas dos nós de variáveis. Os nós de
variáveis, por sua vez, estimam a probabilidade de que um dado bit seja 0 ou 1 na palavra decodificada
através das probabilidades recebidas dos nós de verificação.
O algoritmo de decodificação é dividido em cinco etapas: inicialização, passo horizontal, passo
vertical, determinação da palavra LDPC decodificada e cálculo da síndrome da palavra decodificada.
Geralmente este algoritmo é apresentado no domínio logarítmico para evitar erros de arredondamento
nos cálculos das probabilidades, já que as multiplicações são transformadas em somas. A seção 2.1.4.1
apresenta e detalha o funcionamento e etapas do algoritmo soma-produto (SP).
2.1.4.1 Algoritmo soma-produto (SP)
Antes de descrever este algoritmo, as seguintes notações serão introduzidas. 3� = conjunto dos nós de variável conectados ao nó de verificação ��. 3�\� = conjunto de nós de variável conectados ao nó de verificação �� excetuando o nó de
variável ��. � = conjunto de nós de verificação conectados ao nó de variável ��.
29
�\� = conjunto de nós de verificação conectados ao nó de variável �� excetuando o nó de
verificação ��. -� = Pr (�� = 1|1�) , probabilidade de que o i-ésimo bit recebido seja 1, dado que 1� foi
recebido. &�� = mensagem de nó de variável �� para o nó de verificação ��. '�� = mensagem do nó de verificação �� para o nó de variável ��. �� = Pr (F�|1) = Probabilidade a posteriori para cada nó de variável ��.
As etapas do algoritmo soma-produto são descritas logo a seguir.
a) Inicialização
Os valores iniciais de probabilidade são obtidos a partir da palavra y recebida pelo
decodificador e da característica do canal, conforme as equações (2.5) e (2.6), onde 1� é o valor do bit
da palavra recebida e ;< é o variância do ruído do canal em que o dado foi transmitido.
&��(0) = 11 + G( <HI JK⁄ ) (2.5)
&��(1) = 11 + G(<HI JK⁄ ) (2.6)
b) Passo Horizontal: Atualização dos nós de verificação
No passo horizontal ocorre a atualização do valor de '��, que é a mensagem enviada do nó de
verificação �� para o nó de variável ��. A Figura 2.6 mostra como ocorre a troca de mensagens entre os
nós de variável e de verificação para o grafo de Tanner de uma matriz de verificação de paridade H. O
nó de verificação �� vai enviar uma mensagem ao nó de variável �� , baseando-se nas mensagens
recebidas de todos os nós de variável conectados a ele, excetuando-se ��.
30
Figura 2.6 – Passo Horizontal da decodificação LDPC.
Os valores de ('��) são atualizados de acordo com as equações (2.7) e (2.8).
'��(0) = 12 + 12 N (1 − &�P�(1))�P∈RS\I
(2.7)
'��(1) = 1 − '��(0) (2.8)
c) Passo vertical: Atualização dos nós de variável
No passo vertical ocorre a atualização do valor de &��, que é a mensagem enviada do nó de
variável �� para o nó de verificação �� . A Figura 2.7 ilustra a troca de mensagens entre os nós de
verificação e variável para o grafo de Tanner de uma matriz de verificação de paridade H. O nó de
variável �� envia ao nó de verificação �� uma mensagem obtida através das mensagens recebidas de
todos os nós de verificação conectados a ele, excetuando-se o nó �� .
Figura 2.7 – Passo Vertical da decodificação LDPC.
Os valores de &�� são atualizados utilizando-se as equações (2.9), (2.10) e (2.11).
31
&��(0) = !��(1 − -�) N ('�P�(0))�P∈TI\S (2.9)
&��(1) = !��-� N ('�P�(1))�P∈TI\S (2.10)
A constante !�� é o fator de normalização para garantir que a equação (2.11) seja observada.
&��(0) + &��(1) = 1 (2.11)
d) Obtenção da palavra decodificada
Nesta etapa acontece a atualização das probabilidades a posteriori ��(0) e ��(1), para cada nó
de variável �� . É a partir destas probabilidades que uma palavra LDPC decodificada é obtida. As
equações logo abaixo são empregadas nesta etapa. A constante !� é o fator de normalização para
garantir que a equação (2.14) seja satisfeita
��(0) = !�(1 − -�) N '��(0)�∈TI (2.12)
��(1) = !�-� N '��(1)�∈TI (2.13)
��(0) + ��(1) = 1 (2.14)
A palavra LDPC decodificada é obtida através da equação (2.15), onde �̂(�) é o bit i da palavra
decodificada.
�̂(�) = U1, VG ��(1) > 0.50, �YVZ�Z[\'á'�Z (2.15)
e) Verificação
Nesta etapa, o decodificador verifica se síndrome da palavra decodificada é nula. Isto é
realizado através da equação (2.16), onde ̂ é a palavra decodificada, �� é a transposta da matriz de
verificação de paridade e s é o vetor de dimensão (1 x k) que corresponde à síndrome da palavra
decodificada.
^ = ̂�� (2.16)
Caso a síndrome não seja nula, o processo de decodificação continua até que determinado
número de iterações seja atingido. Várias iterações são utilizadas a fim de possibilitar uma
decodificação com menor probabilidade de erro.
32
As etapas da decodificação LDPC utilizando-se os algoritmos soma-produto estão descritas na
Figura 2.8.
Figura 2.8 – Fluxograma da decodificação LDPC.
O algoritmo soma-produto é bastante preciso, mas tem como ponto negativo o fato de sua
implementação possuir muitas multiplicações, tornando onerosa sua implementação em hardware e
causando rápida saturação dos valores das probabilidades calculadas.
Por causa disso, versões modificadas deste algoritmo, o algoritmo soma-produto utilizando
razões logarítmicas (log-SP) e o algoritmo soma-mínimo (SM), são comumente utilizadas. As seções
2.1.4.2 e 2.1.4.3 descrevem estes algoritmos, respectivamente.
2.1.4.2 Algoritmo soma-produto utilizando razões logarítmicas (log-SP)
A vantagem do algoritmo log-SP sobre o algoritmo SP é que as multiplicações existentes neste
33
último algoritmo são transformadas em somas, cuja implementação é simples em hardware. Este
algoritmo trabalha com o logaritmo da razão de verossimilhança das razões das probabilidades
conforme as equações (2.17), (2.18), (2.19) e (2.20).
�(��) = ln(-'(�� = 0 1�⁄ )-'(�� = 1 1�⁄ )) (2.17)
�(&��) = ln(&��(0)&��(1)) (2.18)
�('��) = ln('��(0)'��(1)) (2.19)
�(��) = ln(��(0)��(1)) (2.20)
A variável �(��) é o logaritmo da razão de verossimilhança da informação intrínseca recebida
pelo decodificador, �(&��) é o logaritmo da razão de verossimilhança da mensagem enviada do nó de
variável �� para o nó de verificação ��, �('��) é o logaritmo da razão de verossimilhança da mensagem
enviada do nó de verificação �� para o nó de variável �� e �(��) é o logaritmo da razão de
verossimilhança da probabilidade a posteriori para cada nó de variável ��. As etapas deste algoritmo são as mesmas do algoritmo soma-produto descritas na Figura 3.8.
a) Inicialização
A inicialização dos valores de �(��) e �(&��) para os canais do tipo AWGN (Additive White
Gaussian Noise) é dada pela equação (2.21), onde 1� é o valor do bit do sinal recebido e ;< é o
variância do ruído do canal em que o dado foi transmitido.
�(&��) = �(��) = 21� ;<⁄ (2.21)
b) Passo Horizontal: Atualização dos nós de verificação
Nesta etapa ocorre a atualização de �('��), mensagem enviada dos nós de verificação para os
nós de variável. O valor de �9'��: é calculado a partir da equação (2.22), sendo a(F), 7�� e 8�� dados,
respectivamente, pelas equações (2.23), (2.24) e (2.25), onde 7�� é o sinal do valor de �(&��) e 8��, a
magnitude de �(&��).
�9'��: = N 7�b��b∈RS\I. a( c a(8�P�)�P∈RS\I
) (2.22)
34
a(F) = −ln(tanh(F 2⁄ )) = ln(Gg + 1Gg − 1) (2.23)
7�� = V��[[�(&��)] (2.24)
8�� =∣ �(&��) ∣ (2.25)
c) Passo vertical: Atualização dos nós de variável
Nesta etapa acontece a atualização de �(&��), mensagem enviada dos nós de variável para os nós
de verificação. O cálculo de �(&��) é feito de acordo com a equação (2.26).
�(&��) = �(��) + c �('�P�)�P∈TI\S (2.26)
d) Obtenção da palavra decodificada
A atualização de �(��), logaritmo da razão de verossimilhança da probabilidade a posteriori
para cada nó de variável ��, é dada pela seguinte equação (2.27) e é através dos valores de �(��) que a
decisão da palavra decodificada é realizada. O bit da palavra decodificada, �̂(�), é obtido através da
equação (2.28).
�(��) = �(��) + c �('��)�∈TI (2.27)
�̂(�) = { 1, VG�(��) < 00, �YVZ�Z[\'á'�Z (2.28)
e) Verificação
Esta etapa é semelhante à verificação realizada no algoritmo no SP, sendo calculada a síndrome
da palavra decodificada.
Outra vantagem do algoritmo log-SP sobre o algoritmo SP é que este algoritmo não necessita
calcular as constantes !�� e !�, que são utilizadas no algoritmo soma-produto.
35
2.1.4.3 Algoritmo soma-mínimo (SM)
O algoritmo soma-mínimo não é nada mais do que uma simplificação do algoritmo log-SP. Esta
simplificação ocorre na atualização do valor de �('��), dado pela equação (2.22).
A simplificação acontece devido ao fato de a função a(F) ser mais influenciada pelo menor
valor de 8��, como mostrado em (2.29). Por causa disso, a atualização do valor de �('��) passa a ser
obtida através da equação (2.30).
a(c a(8�P�)�P ) ≈ (a(a(min�P 8�P�))) = min�P∈RS\I 8�P� (2.29)
�('��) = ( N 7�P��P∈RS\I) ⋅ min�P∈RS\I 8�P� (2.30)
Outra vantagem do algoritmo soma-mínimo é que, para um canal BI-AWGN (Binary Input
Additive White Gaussian Noise), não é necessário conhecer as características do canal em que o dado
foi transmitido para obter o valor inicial de �(&��) [8]. Desta forma, a inicialização de �9&��: é mais
simples e é dada pela equação (2.31).
�9&��: = �(��) = 1� (2.31)
As demais etapas do algoritmo soma mínimo são idênticas às etapas do algoritmo log-SP e
também seguem o fluxograma descrito na Figura 2.8.
O algoritmo soma-mínimo perde em precisão para os demais algoritmos, mas sua
implementação em FPGA é bem mais simples e utiliza menor quantidade de elementos lógicos. Por isto,
ele foi escolhido para ser o algoritmo de decodificação LDPC implementado em hardware na presente
dissertação.
2.2 FPGA - Field-Programmable Gate Array
As primeiras FPGAs foram criadas na década de 80 [9], e, desde então, seu uso e aplicação em
projetos eletrônicos só tem aumentado. A grande vantagem do uso de FPGAs está no fato de ser
possível mudar parâmetros de um circuito eletrônico sem ser necessário o desenvolvimento de uma
36
nova placa eletrônica. Tal maleabilidade permite um tempo mais curto de projeto para um produto,
gerando mais ganhos às empresas que utilizam a tecnologia.
As primeiras FPGAs possuíam apenas portas lógicas simples (AND, OR, XOR, etc)
interconectadas por trilhas de ligação. A Figura 2.9 mostra como uma função lógica de um circuito
digital era obtida a partir de diferentes conexões entre as trilhas de uma FPGA existente na década de
80.
Figura 2.9 – Conjunto de trilhas e portas lógicas de FPGA antiga.
As FPGAs atuais são constituídas por células lógicas que congregam flip-flops e LUTs (look-up
tables), bem como por blocos de memória, blocos de processamento digital de sinais e PLLs (phase-
looked loops). A Figura 2.10 detalha uma FPGA e alguns de seus componentes: trilhas de conexão
(PROGRAMMABLE INTERCONNECT), blocos lógicos (LOGIC BLOCKS) e interfaces de entrada e
saída (I/O BLOCKS).
37
Figura 2.10 – FPGA e seus componentes internos [10].
Quando as FPGAs começaram a ser utilizadas, as conexões entre suas trilhas eram feitas
manualmente. Atualmente, as conexões entre blocos lógicos são feitas via software. Um componente é
descrito utilizando-se alguma linguagem de descrição de hardware tal como VHDL ou Verilog e, em
seguida, o software que realiza a síntese da lógica na FPGA utiliza os blocos lógicos nela existentes e
realiza as interconexões necessárias entre estes blocos lógicos, a fim de implementar o componente
eletrônico criado.
No projeto de circuitos utilizando FPGA, três fatores são relevantes: potência elétrica dissipada,
área ocupada (número de elementos lógicos utilizados) e frequência máxima de operação. Como a ideia
inicial desta dissertação não é desenvolver um produto, mas sim, implementar e comprovar conceitos,
tanto a potência dissipada como a área ocupada na FPGA não foram levados em consideração. O fator
que mais influenciou a implementação do codificador e do decodificador dos códigos IE-LDPC
construídos foi a frequência máxima de operação do projeto, já que isto permite que o circuito opere
com menos paralelismo nas operações matemáticas que vai realizar.
Para finalizar, vale ressaltar que o uso de FPGAs também possui algumas desvantagens.
Quando em projetos utilizando muitos elementos lógicos, a interconexão entre estes elementos dentro
da FPGA pode estar distante, causando atrasos que influenciam negativamente na frequência máxima
de operação. Para casos como estes, e estando o projeto já consolidado, costuma-se construir chips
específicos, denominados ASIC (Application Specific Integrated Circuit), de tal forma a criar o projeto
38
com blocos lógicos próximos entre si, e não com a distância determinada pela FPGA.
A presente dissertação utilizou a FPGA Virtex-5 XC5VLX50T da Xilinx para a implementação
de códigos IE-LDPC em hardware. Esta FPGA foi escolhida por possuir interfaces de entrada e saída
de alta velocidade, ideais para trabalhar com comunicações digitais em altas taxas. Já o software que
realiza a síntese na FPGA do codificador e do decodificador descritos em VHDL é o ISE WebPACK da
Xilinx.
A Figura 2.11 detalha uma célula básica da FPGA utilizada. Esta célula básica possui duas LUTs,
dois flip-flops D e interfaces de conexão com outras células básicas.
Figura 2.11 – Célula básica da Virtex-5 [10].
2.3 Códigos corretores de erro para comunicações ópticas
Códigos corretores de erro, como o LDPC, são utilizados com o propósito de atenuar os efeitos
das interferências presente em um canal sobre os dados transmitidos. No caso de comunicações ópticas,
39
as causas das interferências no canal podem ser: atenuação do sinal óptico, dispersão cromática,
dispersão do modo de polarização e distorção do pulso óptico devido a não-linearidades da fibra óptica,
que é o canal de comunicação [1].
O uso de códigos corretores de erro em comunicações ópticas associados a um processo de
modulação permite o aumento da capacidade de transmissão pelo canal óptico e o aumento do alcance
do sinal óptico transmitido, reduzindo-se, dessa forma, o número de repetidores empregados, gerando
economia na implementação de laços ópticos. Além disso, esta composição de códigos corretores de
erro com modulação possibilita que sistemas de comunicações ópticas operem em taxas acima de 40
Gbps [1], uma vez que a influência da interferência entre símbolos no detector óptico é minimizada.
A Figura 2.12 descreve um sistema de comunicações ópticas em que códigos corretores de erro
associado a um processo de modulação são utilizados.
Figura 2.12 – Diagrama de um sistema de comunicações ópticas.
40
A fonte é o dispositivo que gera a informação a ser transmitida pelo equipamento de
telecomunicações, ou seja, a fonte gera sequências de informação binárias em sua saída.
A codificação de fonte, por sua vez, é um processo de compressão da informação gerada pela
fonte que retira as redundâncias e/ou as irrelevâncias desta informação de tal forma a reduzir ao
máximo possível a quantidade de bits transmitidos, sem comprometer a integridade da informação.
A codificação de canal, por outro lado, é o processo que introduz bits redundantes à informação
a ser transmitida, de tal forma a permitir que o receptor utilize estes bits extras para detectar e corrigir
erros produzidos durante a transmissão através do canal.
Em comunicações ópticas a codificação de canal é realizada empregando-se códigos corretores
de erro, tais como, o RS(255, 239) especificado pela norma ITU-T G.709 e os códigos BCH(3860,
3824) e BCH(2040, 1930) especificados pela norma ITU-T G.975.1. O escopo desta dissertação se
situa na codificação de canal.
A modulação é um processo de mapeamento da informação binária em um sinal adequado a ser
transmitido pelo canal de comunicação. Isso pode implicar na taxa de transmissão do sistema de
comunicação. Em comunicações ópticas podem ser utilizadas modulações na intensidade do sinal
transmitido ou na fase e frequência do sinal óptico. Atualmente as modulações coerentes mais
utilizadas são QAM (Quadrature Amplitude Modulation) e PSK (Phase Shift Keying) [1].
Além de modulação, os sinais ópticos podem ser multiplexados, ou seja, pode-se transmitir
vários sinais distintos dentro de uma fibra. Os sistemas multicanais utilizam multiplexagem por divisão
no comprimento de onda, WDM (Wavelength Division Multiplexing) e também OFDM (Orthogonal
Frequency-Division Multiplexing) [1].
A demodulação é o processo de caracterizar estatisticamente o sinal recebido e decidir, dentro
de um conjunto finito, qual a sequência de formas de ondas transmitidas. Após tomar esta decisão, o
receptor óptico usa um mapeamento inverso em relação ao usado pelo modulador para determinar a
sequência de símbolos discretos na saída do receptor óptico.
O receptor óptico sem modulação consiste de apenas um fotodiodo, que é responsável por
converter o sinal do domínio óptico para o domínio elétrico, e por circuitos eletrônicos apropriados
para amplificar o sinal antes de entregar a informação para o destino. Em sistemas ópticos
convencionais usa-se detecção direta, já que a informação é transmitida na intensidade do sinal. Em
sistemas mais modernos, para aumentar a eficiência espectral, ocorre detecção coerente.
A decodificação de canal é o processo de utilizar a redundância adicionada pela codificação de
41
canal para controlar os efeitos dos ruídos e distorções causados pela transmissão do dado através do
canal. Já a decodificação de fonte, por sua vez, é o processo de reinserir a redundância removida pelo
codificador de fonte.
2.3.1 Interface óptica-elétrica para utilizar códigos LDPC em comunicações ópticas
Para utilizar os códigos LDPC em comunicações ópticas, é necessária uma interface que
converta o sinal do domínio óptico para o domínio elétrico e vice-versa. Além disso, para operar com
códigos LDPC, esta interface necessita trabalhar com valores reais, representados por um conjunto de
bits, e não valores binários 0 ou 1.
Quando códigos LDPC são empregados em comunicações ópticas, esta interface amostra e
quantiza o sinal óptico, convertendo-o em um sinal elétrico constituído por p conjuntos de q bits, onde
p é o fator de paralelismo empregado e q é a quantidade de bits empregados para quantizar o valor do
sinal óptico.
A quantização é realizada baseando-se na intensidade luminosa do sinal óptico, quando a
detecção do sinal óptico é por intensidade, ou na fase e amplitude do sinal óptico, quando a detecção
coerente é empregada.
Como a decodificação do código LDPC utiliza decisão suave (soft-decision), na presente
dissertação, o valor do sinal óptico é quantizado por um conjunto de 12 bits que correspondem a um
valor real no intervalo [-1,1]. Nestes 12 bits, o bit mais significativo representa o sinal do número, os 7
bits seguintes, sua parte inteira, e os 4 bits restantes, sua parte fracionária.
A implementação dos códigos LDPC utilizou a representação em ponto fixo, pois a
representação em ponto flutuante é muito complexa de ser implementada em FPGA. O tamanho da
parte inteira, 7 bits, foi escolhido de tal forma a impedir a saturação das somas que ocorrem no
algoritmo de decodificação soma-mínimo (SM). Já os 4 bits da parte fracionária foram escolhidos de
forma a garantir uma precisão mínima de 0.075 na quantização dos valores do sinal óptico. A Figura
2.13 detalha a notação em ponto fixo empregada na presente dissertação.
42
Figura 2.13 – Notação em ponto fixo empregada na presente dissertação.
A Figura 2.14 ilustra uma interface óptica-elétrica trabalhando com sinais ópticos de diferentes
taxas (2,5 Gbps, 10 Gbps ou 40 Gbps) e sinais elétricos formados por 16, 64 ou 256 conjuntos de 12
bits, respectivamente.
Figura 2.14 – Interface óptica-elétrica.
43
Outras taxas de paralelismo na conversão óptica-elétrica poderiam ser empregadas. O sinal
óptico de 2,5 Gbps, por exemplo, poderia ser transformado em um sinal elétrico formado por 8
conjuntos de 12 bits. Entretanto, com esta taxa de paralelismo, o codificador e o decodificador LDPC
teriam que operar com o dobro da frequência necessária para quando se trabalha com a taxa de 16
conjuntos de 12 bits.
A escolha de uma menor taxa de paralelismo implica na necessidade de se operar em
frequências maiores. Por outro lado, quanto maior for a taxa de paralelismo, maior será a quantidade de
LUTs utilizadas no projeto, influenciando negativamente na quantidade de elementos lógicos utilizados.
Assim, é necessário encontrar o ponto ótimo entre taxa de paralelismo e quantidade de elementos
lógicos utilizados.
A Virtex-5, FPGA utilizada na presente dissertação, tem frequência máxima de operação da
ordem de grandeza de centenas de MHz e só é possível utilizá-la para processar sinais de ordem de
Gbps porque ocorre o processamento em paralelo de vários bits em um pulso de relógio. Por exemplo,
para se processar um sinal de taxa de 2,5 Gbps, uma das opções possíveis é processar 16 conjuntos de
12 bits a cada pulso de relógio, fazendo com que a FPGA trabalhe a uma frequência de 156,25 MHz.
A Figura 2.15 ilustra como ocorre o fluxo dos sinais ópticos e elétricos através das interfaces e
dentro da FPGA.
Figura 2.15 – Visão global do contexto em que o codificador e decodificador LDPC é empregado.
44
3 IMPLEMENTAÇÃO
Este capítulo descreve a implementação em VHDL do codificador e o decodificador de códigos
IE-LDPC. Antes desta descrição, são apresentadas as influências da FGPA utilizada, Virtex-5, no
desenvolvimento do codificador e do decodificador dos códigos IE-LDPC construídos.
3.1 Influências dos componentes da Virtex-5 na implementação do codificador e do
decodificador IE-LDPC
A implementação de um projeto em FPGA é determinada pelos seus componentes. Nas seções a
seguir são descritos os componentes internos da Virtex-5, FPGA utilizada na presente dissertação, que
mais influenciaram na implementação do codificador e do decodificador dos códigos IE-LDPC
construídos.
A Figura 3.1 detalha a Virtex-5 e seus principais componentes: DLL (Delay-locked Loop),
circuito similar ao PPL (Phase-locked Loop), com a diferença de o oscilador controlado por tensão é
substituído por uma linha de atraso; CLB (Configurable Logic Blocks), parte da FPGA que armazena as
células lógicas e flip-flops; BLOCK RAM (Random Access Memory), banco de memórias internas da
FPGA e I/O LOGIC, pinos de entrada e saída da FPGA.
45
Figura 3.1 – Componentes da Virtex-5 interligados por trilhas internas [10].
3.1.1 Trilhas internas e frequência máxima de operação
Os componentes da Virtex-5 são interconectados por trilhas internas, conforme indicado pela
Figura 3.2. Estas interconexões entre os elementos da FPGA faz com que qualquer circuito sintetizado
na Virtex-5 tenha frequência máxima de operação em torno de 400 MHz, que é a frequência máxima
em que seu fabricante, Xilinx, garante que o sinal de relógio que se propaga pelas trilhas internas que
ligam os flip-flops está estabilizado e os tempos de set e hold não são violados.
Porém, na prática, a frequência máxima de operação da Virtex-5 é um pouco menor. O fator
limitante é o atraso de propagação de um sinal pelo caminho combinacional entre flip-flops. Para evitar
problemas de amostragem, o período do relógio do flip-flop tem que ser maior que o atraso ocasionado
pelo caminho combinacional. Além da quantidade de portas lógicas, a distância entre elementos lógicos
influenciam negativamente na frequência máxima de operação. A Figura 3.2 exemplifica um caminho
combinacional entre flip-flops que causa impacto na frequência máxima de operação.
46
Figura 3.2 – Atraso dentro da Virtex-5 devido ao caminho combinacional.
3.1.2 Memórias internas
A Virtex-5 possui bancos de memórias, que são as block RAMs, usadas para aumentar a
velocidade da escrita e leitura de dados dentro da FPGA. Quando todas estas memórias estiverem
utilizadas ou quando não especificado pelo usuário, o programa sintetizador de lógica na Virtex-5 vai
sintetizar memórias utilizando blocos lógicos. Esta forma de síntese de memórias é conhecida como
distributed RAM e seu uso diminui a frequência máxima de operação da FPGA, pois o processo de
leitura e escrita em distributed RAMs é mais lento do que em block RAMs.
3.2 Implementação do código IE-LDPC
3.2.1 Codificador
O codificador implementa a equação (3.1), onde c é a palavra LDPC codificada, m é a palavra
47
de informação a ser codificada, G é a matriz geradora do código LDPC, P é a matriz de paridade do
código LDPC e �� é a matriz identidade de ordem k.
= @A
c = [o(1) o(2) … o(q)] [P | ��]
c = [�(1) �(2) … �([ − q)| o(1) o(2) … o(q)]
(3.1)
A implementação do codificador é simples, sendo, para códigos binários, várias portas XOR em
cascata. A Figura 3.8 mostra como o codificador foi implementado. Para o cálculo dos bits �(1) a �([ − q) da palavra codificada, o codificador usa todos os bits da sequência de informação m. Quando
o elemento g(j, 1) = 1 da matriz G, o bit m(j) entra no cálculo do bit c(j), caso contrário, não. A variável
j pertence ao conjunto [1, (n-k)] e k é o número de linhas da matriz G.
Figura 3.3 – Codificador LDPC.
3.2.2 Decodificador
O decodificador LDPC é a implementação em hardware do algoritmo soma-mínimo e é
constituído por três componentes: cálculo de �('��) , cálculo de �(&��) e decisão. Esta divisão é
relacionada às etapas do algoritmo de decodificação.
A etapa do cálculo do logaritmo da razão de verossimilhança da mensagem enviada do nó de
48
verificação �� para o nó de variável ��, �('��), ou passo horizontal, consiste na obtenção dos valores das
mensagens que os nós de verificação enviam aos nós de variável. Esta etapa recebe o nome de passo
horizontal, pois este cálculo é realizado percorrendo-se a linha da matriz H.
A etapa do cálculo do logaritmo da razão de verossimilhança da mensagem envidada do nó de
variável �� para o nó de verificação ��, �(&��), ou passo vertical, consiste na obtenção dos valores das
mensagens que os nós de variável enviam aos nós de verificação. Esta etapa recebe o nome de passo
vertical porque este cálculo é realizado percorrendo-se a coluna da matriz H.
A etapa Decisão consiste no cálculo na palavra de informação decodificada e no cálculo da
síndrome desta palavra.
Cada uma destas etapas é realizada em um pulso de relógio. Portanto, uma iteração de
decodificação de uma palavra LDPC leva três pulsos de relógio para ser realizada.
A Figura 3.4 mostra o decodificador LDPC dividido em seus blocos operacionais. O cálculo de �('��) ocorre no primeiro pulso de relógio, o cálculo de �(&��), no segundo pulso de relógio e o cálculo
da nova palavra decodificada, data_out, e de sua síndrome ocorre no terceiro e último pulso de relógio
da iteração da decodificação LDPC.
Figura 3.4 – Blocos do decodificador LDPC.
Cada valor de �(&��) e �('��) é armazenado em LUTs e representado por um conjunto de 12 bits,
conforme indicado na Figura 2.13. Não foi possível utilizar as block RAMs da FPGA, já que se estes
valores fossem armazenados nestas memórias, não seria possível efetuar a leitura e escrita de vários
endereços de memória em um mesmo pulso de relógio.
Um ponto negativo do armazenamento dos valores de �(&��) e �('��) em LUTs é que estes
valores são armazenados em células lógicas, aumentado consideravelmente a quantidade de elementos
lógicos da FPGA utilizados no projeto.
49
A implementação tradicional do decodificador LDPC verifica a cada instante se o valor de ℎ(�, �) é nulo ou não, tornando o caminho combinacional longo e lento. Por isso, optou-se por
armazenar em uma matriz, ����, os valores das colunas e das linhas para as quais ℎ(�, �) = 1, e, da
mesma forma, em outra matriz, ����, os valores das linhas e das colunas para as quais ℎ(�, �) = 1.
Trabalhando-se com a matriz H, seria necessário armazenar (k x n) valores. No entanto,
utilizando-se ���� e ����, é necessário armazenar duas matrizes de dimensões (46 x k) e (n x 45),
respectivamente. Sendo 46 o número de 1s por linha e 45 o número de 1s por coluna da matriz H.
A Figura 3.5 mostra como as matrizes ���� e ���� são obtidas a partir da matriz H. Para a
primeira linha da matriz H temos ℎ(�, �) = 1 para os seguintes valores de coluna: 2, 4, 5 e 8. Estes
valores são os elementos da primeira linha da matriz ����. Para a primeira coluna da matriz H temos ℎ(�, �) = 1 para os seguintes valores de linha: 2 e 4. Estes valores são os elementos da primeira linha da
matriz ����.
Figura 3.5 – Matrizes auxiliares obtidas a partir da matriz H.
Os itens 3.3.2.1, 3.3.2.2 e 3.3.2.3 a seguir detalham como cada componente do decodificador
LDPC foi implementado.
50
3.2.2.1 Calculador do Passo Horizontal
O passo horizontal é a etapa em que são calculados os valores de probabilidade da mensagem
que o nó de verificação �� envia para o nó de variável �� . A mensagem �('��) só existirá quando ℎ(�, �) = 1.
Esta é a etapa que mais utiliza elementos lógicos no decodificador LDPC. A grande vantagem
do algoritmo SM é que ele transforma o cálculo de �('��) na obtenção do valor mínimo do módulo de �(&��), 8�� , e na multiplicação em cascata do sinal de �(&��.), 7�� , para todos os valores de �(&��)
envolvidos no cálculo de �('��) para um valor específico de linha i e coluna j.
Como os valores de �(&��) estão em representação de complemento de 2, para se obter o
mínimo do módulo de números negativos, é necessário transformá-los em seus correspondentes valores
positivos, e, a partir daí, obter o valor de menor módulo. O circuito que obtém o sinal resultante são
várias portas lógicas XOR em sequência, lembrando que o sinal negativo tem valor lógico 1 e o
positivo, 0.
A Figura 3.6 mostra a implementação do passo horizontal. Para obter o valor de �('��), são
utilizados no cálculo os valores de �(&�P�) e 7��P, onde �P é o valor das colunas da linha j da matriz H
em que ℎ(�, �) = 1, excetuando-se a coluna i.
51
Figura 3.6 – Passo Horizontal do decodificador LDPC.
A variável �P pertence ao conjunto 3�\�, que é o conjunto formado pelas colunas da linha j em
que ℎ(�, �) = 1, excetuando-se a coluna i. Este é o conjunto dos nós de variável conectados ao nó de
verificação �� excetuando o nó de variável ��. O conjunto 3�\� tem dimensão igual a 46-1 e é formado
pelos elementos {�r, �<,..., �s6 r}, que são os valores das colunas em que ℎ(�, �) = 1, para a linha j,
excetuando-se a coluna i.
Considere a matriz de verificação de paridade H da Figura 3.5. Para a primeira linha, o conjunto
dos valores de coluna em que ℎ(�, �) = 1 é {2,4,5,8}. Assim, o cálculo do valor de �('<r) depende dos
valores de �(&rt), �(&ru) e �(&rv), e o cojunto {�r, �<,..., �s6 r} é igual a {4,5,8}.
Da mesma forma, para a terceira linha, o conjunto dos valores de coluna em que ℎ(�, �) = 1 é
{3,6,7,8}. Assim, o cálculo do valor de �('wx) depende os valores de �(&xx), �(&xy) e �(&xv) e o
conjunto {�r, �<,..., �s6 r} é igual a {3,7,8}.
O bloco módulo-mínimo da Figura 3.6 recebe como entrada 12 bits, pois ele precisa saber se o
número é negativo ou não para convertê-lo ao seu complemento de 2, e assim obter qual possui menor
módulo. O bloco concatenação, por sua vez, recebe a magnitude do menor valor do módulo de �(&��),
11 bits, e concatena com o bit de sinal, 1 bit, resultante da operação com todos os sinais de �(&��),
formando, desta forma, o valor de �('��).
52
3.2.2.2 Calculador do Passo Vertical
O passo vertical é a etapa em que são calculados os valores de probabilidade da mensagem que
o nó de variável �� envia para o nó de verificação ��. A mensagem �(&��) só existirá quando ℎ(�, �) = 1.
Cada valor de �(&��) é obtido pela soma de valores de �('��) e do valor de �(��), que é o valor
inicial da probabilidade da palavra recebida do canal. Consequentemente, este bloco foi implementado
com somadores em cascata, sendo que cada somador armazena um conjunto de 12 bits, conforme
descrito na Figura 2.13.
Como o calculador de �(&��) é um acumulador, o dado foi projetado com parte inteira de 7 bits
para evitar saturação. A soma foi implementada com complemento de 2, tendo valores no intervalo
[−128,127], sendo que o valor da soma é protegido contra overflow e underflow. Se a soma exceder o
valor de 127, ou se ela for inferior a -128, este valor é armazenado.
A Figura 3.7 ilustra a implementação do calculador dos valores �(&��) . O bloco somador
executa a soma de valores de 12 bits no intervalo [-128,127] e �(��) é o valor inicial da probabilidade
da palavra recebida do canal. O cálculo dos valores de �(&��) é realizado para um valor fixo i, que
representa a coluna percorrida durante o passo vertical.
Figura 3.7 – Passo Vertical do decodificador LDPC.
A variável �P pertence ao conjunto �\� , que é o conjunto formado pelos valores de linha da
coluna i em que ℎ(�, �) = 1 , excetuando-se a linha j. Este é o conjunto dos nós de verificação
conectados ao nó de variável �� excetuando o nó de verificação ��. O conjunto �\� tem dimensão igual
53
a 45-1 e é formado pelos elementos {�r, �<,..., �s5 r}, que são os valores das colunas em que ℎ(�, �) =1, para a linha j, excetuando-se a coluna i.
Considere a matriz de verificação de paridade H da Figura 3.5. Para a primeira coluna, o
conjunto dos valores de linha em que ℎ(�, �) = 1 é {2,4}. Assim, o cálculo do valor de �(&r<) depende
dos valores de �('tr) e �(�r), e o conjunto {�r, �<,..., �s5 r} é igual a {4}.
Da mesma forma, para a sexta coluna, o conjunto dos valores de linha em que ℎ(�, �) = 1 é
{2,3}, Assim, o cálculo do valor de �(&wx) depende os valores de �('w<) e �(�w), e o conjunto {�r, �<,..., �s6 r} é igual a {2}.
3.2.2.3 Decisão
Este bloco é responsável pelo cálculo do logaritmo da razão de verossimilhança da
probabilidade a posteriori para cada nó de variável ��, �(��), pela obtenção da palavra decodificada e
pelo cálculo da síndrome desta palavra.
O valor de �(��) é obtido através da soma de todos os valores �('��) em que ℎ(�, �) = 1 para
determinada coluna i. A Figura 3.8 descreve como o calculador de �(��) foi implementado. A variável �P pertence ao conjunto � , que é o conjunto formado pelos valores de linha da coluna i em que ℎ(�, �) = 1. Este é o conjunto dos nós de verificação conectados ao nó de variável ��. O conjunto � tem dimensão igual a 45 e é formado pelos elementos {�r, �<,..., �s5}, que são os valores das colunas
em que ℎ(�, �) = 1, para a linha j.
Considere a matriz de verificação de paridade H da Figura 3.5. Para a primeira coluna, o
conjunto dos valores de linha em que ℎ(�, �) = 1 é {2,4}. Assim, o cálculo do valor de �(�r) depende
dos valores de �('<r) e �('tr) e o conjunto {�r, �<,..., �s5} é igual a {2,4}.
Da mesma forma, para a sexta coluna, o conjunto dos valores de linha em que ℎ(�, �) = 1 é
{2,3}, Assim, o cálculo do valor de �(�w) depende os valores de �('w<) e �('wx) e o conjunto {�r, �<,..., �s6} é igual a {2,3}.
54
Figura 3.8 – Calculador de �(��).
A palavra decodificada é obtida através dos valores de �(��). Cada bit da palavra-código
recebida, �̂(�), é obtido através da equação (3.2).
�̂(�) = U 1, VG �(��) < 00, caso contrário (3.2)
A implementação da equação (3.2) é simples. Verificando-se o valor do sinal de �(��), bit mais
significativo, determina-se se o valor de �̂(�) é 1 ou 0.
Uma vez decodificada a palavra-código recebida, sua síndrome é calculada. O cálculo da
síndrome ocorre através da equação (3.3) onde ̂ é a palavra-código recebida, �� é a transposta da
matriz de verificação de paridade e s é a síndrome.
} = ̂�� (3.3)
A Figura 3.13 ilustra como o calculador de síndrome foi implementado. O cálculo da síndrome é
semelhante ao codificador e consiste em portas lógicas XOR em cascata. A síndrome s é um vetor de
dimensão (1 x n-k) e seus bits, s(i), são determinados multiplicando-se o vetor ̂ com a coluna i da
matriz ��, onde n é o número de bits da palavra-código. Se existe ��(1, �), o bit �̂(�) da palavra-código
recebida entra no cálculo do bit s(i) da síndrome, caso contrário, não. A variável i pertence ao conjunto
[1,n], onde n é o número de colunas da matriz ��.
55
Figura 3.9 – Calculador de síndrome do decodificador LDPC.
Na implementação, a etapa da decisão é a etapa mais lenta do decodificador, pois realiza o
cálculo de �(��), o cálculo da palavra decodificada e de sua síndrome em um mesmo pulso de relógio.
Este bloco poderia ser executado em mais de um pulso de relógio, mas isto acarretaria em uma maior
latência no cálculo da palavra decodificada.
3.2.2.4 Propagação dos dados dentro do decodificador
A decodificação de uma palavra codificada LDPC recebida leva três pulsos de relógio para
ocorrer. No primeiro pulso de relógio acontece o cálculo dos valores de �('��), no segundo pulso de
relógio é realizada a atualização dos valores de �(&��) e no terceiro pulso de relógio é calculada a
palavra LDPC decodificada.
A Figura 3.10 ilustra como ocorre a propagação das palavras que chegam ao decodificador
LDPC. No instante t, a palavra data_in(t) chega ao decodificador e os valores de �('��) para esta
palavra são calculados. No instante t+1, enquanto a palavra data_in(t) tem seus valores de �(&��)
calculados, chega ao decodificador uma nova palavra, data_in(t+1), que tem calculados os seus valores
56
de �('��).
No instante t+2, enquanto a palavra data_in(t) tem sua palavra decodificada, data_in(t+1) seus
valores de �(&��) calculados, chega ao decodificador uma nova palavra, data_in(t+2) que tem
calculados os seus valores de �('��). No instante t+3, a palavra data_in(t) tem sua palavra decodificada, data_out(t+3), exteriorizada
pelo decodificador, a palavra data_in(t+1) tem sua palavra decodificada calculada, a palavra
data_in(t+2) tem seus valores de �(&��) calculados e a palavra que que chegou no instante t+3,
data_in(t+3), tem seus valores de �('��) calculados.
A palavra que chegou no instante t+1, data_in(t+1), tem sua palavra decodificada exteriorizada
no instante t+4, a palavra que chegou no instante t+2, data_in(t+2), tem sua palavra decodificada,
data_out_(t+5) exteriorizada no instante t+5 e assim continua o processo de decodificação. Enquanto
este processo acontece, novas palavras chegam ao decodificador e suas etapas internas continuam em
operação.
É necessário ressaltar o preço de cada iteração do decodificador LDPC. Cada iteração do
decodificador dura três pulsos de relógio, sendo necessários, portanto, três novos blocos do
decodificador para cada nova iteração. Desta forma, chega-se em um compromisso entre o aumento de
desempenho e o aumento do número de elementos lógicos. Por exemplo, um decodificador que
realizasse quatro iterações precisaria de 12 blocos básicos para funcionar.
Caso a palavra decodificada já esteja correta antes de alcançar todas as iterações, as operações
matemáticas são interrompidas, sendo o valor da palavra decodificada apenas propagado para manter o
sincronismo e a latência do decodificador.
57
Figura 3.10 – Propagação dos dados ao longo dos vários blocos do decodificador..
58
4 RESULTADOS
Neste capítulo são apresentados os resultados da comparação do desempenho de dois algoritmos
de decodificação de códigos LDPC, os algoritmos log-SP e SM, para os códigos IE-LDPC construídos.
Este capítulo também apresenta os resultados da síntese em FPGA do codificador e do decodificador
implementados para estes códigos.
4.1 Comparação do desempenho dos algoritmos de decodificação log-SP e SM para os códigos
IE-LDPC construídos
Esta seção apresenta os resultados da comparação do desempenho dos códigos IE-LDPC
construídos e decodificados com os algoritmos de decodificação log-SP e SM. Foram construídos
códigos LDPC binários, irregulares e estruturados de comprimentos (2000, 1000) e (4000, 2000). As
matrizes de verificação de paridade destes códigos foram construídas conforme descrito na seção
2.1.2.1 desta dissertação.
Os comprimentos destes códigos foram escolhidos de tal forma que, quando estes códigos
fossem sintetizados, seus codificadores e decodificadores operassem em frequências compatíveis com
operações em FPGA. Para os códigos IE-LDPC (2000, 1000) e IE-LDPC (4000, 2000) é necessário que
seus codificadores e decodificadores, quando em funcionamento em FPGA, tenham frequência de
operação de no mínimo 50 MHz e 25 MHz, respectivamente.
A comparação do desempenho foi realizada através da simulação da transmissão de dados
através de um canal AWGN, tido como uma simplificação do modelo de canal utilizado em
comunicações ópticas. A simulação foi realizada utilizando-se o software MATLAB e as palavras-
códigos transmitidas foram decodificadas iterativamente utilizando cinco iterações.
A Figura 4.1 apresenta o ambiente em que os algoritmos de decodificação tiveram seu
desempenho analisado. A sequência de informação foi gerada de forma aleatória, em seguida, foi
codificada e transmitida por um canal AWGN. Por fim, a palavra-código recebida foi decodificada e a
estimativa da sequência de informação foi comparada com a sequência de informação original a fim de
se obter a taxa de erro de bit na recepção. Tal procedimento foi realizado para diversos valores de
59
relação sinal/ruído por bit (��/()).
Figura 4.1 – Cenário da simulação dos códigos IE-LDPC.
A meta neste capítulo é ajustar a dimensão da matriz identidade que gera os códigos IE-LDPC
de forma a estreitar o intervalo entre os desempenhos dos processos de decodificação log-SP e SM. Isto
permite a escolha de códigos LDPC que associados à decodificação SM utilizem menor número de
elementos lógicos na placa FPGA com baixa perda no processo de decodificação.
4.1.1 Resultados da comparação do desempenho dos algoritmos log-SP e SM para os códigos
IE-LDPC (2000, 1000)
Quatro códigos foram construídos utilizando matriz identidade com os seguintes valores de
ordem: 50, 100, 200 e 500. As Figuras 4.2 a 4.5 mostram o desempenho dos algoritmos de
decodificação para estes códigos IE-LDPC (2000, 1000).
4.1.1.1 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 50
A forma reduzida da matriz H do código IE-LDPC (2000, 1000), gerada a partir de uma matriz
identidade de ordem igual a 50, está representada na equação (4.1).
60
� = � �u) 2u) … 2u) Eu),< Eu),x … Eu),<r2u) �u) … 2u) Eu),<x Eu),<� … Eu),<x⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮2u) 2u) … �u) Eu),<r Eu),xx … Eu),tr�
(4.1)
A Figura 4.2 mostra que para este código, o ganho do algoritmo log-SP em relação ao algoritmo
SM ficou em um intervalo de amplitude igual a 1,5 dB, valor este alcançado para uma BER = 10-5.
Figura 4.2 – Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz identidade de
ordem igual a 50.
4.1.1.2 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 100
A forma reduzida da matriz H do código IE-LDPC (2000, 1000), gerada a partir de uma matriz
identidade de ordem igual a 100, está representada na equação (4.2).
� = � �r)) 2r)) … 2r)) Er)),< Er)),x … Er)),<�2r)) �r)) … 2r)) Er)),xr Er)),xy … Er)),yr⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮2r)) 2r)) … �r)) Er)),wy Er)),y� … Er)),tr�
(4.2)
Para este código, conforme visto na Figura 4.3, o algoritmo SM teve desempenho 0,4 dB
61
inferior ao log-SP, para BER = 10-4.
Figura 4.3 - Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz identidade de
ordem igual a 100.
4.1.1.3 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 200
A forma reduzida da matriz H do código IE-LDPC (2000, 1000), gerada a partir de uma matriz
identidade de ordem igual a 200, está representada na equação (4.3).
� = � �<)) 2<)) … 2<)) E<)),< E<)),x … E<)),rr2<)) �<)) … 2<)) E<)),rx E<)),ry … E<)),<�⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮2<)) 2<)) … �<)) E<)),yx E<)),y� … E<)),�y�
(4.3)
Para este código, apresentado pela Figura 4.4, a variação do desempenho do algoritmo log-SP,
em termo de relação sinal/ruído, ficou em um intervalo de 0,15 dB maior em relação ao algoritmo SM,
para uma BER = 10-4.
62
Figura 4.4 - Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz identidade de
ordem igual a 200.
4.1.1.4 Resultados para o código IE-LDPC (2000, 1000) gerado a partir de uma matriz
identidade de ordem igual a 500
A forma reduzida da matriz H do código IE-LDPC (2000, 1000), gerada a partir de uma matriz
identidade de ordem igual a 500, está representada na equação (4.4).
� = � �u)) 2u))2u)) �u)) Eu)),< Eu)),xEu)),u Eu)),y� (4.4)
A Figura 4.5 mostra que os dois algoritmos de decodificação têm desempenho próximos e que a
máxima diferença de desempenho entre os dois algoritmos é menor que 0,12 dB, a favor do log-SP,
para uma BER em torno de 10-4.
63
Figura 4.5 - Curvas de desempenho do código IE-LDPC (2000, 1000) gerado a partir de uma matriz identidade de
ordem igual a 500.
Dentre os códigos IE-LDPC(2000,1000) construídos, o que apresentou melhor desempenho foi
o código gerado a partir de uma matriz identidade de ordem igual a 50, alcançando uma taxa de erro
próxima a 10-6 para um relação sinal-ruído de 2 dB, quando decodificado com o algoritmo log-SP. Isso
é devido ao fato de que quanto menor a ordem da matriz identidade, maior será a quantidades de 1s por
linha e coluna e, consequentemente, maior será a quantidade de nós de variável e nós de verificação.
Por fim, uma quantidade maior de nós aumenta a precisão do cálculo dos valores das probabilidades
permutadas entre os nós do código LDPC. Além disso, quanto maior a dimensão da matriz identidade
que vai gerar os códigos IE-LDPC, mais o desempenho do algoritmo SM se aproxima do desempenho
do algoritmo log-SP.
4.1.2 Resultados da comparação do desempenho dos algoritmos log-SP e SM para os códigos
IE-LDPC (4000, 2000)
Cinco códigos foram construídos utilizando matriz identidade com os seguintes valores de
64
ordem: 50, 100, 200, 500 e 1000. As Figuras 4.6 a 4.10 mostram o desempenho dos algoritmos de
decodificação para estes códigos IE-LDPC (4000 2000).
4.1.2.1 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 50
A forma reduzida da matriz H código IE-LDPC (4000, 2000), gerada a partir de uma matriz
identidade de ordem igual a 50, do está representada na equação (4.5).
� = � �u) 2u) … 2u) Eu),< Eu),x … Eu),<x2u) �u) … 2u) Eu),<� Eu),xr … Eu),�⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮2u) 2u) … �u) Eu),<r Eu),<y … Eu),t��
(4.5)
A Figura 4.6 mostra que para o presente código, o desempenho do algoritmo log-SP é melhor
que o do SM em torno de 1 dB, para BER aproximadamente igual a 10-3.
Figura 4.6 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz identidade
de ordem igual a 50.
4.1.2.2 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 100
65
A forma reduzida da matriz H do código IE-LDPC (4000, 2000), gerada a partir de uma matriz
identidade de ordem igual a 100, está representada na equação (4.6).
� = � �r)) 2r)) … 2r)) Er)),< Er)),x … Er)),yr2r)) �r)) … 2r)) Er)),yx Er)),y� … Er)),yx⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮2r)) 2r)) … �r)) Er)),<r Er)),xx … Er)),tr�
(4.6)
Conforme ilustrado na Figura 4.7, para este código, a diferença de desempenho entre os dois
algoritmos chega a alcançar 1,3 dB a favor do log-SP, para BER igual a 10-4.
Figura 4.7 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz identidade
de ordem igual a 100.
4.1.2.3 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 200
A forma reduzida da matriz H do código IE-LDPC (4000, 2000), gerada a partir de uma matriz
identidade de ordem igual a 200, está representada na equação (4.7).
66
� = � �<)) 2<)) … 2<)) E<)),< E<)),x … E<)),<�2<)) �<)) … 2<)) E<)),xr E<)),xy … E<)),yr⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮2<)) 2<)) … �<)) E<)),wy E<)),y� … E<)),rtr�
(4.7)
A Figura 4.8 mostra que, para este código, a diferença de desempenho a favor do algoritmo log-
SP fica em um intervalo que não excede o valor 0,75 dB.
Figura 4.8 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz identidade
de ordem igual a 200.
4.1.2.4 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 500
A forma reduzida da matriz H do código IE-LDPC (4000, 2000), gerada a partir de uma matriz
identidade de ordem igual a 500, está representada na equação (4.8).
� = � �u)) 2u)) … 2u)) Eu)),< Eu)),x … Eu)),rr2u)) �u)) … 2u)) Eu)),rx Eu)),ry … Eu)),<�⋮ ⋮ ⋱ ⋮ ⋮ ⋮ ⋱ ⋮2u)) 2u)) … �u)) Eu)),yx Eu)),y� … Eu)),�y�
(4.8)
A Figura 4.9 mostra que, para este código, o decréscimo de desempenho do algoritmo SM em
relação ao log-SP não ultrapassa 0,15 dB.
67
Figura 4.9 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz identidade
de ordem igual a 500.
4.1.2.5 Resultados para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 1000
A forma reduzida da matriz H do código IE-LDPC (4000, 2000), gerada a partir de uma matriz
identidade de ordem igual a 1000, está representada na equação (4.9).
� = � �r))) 2r)))2r))) �r))) Er))),< Er))),xEr))),u Er))),y� (4.9)
A Figura 4.10 mostra que, para este código, os dois algoritmos têm desempenho praticamente
idênticos, exceto por uma pequena diferença de 0,06 dB, em favor do algoritmo log-SP, para uma BER
próxima a 10-2.
68
Figura 4.10 - Curvas de desempenho para o código IE-LDPC (4000, 2000) gerado a partir de uma matriz
identidade de ordem igual a 1000.
Diferentemente do esperado, o código IE-LDPC(4000,2000) de melhor desempenho não o
código foi o código gerado a partir de uma matriz identidade de ordem igual a 50, e sim o código
gerado a partir de uma matriz identidade de ordem igual a 100, apesar do primeiro ter um número
maior de 1s por linha e coluna. Isso ocorre devido à existência de girth igual a 4 na matriz verificadora
de paridade do código IE-LDPC(4000,2000) gerado a partir de uma matriz identidade de ordem igual a
50. Como existem apenas 15 números primos menores que 50 e vinte matrizes circulantes são geradas
para gerar a matriz H, haverá 5 matrizes coincidentes a cada conjunto de 50 linhas. Novamente foi
observado para estes códigos que quanto maior a dimensão da matriz identidade que vai gerar os
códigos IE-LDPC, mais o desempenho do algoritmo SM se aproxima do desempenho do algoritmo log-
SP.
4.2 Resultados da síntese em FPGA do codificador e do decodificador LDPC
Esta seção apresenta os resultados da síntese do codificador e do decodificador para dois
69
códigos IE-LDPC na Virtex-5 XC5VLX50T, FPGA utilizada na presente dissertação.
Os codificadores e os decodificadores foram sintetizados em FPGA utilizando-se o software ISE
WebPACK da Xilinx. As implementações em VHDL do codificador e do decodificador foram simuladas
utilizando-se o software Modelsim. Os resultados obtidos através deste software foram comparados
com os resultados obtidos através da implementação do codificador e decodificador em MATLAB, a
fim de validar o funcionamento do codificador e do decodificador descritos em VHDL.
A ideia inicial era sintetizar os códigos IE-LDPC (2000, 1000) e IE-LDPC (4000, 2000) que
apresentassem decodificação SM com menor perda de desempenho em relação a log-SP. Porém, devido
às limitações físicas da plataforma FPGA utilizada, como alternativa foi realizada a síntese do
codificador e do decodificador para o código IE-LDPC (40, 20), gerado a partir de uma matriz
identidade de ordem igual a 10, e o código IE-LDPC (200, 100), gerado também a partir de uma matriz
identidade de ordem igual a 10. Em ambos os casos, o decodificador sintetizado executa apenas uma
iteração.
As tabelas 4.1 e 4.2 apresentam os resultados, em termos de parâmetros de implementação na
placa FPGA, das sínteses do codificador e do decodificador dos códigos IE-LDPC (40, 20) e IE-LDPC
(200, 100), respectivamente.
Tabela 4.1- Parâmetros do codificador e do decodificador do código IE-LDPC (40, 20) na FGPA
LDPC (40, 20)
Codificador Decodificador
n° de LUTs 47 4795 % de LUTs utilizadas 0,1 % 10,4 % n° de flip-flops 25 882 % de flip-flops utilizados 0,08 % 3 % Frequência máxima de operação
362,8 MHz 140,6 MHz
Tabela 4.2 - Parâmetros do codificador e do decodificador do código IE-LDPC (200, 100) na FGPA
LDPC (200, 100)
Codificador Decodificador
n° de LUTs 199 153264 % de LUTs utilizadas 0,4 % 332 %
70
n° de flip-flops 100 9962 % de flip-flops utilizados 0,3 % 34,6 % Frequência máxima de operação
330,8 MHz 46,8 MHz
Pela análise das tabelas 4.1 e 4.2, percebe-se que o decodificador do código IE-LDPC utiliza
bem mais LUTs e flip-flops do que o codificador, portanto, qualquer esforço em diminuir o número de
elementos da FPGA utilizados na implementação descrita nesta dissertação tem que ser concentrado no
decodificador.
O número de LUTs e flip-flops utilizados pelo decodificador aumenta consideravelmente com o
aumento do comprimento do código LDPC. A síntese do decodificador do código IE-LDPC (200, 100)
utilizou 11 vezes mais flip-flops e 32 vezes mais LUTs do que a síntese do código IE-LDPC (40, 20),
de comprimento cinco vezes menor.
Além disso, o decodificador do código IE-LDPC (200, 100) tem uma frequência máxima de
operação bem menor do que a do decodificador IE-LDPC (40, 20), levando à conclusão que para
códigos LDPC de comprimentos maiores, a frequência máxima do decodificador seria menor ainda.
O decodificador do código IE-LDPC (200, 100) utiliza mais LUTs do que as existentes na
FPGA utilizada, que possui um total de 28.800 flip-flops e 46.080 LUTs. O uso de uma FPGA com
mais LUTs e flip-flops influenciaria consideravelmente no preço comercial de um ipcore formado por
um codificador e decodificador LDPC. Por isto, a melhor alternativa para a síntese do decodificador
LDPC é o estudo de uma nova arquitetura e não a substituição da FPGA empregada no projeto.
O elevado número de LUTs utilizadas no decodificador está relacionado com a implementação
em VHDL, que armazenou os valores de �(&��) e �('��) em LUTs. Uma forma de diminuir a
quantidade de LUTs utilizadas pelo decodificador é o uso de uma memória cujos processos de escrita e
leitura funcionassem a uma taxa bem maior que o a taxa da propagação das mensagens �(&��) e �('��)
dentro do decodificador. Outra forma de diminuir a quantidade de LUTs utilizadas pelo decodificador é
representar os valores utilizados no cálculo da decodificação LDPC através de uma menor quantidade
de bits, em vez dos 12 bits atuais.
O número de LUTs e flip-flops mostrados nas tabelas 4.1 e 4.2 são apenas para uma iteração no
processo de decodificação. A cada nova iteração de decodificação, a quantidade total de elementos
lógicos e flip-flops do decodificador também teria que ser aumentada.
71
5 CONCLUSÃO E TRABALHOS FUTUROS
5.1 Conclusão
O desenvolvimento de códigos LDPC binários, irregulares e estruturados utilizando-se o
método descrito mostrou ser capaz de gerar códigos de forma simples e rápida. Como esperado, para
todos os códigos construídos, a decodificação utilizando o algoritmo soma-produto com razões
logarítmicas (log-SP) teve melhor desempenho do aquela em que foi utilizado o algoritmo soma-
mínimo (SM).
Para alguns códigos IE-LDPC, a diferença de desempenho entre os algoritmos de decodificação
ficou menor do que 0,2 dB, valor pequeno frente à economia de elementos lógicos que o algoritmo SM
propicia quando implementado. Vale ressaltar que quanto maior a dimensão da matriz identidade que
vai gerar os códigos IE-LDPC, mais o desempenho do algoritmo SM se aproxima do desempenho do
algoritmo log-SP.
Quanto à implementação em VHDL, a metodologia aplicada na decodificação precisa ser
melhor dimensionada para sua sintetização em FPGA, tendo em vista que esta utilizou muitos
elementos lógicos.
A utilização de mais placas FPGA de modo a dividir as operações executadas no processo de
decodificação também seria uma possibilidade de implementação. Esta alternativa seria a mais viável
embora envolva um maior custo financeiro de implementação.
Os códigos IE-LDPC obtidos e analisados mostram que, ajustando-se a dimensão da matriz
identidade geradora das submatrizes circulantes componentes da matriz H, pode-se fazer com que o
desempenho do algoritmo de decodificação SM se aproxime do desempenho do algoritmo log-SP,
propiciando uma considerável redução de elementos lógicos na placa FPGA sem que haja uma
degradação significativa do desempenho em termos de BER por Eb/N0.
5.2 Trabalhos Futuros
Para o desenvolvimento e implementação de um código LDPC de bom desempenho com
72
aplicação em comunicações ópticas, os seguintes trabalhos ainda necessitam ser realizados:
a) Estudo, construção e análise do desempenho de outros códigos estruturados tais como os
códigos LDPC quase-cíclicos (QC-LDPC);
b) Estudo de códigos estruturados não-binários;
c) Estudo de outros algoritmos sub-ótimos de decodificação de códigos LDPC;
d) Implementação de arquiteturas do decodificador LDPC que utilizem menor quantidade de
elementos lógicos na placa FPGA;
e) Modelagem mais precisa do canal óptico;
f) Representação com menor número de bits da notação em ponto fixo dos números envolvi-
dos no cálculo da decodificação dos códigos LDPC;
g) Estudo e implementação de código corretores de erro conjuntamente com modulação não
binária (BPSK);
h) Desenvolvimento da interface óptica-elétrica necessária para a validação em hardware do
codificador e do decodificador LDPC sintetizados em FPGA.
73
REFERÊNCIAS BIBLIOGRÁFICAS
[1] I. Djordjevic, W. Ryan and B. Vasic, Coding for optical channels. New York: Springer, 2010.
[2] Wada, H., et al. FEC Considerations for 10Gbps EPON System. September 18, 2006. Disponível em: <http://www.ieee802.org/3/av/public/2006_09/3av_0609_wada_1.pdf> Acesso em: 17 ago.2010.
[3] J. Castiñeira Moreira and P. Farrell, Essentials of error-control coding. West Sussex, England: John Wiley & Sons, 2006.
[4] Sae-Young Chung; Forney, G.D., Jr.; Richardson, T.J.; Urbanke, R., "On the design of low-density parity-check codes within 0.0045 dB of the Shannon limit," in Communications Letters, IEEE , vol.5, no.2, pp.58-60, Feb 2001.
[5] IEEE Unapproved Draft Std P802.11n/D11.0, Jun. 2009.
[6] M. Jobes. A VLSI Architecture and the FPGA Implementation for multi-rate LDPC Decoding, MASc thesis, McMaster University, 2009.
[7] M. Karkooti. Semi-Parallel Architectures for Real-Time LDPC Coding, MASc thesis, Rice University, 2004.
[8] W. E. Ryan. An Introduction to LDPC codes. Disponível em: <http://www.telecom.tuc.gr/~alex/papers/ryan.pdf> Acesso em: 13 fev.2011.
[9] J. Teubner and L. Woods, Data processing on FPGAs. San Rafael, Calif.: Morgan & Claypool, 2013.
[10] Virtex-5 FPGA User Guide. Disponível em: <http://www.xilinx.com/support/documentation/user_guides/ug190.pdf> Acesso em: 22 jun. de 2012.
[11] Karkooti, M.; Cavallaro, J.R., "Semi-parallel reconfigurable architectures for real-time LDPC decoding," Information Technology: Coding and Computing, 2004. Proceedings. ITCC 2004. International Conference on , vol.1, no., pp.579,585 Vol.1, 5-7 April 2004.
[12] Mansour, M.M.; Shanbhag, N.R., "Low-power VLSI decoder architectures for LDPC codes," in Low Power Electronics and Design, 2002. ISLPED '02. Proceedings of the 2002 International Symposium on, vol., no., pp.284-289, 2002.
[13] L. Yang. An area-efficient architecture for the implementation of LDPC decoder, MASc thesis, Case Western Reserve University, 2011.
[14] Xiao-Yu Hu; Eleftheriou, E.; Arnold, D.-M.; Dholakia, A., "Efficient implementations of the sum-product algorithm for decoding LDPC codes," in Global Telecommunications Conference, 2001. GLOBECOM '01. IEEE , vol.2, no., pp.1036-1036E vol.2, 2001.
[15] Hosseini, S.M.E.; Sann Chan, Kheong; Wang Ling Goh, "A reconfigurable FPGA implementation
74
of an LDPC decoder for unstructured codes," in Signals, Circuits and Systems, 2008. SCS 2008. 2nd International Conference on , vol., no., pp.1-6, 7-9 Nov. 2008.
[16] Darabiha, A.; Carusone, A.C.; Kschischang, F.R., "A bit-serial approximate min-sum LDPC decoder and FPGA implementation," in Circuits and Systems, 2006. ISCAS 2006. Proceedings. 2006 IEEE International Symposium on , vol., no., pp.4 pp.-, 21-24 May 2006.
[17] Kamiya, N.; Shioiri, S., "Concatenated QC-LDPC and SPC codes for 100 Gbps ultra long-haul optical transmission systems," in Optical Fiber Communication (OFC), collocated National Fiber Optic Engineers Conference, 2010 Conference on (OFC/NFOEC), vol., no., pp.1-3, 21-25 March 2010.
[18] Djordjevic, I.B.; Arabaci, M.; Minkov, L.L., "Next Generation FEC for High-Capacity Communication in Optical Transport Networks," in Lightwave Technology, Journal of, vol.27, no.16, pp.3518-3530, Aug.15, 2009.
[19] Yun Chen; Xiang Chen; Yifei Zhao; Chunhui Zhou; Jing Wang, "Design and implementation of multi-mode QC-LDPC decoder," in Communication Technology (ICCT), 2010 12th IEEE International Conference on, vol., no., pp.1145-1148, 11-14 Nov. 2010.
[20] Spagnol, C.; Marnane, W., "A class of quasi-cyclic LDPC codes over GF(2m)," in Communications, IEEE Transactions on, vol.57, no.9, pp.2524-2527, September 2009.
[21] Chung-Jin Tsai; Mu-Chung Chen, "Efficient LDPC decoder implementation for DVB-S2 system," in VLSI Design Automation and Test (VLSI-DAT), 2010 International Symposium on, vol., no., pp.37-40, 26-29 April 2010.
[22] Zhengya Zhang; Dolecek, L.; Lee, P.; Anantharam, V.; Wainwright, M.J.; Richards, B.; Nikolic, B., "Low error rate LDPC decoders," in Signals, Systems and Computers, 2009 Conference Record of the Forty-Third Asilomar Conference on , vol., no., pp.1278-1282, 1-4 Nov. 2009.
[23] Jie Jin; Chi-ying Tsui, "A low power layered decoding architecture for LDPC decoder implementation for IEEE 802.11n LDPC codes," in Low Power Electronics and Design (ISLPED), 2008 ACM/IEEE International Symposium on , vol., no., pp.253-258, 11-13 Aug. 2008.
[24] Fanucci, L.; Rossi, F., "A throughput/complexity analysis for the VLSI implementation of LDPC decoder," in Signal Processing and Information Technology, 2004. Proceedings of the Fourth IEEE International Symposium on , vol., no., pp.409-412, 18-21 Dec. 2004.
[25] Hong Ding; Shuai Yang; Wu Luo; Mingke Dong, "Design and Implementation for High Speed LDPC Decoder with Layered Decoding," in Communications and Mobile Computing, 2009. CMC '09. WRI International Conference on , vol.1, no., pp.156-160, 6-8 Jan. 2009.
[26] Guilloud, F.; Boutillon, E.; Tousch, J.; Danger, J.-L., "Generic Description and Synthesis of LDPC Decoders," in Communications, IEEE Transactions on , vol.55, no.11, pp.2084-2091, Nov. 2007.
[27] Bhatt, T., Narayanan, K., & Kehtarnavaz, N. (2000, October). Fixed point DSP implementation of low-density parity check codes. In Proc. Ninth DSP Workshop, Hunt, Texas.
75
[28] Brack, T.; Alles, M.; Lehnigk-Emden, T.; Kienle, F.; Wehn, N.; L'Insalata, N.E.; Rossi, F.; Rovini, M.; Fanucci, L., "Low Complexity LDPC Code Decoders for Next Generation Standards," in Design, Automation & Test in Europe Conference & Exhibition, 2007. DATE '07 , vol., no., pp.1-6, 16-20 April 2007.
[29] Beuschel, C.; Pfleiderer, Hans-Jörg, "FPGA implementation of a flexible decoder for long LDPC codes," in Field Programmable Logic and Applications, 2008. FPL 2008. International Conference on , vol., no., pp.185-190, 8-10 Sept. 2008.
[30] Mizuochi, T.; Konishi, Y.; Miyata, Y.; Inoue, T.; Onohara, K.; Kametani, S.; Sugihara, T.; Kubo, K.; Kobayashi, T.; Yoshida, H.; Ichikawa, T., "FPGA based prototyping of next generation forward error correction," in Optical Communication, 2009. ECOC '09. 35th European Conference on , vol., no., pp.1-4, 20-24 Sept. 2009.
[31] Yongyi Mao; Banihashemi, A.H., "A heuristic search for good low-density parity-check codes at short block lengths," in Communications, 2001. ICC 2001. IEEE International Conference on, vol.1, no., pp.41-44 vol.1, 11-14 Jun 2001.
[32] Sae-Young Chung; Richardson, T.J.; Urbanke, R.L., "Analysis of sum-product decoding of low-density parity-check codes using a Gaussian approximation," in Information Theory, IEEE Transactions on , vol.47, no.2, pp.657-670, Feb 2001.
[33] W. P. de S. Guimarães, Decodificação híbrida para códigos LDPC, Tese (Doutorado em Eng. Elétrica), Programa de Pós-Graduação em Engenharia Elétrica da Universidade Federal de Pernambuco, Recife, PE, 2013.
[34] M. A. C. Gomes, Códigos binários definidos por matrizes de teste de paridade esparsas algoritmos de descodificação, MASc thesis,Universidade de Coimbra, 2003.
[35] LDPC code using MATLAB and C MEX. Disponível em <http://sites.google.com/site/bsnugroho/ldpc>. Acesso em: 3 set. 2011.
[36] Soares, André. “Desafios das próximas gerações de Redes Ópticas de Transporte.” UFPI. ENUCOMP 2013. Disponível em <http://www.enucomp.com.br/2013/conteudos/palestras/palestra_andre.pdf>. Acesso em: 27 jul. 2014.
76
ANEXOS
77
ANEXO A – Código-fonte dos arquivos desenvolvidos para realizar a análise do desempenho dos
algoritmos log-SP e SM utilizando os códigos IE-LDPC construídos
% ----------------------------------------------------------------------------
%% ldpd_top.m %%
% Script to test dec_logSP_f.
clear;
clc;
tic;
%% File for the results
fid = fopen('ber_res.txt','w');
%% Signal-to-noise ratio
SNR_dB = 0:.5:7;
%SNR_dB = 2;
%% Initializations
% error number for log-SP algorithm
n1_err = zeros(1,length(SNR_dB));
% error number for SM algorithm
n2_err = zeros(1,length(SNR_dB));
% number of transmitted words
%N = 10^4;
%N = 10^3
N_vec = [10^3 10^3 10^3 10^3 10^3 10^4 10^4 10^4 10^5 10^5 10^5 10^6 10^6 10^7 10^7];
n_min_err = [100 100 100 50 50 50 25 25 25 25 10 10 10 10 10];
%% generating parity-check and generator matrix
n = 2000;
k = 1000;
dim = 500; % identity matrix dimension
[H, G] = gen_mat_f(n,k,dim);
%% Iteration loop
78
% number of errors
n1_err = zeros(1,length(SNR_dB));
n2_err = zeros(1,length(SNR_dB));
% number of iterations
niter1 = zeros(1,length(SNR_dB));
niter2 = zeros(1,length(SNR_dB));
for ii = 1:length(SNR_dB)
err1 = 0;
err2 = 0;
for ll = 1:N_vec(ii)
%% Monte Carlo loop
if ((n1_err(ii) < n_min_err(ii)) && (n2_err(ii) < n_min_err(ii)))
%% LDPC encoding
m = randint(1,k,[0,1]);
c = ldpc_enc_f(m,G);
%% Modulation
x = 1 - 2*c;
%% Transmitting over a AWGN channel
[y, sigma] = awgn_channel_f(x,SNR_dB(ii));
%y = x;
%% LDPC decoding
fprintf('Decoding %d word for %0.1f dB\n',ll,SNR_dB(ii));
% number of iterations
iter = 5;
% log-SP decoding
[logSP_c_hat, logSP_ok] = dec_logSP_f(y,H,iter,n,k,sigma);
%c
%logSP_c_hat
% SM decoding
[SM_c_hat, SM_ok] = dec_SM_f(y,H,iter,n,k);
%c
%SM_c_hat
%% Error computation
err1 = err1 + biterr(c,logSP_c_hat);
err2 = err2 + biterr(c,SM_c_hat);
niter1 = ll;
niter2 = ll;
79
n1_err(ii) = err1;
n2_err(ii) = err2;
n1_iter(ii) = niter1;
n2_iter(ii) = niter2;
% BER
ber1(ii) = n1_err(ii)/(n1_iter(ii)*length(y));
%ber1(ii) = n1_err(ii)/(N*length(y));
ber2(ii) = n2_err(ii)/(n2_iter(ii)*length(y));
%ber2(ii) = n1_err(ii)/(N*length(y));
fprintf('ber1: %d ber2: %d \n',n1_err(ii),n2_err(ii));
fprintf(fid,'ber1: %d ber2: %d \n',n1_err(ii),n2_err(ii));
else
break;
end
end
end
%% BER plot
figure('Color',[1 1 1]); % change background color
set(gca, 'Fontsize', 16)
semilogy(SNR_dB, ber1, 'rd-.', 'Linewidth', 3, 'Markersize', 8);
hold all;
semilogy(SNR_dB, ber2, 'bo-.', 'Linewidth', 3, 'Markersize', 8);
hold all;
xlabel('Eb/N0(dB)');
ylabel('BER');
grid on
legend('log-SP','SM',1);
%grid on;
hold off;
n1_err
n2_err
n1_iter
n2_iter
ber1
ber2
%% File
fclose(fid);
toc;
% ----------------------------------------------------------------------------
80
%% gen_mat_f.m %%
% This function generates a matrix H based on its colunm number (n), its
% line number (k) and the dimension of its basic matrix (dim).
function [H, G] = gen_mat_f(n,k,dim)
% There will be used ((n-k)/dim)*(k/dim) rotated matrices.
% The matrices are a prime number shifted.
% Initializing the matrix.
% Pt = transpose matrix of parity matrix
Pt = zeros((n-k),k);
% Prime number set. The value 20000 was chosen because for LDPC(4000,2000)
% and dim = 50, it is necessary 1600 shift values.
Prime_set = primes(200000);
% index of the prime number set element
index = 1;
% x1 is the column index inside matrix Mat
% x2 is the line index inside matrix Mat
for i=1:(n-k)/dim
for j=1:k/dim
% shift number
nrot = Prime_set(index);
% shifted matrix
Mrot = rot_mat_f(dim,nrot);
x1 = dim*(j-1)+ 1;
x2 = dim*(i-1)+ 1;
Pt(x2:x2+dim-1,x1:x1+dim-1) = Mrot;
index = index + 1;
end
end
% parity-check matrix
H = [eye(n-k) Pt];
% parity matrix
P = Pt';
% generator matrix
G = [P eye(k)];
81
% ----------------------------------------------------------------------------
%% rot_mat_f.m %%
% This function generates a matrix from the identity matrix shifted nrot
% colunms to the right.
% dim = identity matrix dimension
% nrot = right shift number
function Mrot = rot_mat_f(dim,nrot)
Meye = eye(dim);
P = [Meye(:,dim) Meye(:,1:dim-1)];
% initialized with the identity matrix
Mrot = P;
if nrot == 0
Mrot = eye(dim);
else
if nrot == 1
Mrot = P;
else
for i=1:mod(nrot-1,dim)
Mrot = Mrot*P;
end
end
end
% ----------------------------------------------------------------------------
%% ldpc_enc_f.m %%
% LDPC encoder
% m : word to be encoded
% G : generator matrix
function c = ldpc_enc_f(m,G)
% G = k x n
% m = 1 x k
% It is necessary to use m' at the multiplication
% Multiplication done at GF(2)
gf_m = gf(m',2);
gf_G = gf(G',2);
82
% G' = n x k m' = k x 1
% Multiplication G' and m' --> n x 1
gf_c = gf_G*gf_m;
% encoded word
c(gf_c == 1) = 1;
c(gf_c == 0) = 0;
% ----------------------------------------------------------------------------
%% awgn_channel_f.m %%
% AWGN channel
function [y, sigma] = awgn_channel_f(x,SNR)
N0 = 10^-(0.1*SNR);
sigma = sqrt(N0/2);
noise = sigma*randn(1,length(x));
y = x + noise;
% ----------------------------------------------------------------------------
%% dec_logSP_f.m %%
% Implementation of LDPC decoding algorithm log-SP.
% y: received word
% H: parity-check matrix
% iter: iteration number
function [c_hat, ok] = dec_logSP_f(y,H,iter,n,k,sigma)
% number of iterations done by the loop
it = 0;
ok = 1;
while (ok ~= 0 && it < iter)
if (it == 0)
% finding Hzon
[Hzon, wc_vec, wc] = hzon_f(H,n);
%Hzon
83
% finding Hver
[Hver, wr_vec, wr] = hver_f(H,k);
%Hver
% initialization
[Lc, Lq] = logSP_init_f(y,sigma,n,wc);
end
% Horizontal step
Lr = logSP_Hstep_f(Lq,Hzon,Hver,k,wr,wr_vec,wc_vec);
% Vertical step
Lq = Vstep_f(Lr,Lc,Hzon,Hver,n,wc,wc_vec,wr_vec);
% Q calculation
Q = Qcalc_f(Lr,Lc,Hzon,Hver,n,wc_vec,wr_vec);
% Decision
c_hat = decision_f(Q,n);
% Syndrome
synd = synd_f(c_hat, H);
ok = sum(synd.x);
it = it + 1;
end
% ----------------------------------------------------------------------------
%% hzon_f.m %%
% The matrix Hzon stores the columns of the matrix H where there are
% non-zero elements.
function [Hzon, wc_vec, wc] = hzon_f(H,n)
% column and line positions for H(1,1) == 1
[row, col] = find(H == 1);
% vector with wc for all columns
wc_vec = zeros(1,n);
% determining wc
max_wc = 0;
84
for i=1:n
% number of 1s in a column
n_wc = 0;
for j=1:length(col)
if col(j) == i
n_wc = n_wc + 1;
end
end
wc_vec(i) = n_wc;
if n_wc >= max_wc
max_wc = n_wc;
end
end
wc = max_wc;
% initializing Hzon
Hzon = zeros(wc,n);
for i=1:n
% row inside Hzon
jrow = 0;
for j=1:size(col)
if col(j) == i
jrow = jrow + 1;
Hzon(jrow,i)= row(j);
end
end
end
% ----------------------------------------------------------------------------
%% hver_f.m %%
% The matrix Hver stores the lines of the matrix H where there are non-zero
% elements.
function [Hver, wr_vec, wr] = hver_f(H,k)
% Finding line and column positions for H(i,j) == 1
[row, col] = find(H == 1);
% vector with wr for all rows
wr_vec = zeros(1,k);
% determining wr
max_wr = 0;
85
for j=1:k
% number of 1s in a line
n_wr = 0;
for i=1:length(row)
if row(i) == j
n_wr = n_wr + 1;
end
end
wr_vec(j) = n_wr;
if n_wr >= max_wr
max_wr = n_wr;
end
end
wr = max_wr;
% initializing Hver
Hver = zeros(k,wr);
for j=1:k
% row inside Hzon
icol = 0;
for i=1:length(row)
if row(i) == j
icol = icol + 1;
Hver(j,icol)= col(i);
end
end
end
% ----------------------------------------------------------------------------
%% logSP_init_f.m %%
% log-SP algorithm initialization of Lc and Lq vectors.
function [Lc, Lq] = logSP_init_f(y,sigma,n,wc)
Lc = zeros(1,n);
Lq = zeros(wc,n);
for i=1:n
Lc(i) = (2*y(i))/(sigma^2);
for j=1:wc
Lq(j,i) = Lc(i);
86
end
end
% ----------------------------------------------------------------------------
%% logSP_Hstep_f.m %%
% Function to calculate horizontal step for log-SP algorithm.
function Lr = logSP_Hstep_f(Lq,Hzon,Hver,k,wr,wr_vec,wc_vec)
Lr = zeros(k,wr);
% line loop
for j=1:k
% column loop
for i=1:wr_vec(j)
alfa = 1;
sum_beta = 0;
% elements in the line loop
for l =1:wr_vec(j)
if(l ~= i)
col_Lq = Hver(j,l);
% loop inside Hzon column
for ll=1:wc_vec(col_Lq)
if (Hzon(ll,col_Lq) == j)
line_Lq = ll;
end
end
alfa = alfa*sign(Lq(line_Lq,col_Lq));
beta = abs(Lq(line_Lq,col_Lq));
sum_beta = sum_beta + alfa_f(beta);
end
end
Lr(j,i) = alfa*alfa_f(sum_beta);
end
end
% ----------------------------------------------------------------------------
%% Vstep_f.m %%
% Function that performs Vertical Step of LDPC decodification
function Lq = Vstep_f(Lr,Lc,Hzon,Hver,n,wc,wc_vec,wr_vec)
Lq = zeros(wc,n);
87
% column loop
for i=1:n
% line loop
for j=1:wc_vec(i)
sum_Lr = 0;
% elements in the column loop
for l=1:wc_vec(i)
if (j~=l)
line_Lr = Hzon(l,i);
for ll=1:wr_vec(line_Lr)
if (Hver(line_Lr,ll) == i)
col_Lr = ll;
end
end
sum_Lr = sum_Lr + Lr(line_Lr,col_Lr);
end
end
Lq(j,i) = Lc(i) + sum_Lr;
end
end
% ----------------------------------------------------------------------------
%% Qcalc_f.m %%
% Function that performs Vertical Step of LDPC decodification
function Q = Qcalc_f(Lr,Lc,Hzon,Hver,n,wc_vec,wr_vec)
Q = zeros(1,n);
for i=1:n
sum_Q = 0;
for j=1:wc_vec(i)
% elements in the column loop
line_Lr = Hzon(j,i);
for ll=1:wr_vec(line_Lr)
if (Hver(line_Lr,ll) == i)
col_Lr = ll;
end
end
sum_Q = sum_Q + Lr(line_Lr,col_Lr);
end
Q(i) = Lc(i) + sum_Q;
end
88
% ----------------------------------------------------------------------------
%% decision_f.m %%
% Function to calculate the decoded word.
function c_hat = decision_f(Q,n)
% decoded word
c_hat = zeros(1,n);
c_hat(Q < 0) = 1;
c_hat(Q >= 0) = 0;
% ----------------------------------------------------------------------------
%% synd_f.m %%
% Function that calculates the syndrome of the decoded word.
function synd = synd_f(c_hat, H)
% Transforming c_hat to GF(2) to perform matrix multiplication
gf_c_hat = gf(c_hat',2);
synd = H*gf_c_hat;
% ----------------------------------------------------------------------------
%% dec_SM_f.m %%
% Implementation of LDPC decoding algorithm log-SP.
% y: received word
% H: parity-check matrix
% iter: iteration number
function [c_hat, ok] = dec_SM_f(y,H,iter,n,k)
% number of iterations done by the loop
it = 0;
ok = 1;
while (ok ~= 0 && it < iter)
if (it == 0)
% finding Hzon
89
[Hzon, wc_vec, wc] = hzon_f(H,n);
%Hzon
% finding Hver
[Hver, wr_vec, wr] = hver_f(H,k);
%Hver
% initialization
[Lc, Lq] = SM_init_f(y,n,wc);
end
% Horizontal step
Lr = SM_Hstep_f(Lq,Hzon,Hver,k,wr,wr_vec,wc_vec);
% Vertical step
Lq = Vstep_f(Lr,Lc,Hzon,Hver,n,wc,wc_vec,wr_vec);
% Q calculation
Q = Qcalc_f(Lr,Lc,Hzon,Hver,n,wc_vec,wr_vec);
% Decision
c_hat = decision_f(Q,n);
% Syndrome
synd = synd_f(c_hat, H);
ok = sum(synd.x);
it = it + 1;
end
% ----------------------------------------------------------------------------
%% SM_init_f.m %%
% SM algorithm initialization of Lc and Lq vectors.
function [Lc, Lq] = SM_init_f(y,n,wc)
Lc = zeros(1,n);
Lq = zeros(wc,n);
for i=1:n
Lc(i) = y(i);
for j=1:wc
90
Lq(j,i) = Lc(i);
end
end
% ----------------------------------------------------------------------------
%% SM_Hstep_f.m %%
% Function to calculate horizontal step for log-SP algorithm.
function Lr = SM_Hstep_f(Lq,Hzon,Hver,k,wr,wr_vec,wc_vec)
Lr = zeros(k,wr);
% line loop
for j=1:k
% column loop
for i=1:wr_vec(j)
alfa = 1;
% first iteration
first = 0;
% elements in the line loop
for l=1:wr_vec(j)
if(i~=l)
col_Lq = Hver(j,l);
% loop inside Hzon clolumn
for ll=1:wc_vec(col_Lq)
if (Hzon(ll,col_Lq) == j)
line_Lq = ll;
end
end
alfa = alfa * sign(Lq(line_Lq,col_Lq));
beta = abs(Lq(line_Lq,col_Lq));
if first == 0
mim_beta = beta;
else
if beta < mim_beta
mim_beta = beta;
end
end
first = 1;
end
end
Lr(j,i)= alfa*mim_beta;
end
end
% ----------------------------------------------------------------------------
91
ANEXO B - Código-fonte dos arquivos desenvolvidos para a implementação em VHDL do
codificador e do decodificador dos códigos IE-LDPC construídos
# ----------------------------------------------------------------------------
-- Package that store the functions that performs sum and gives the minimum
-- value of two numbers.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
package rasc_pkg is
-- NOTE: I use to instead of downto for Lq_t e Lr_t to facilitate validation
-- using MATLAB.
-- LDPC dimensions
constant n_c : integer := 8;
constant k_c : integer := 4;
-- number of bit per value
constant bit_c : integer := 12;
constant zero_c : std_logic_vector(bit_c-1 downto 0):= conv_std_logic_vector(0,bit_c);
-- Hzon
constant nrow_Hzon_c : integer := k_c;
constant ncol_Hzon_c : integer := 4;
-- Hver
constant nrow_Hver_c : integer := n_c;
constant ncol_Hver_c : integer := 2;
type row_t is array(n_c-1 downto 0) of std_logic_vector(bit_c-1 downto 0);
-- Lq
type row_Hzon_t is array(0 to ncol_Hzon_c-1) of std_logic_vector(bit_c-1 downto 0);
type Lq_t is array(0 to k_c-1) of row_Hzon_t;
-- Hzon
type Hzon_matrix_t is array(1 to nrow_Hzon_c, 1 to ncol_Hzon_c) of integer;
92
-- Hzon matrix
constant Hzon_c : Hzon_matrix_t := (
(1,3,6,7),
(2,5,6,8),
(2,3,4,5),
(1,4,7,8)
);
-- Lr
type row_Hver_t is array(0 to ncol_Hver_c-1) of std_logic_vector(bit_c-1 downto 0);
type Lr_t is array(0 to n_c-1) of row_Hver_t;
-- Hver
type Hver_matrix_t is array(1 to nrow_Hver_c, 1 to ncol_Hver_c) of integer;
-- Hver matrix
constant Hver_c : Hver_matrix_t := (
(1,4),
(2,3),
(1,3),
(3,4),
(2,3),
(1,2),
(1,4),
(2,4)
);
-- LDPC encoder
function ldpc_enc_f(data_i: std_logic_vector(k_c-1 downto 0))
return std_logic_vector;
-- sum of two numbers
function sum_f(a_v: std_logic_vector(bit_c-1 downto 0);
b_v: std_logic_vector(bit_c-1 downto 0))
return std_logic_vector;
-- minimum of two numbers
function min_f(a_v: std_logic_vector(bit_c-1 downto 0);
b_v: std_logic_vector(bit_c-1 downto 0))
return std_logic_vector;
-- LDPC decision
function decision_f(a_v: std_logic_vector(bit_c-1 downto 0))
return std_logic;
end rasc_pkg;
93
package body rasc_pkg is
-- LDPC encoder
function ldpc_enc_f(data_i: std_logic_vector(k_c-1 downto 0))
return std_logic_vector is
variable data_v : std_logic_vector(n_c-1 downto 0);
variable aux_v : std_logic := '0';
-- message
data_v(0 to k_c-1) = data_i(0 to k_c-1);
aux_v := 0;
for j in k_c to n_c-1 loop
data_v(j) := 0;
for i in 1 to ncol_Hver_c loop
if Hver_c(j,i) /= 1 then
data_v(j) := data_v(j) xor data_i(Hver_c(j,i)-1);
end if;
end loop;
end loop;
-- data_v : encoded data
return data_v;
end ldpc_enc_f;
-- sum function
function sum_f(a_v : std_logic_vector(bit_c-1 downto 0);
b_v: std_logic_vector(bit_c-1 downto 0))
return std_logic_vector is
-- The factors have size of 12 bits
-- It is necessary to truncate the number when the result is bigger
-- than 127 or littler than -128.
-- maximum value: 127
-- minimum value: - 128
-- Bitwise operation is performed
variable res_v: std_logic_vector(bit_c-1 downto 0);
variable carry_v: std_logic_vector(bit_c-1 downto 0);
94
variable result_v: std_logic_vector(bit_c-1 downto 0);
variable underflow_v : std_logic;
begin
res_v(0) := a_v(0) xor b_v(0);
carry_v(0) := a_v(0) and b_v(0);
for j in 1 to 11 loop
carry_v(j) := (a_v(j) and b_v(j)) or (a_v(j) and carry_v(j-1)) or (b_v(j) and carry_v(j-1));
res_v(j) := a_v(j) xor b_v(j) xor carry_v(j-1);
end loop;
-- I have to use the predecessors, so it is to instead of downto.
-- carry_v(11) will signalized if there is overflow or underflow.
-- overflow: both positive and carry(msb) = '1'
-- underflow: both negative and carry(msb) xor carry(msb-1) = '1'
underflow_v := carry_v(11) xor carry_v(10);
-- overflow detection
if a_v(11) = '0' and b_v(11) = '0' and carry_v(10) = '1' then
-- 127 Remember that the four lsb are the fractional part
result_v := conv_std_logic_vector(2032,12);
-- underflow detection
elsif (a_v(11) = '1' and b_v(11) = '1') and underflow_v = '1' then
-- -128 Remember that the four lsb are the fractional part
result_v := conv_std_logic_vector(2048,12);
else
result_v := res_v;
end if;
return result_v;
end sum_f;
-- minimum value function
function min_f(a_v: std_logic_vector(bit_c-1 downto 0);
b_v: std_logic_vector(bit_c-1 downto 0))
return std_logic_vector is
-- integer values
variable a_int_v : integer range 0 to 2047;
variable b_int_v : integer range 0 to 2047;
-- minimum value
variable min_value_v : std_logic_vector(bit_c-1 downto 0);
begin
95
-- both positive
if a_v(11) = '0' and b_v(11) = '0' then
a_int_v := conv_integer(a_v(10 downto 0));
b_int_v := conv_integer(b_v(10 downto 0));
if a_int_v > b_int_v then
min_value_v := b_v;
else
min_value_v := a_v;
end if;
-- a < 0 and b >= 0
elsif a_v(11) = '1' and b_v(11) = '0' then
min_value_v := a_v;
-- a >= 0 and b < 0
elsif a_v(11) = '0' and b_v(11) = '1' then
min_value_v := b_v;
-- both negative
else
a_int_v := conv_integer(a_v(10 downto 0));
b_int_v := conv_integer(b_v(10 downto 0));
if a_int_v < b_int_v then
min_value_v := a_v;
else
min_value_v := b_v;
end if;
end if;
return min_value_v;
end min_f;
-- LDPC decision
function decision_f(a_v: std_logic_vector(bit_c-1 downto 0))
return std_logic is
-- result
variable res_v : std_logic;
begin
-- If a_v is positive, res_v = '1', otherwise, res_v = '0'
if a_v(bit_c-1) = '0' then
res_v := '1';
else
res_v := '0';
end if;
return res_v;
96
end function decision_f;
end package body rasc_pkg;
# ----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.numeric_std.all;
library ldpc_lp;
use ldpc_lp.rasc_pkg.all;
-- Encoder for an LDPC binary code.
entity ldpc_encoder_top is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
data_i : in std_logic_vector(k_c-1 downto 0);
data_o : out std_logic_vector(n_c-1 downto 0)
);
end ldpc_encoder_top;
-- The codeword is obtained by msg * H.
architecture rtl of ldpc_encoder_top is
begin
process(rst_i, mclk_i)
begin
if rst_i = '1' then
data_o <= (others => '0');
elsif mclk_i'event and mclk_i = '1' then
if en_i = '1' then
for j in n_c-1 downto 0 loop
data_o <= ldpc_enc_f(data_i);
end loop;
end if;
end if;
end process;
end rtl;
# ----------------------------------------------------------------------------
97
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This is the implementation of a ldpc decoder.
entity ldpc_decoder_top is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
-- input
new_word_i : in std_logic;
rx_i : in row_t;
-- output
dec_data_o : out std_logic_vector(n_c-1 downto 0)
);
end ldpc_decoder_top;
-- new_word_i : flag to indicate a incoming data.
-- rx_i : ldpc word. It is a array of n_c elements of bit_c bits.
-- It stores corresponds to values in the [-1,1] interval.
-- dec_data_o : decoded ldpc word.
-- This code version implemented a three-iteratin LDPC decoder.
architecture rtl of ldpc_decoder_top is
-- first iteration
component ldpc_first_iter_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
-- input
rx_i : in row_t;
new_word_i : in std_logic;
-- output
98
Lc_o : out row_t;
Lq_o : out Lq_t;
Lr_o : out Lr_t;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end component;
-- output signals for the inner iteration block
signal Lc_first_s : row_t;
signal Lq_first_s : Lq_t;
signal Lr_first_s : Lr_t;
-- inner iterations
component ldpc_middle_iter_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
-- input
new_word_i : in std_logic;
Lc_i : in row_t;
Lr_i : in Lr_t;
-- output
Lr_o : out Lr_t;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end component;
-- output for the last iteration block
signal Lc_inner_s : row_t;
signal Lq_inner_s : Lq_t;
signal Lr_inner_s : Lr_t;
-- last iteration
component ldpc_last_iter_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
-- input
99
new_word_i : in std_logic;
Lc_i : in row_t;
Lr_i : in Lr_t;
-- output
dec_data_o : out std_logic_vector(n_c-1 downto 0)
);
end component;
begin
-- first iteration
ldpc_first_iter_block_inst: ldpc_first_iter_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => en_i,
rx_i => rx_i,
new_word_i => new_word_i,
Lc_o => Lc_first_s,
Lq_o => open,
Lr_o => Lr_first_s,
dec_rx_o => open
);
-- inner iterations
ldpc_middle_iter_block_inst: ldpc_middle_iter_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => en_i,
new_word_i => new_word_i,
Lc_i => Lc_first_s,
Lr_i => Lr_first_s,
Lr_o => Lr_inner_s,
dec_rx_o => open
);
-- last iteration
ldpc_last_iter_block_inst: ldpc_last_iter_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => en_i,
new_word_i => new_word_i,
Lc_i => Lc_first_s,
100
Lr_i => Lr_inner_s,
dec_data_o => dec_data_o
);
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This block performs the first iteration of the ldpc decoder.
-- At the first clock pulse occurs Lc and Lq initialization.
-- At the second clock pulse happens Lr update
-- At the third clock pulse decision is performed.
entity ldpc_first_iter_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
-- input
rx_i : in row_t;
new_word_i : in std_logic;
-- output
Lc_o : out row_t;
Lq_o : out Lq_t;
Lr_o : out Lr_t;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end ldpc_first_iter_block;
-- new_word_i : flag to indicate a incoming data.
-- rx_i : ldpc word.
-- Lq_o : Lq matrix
-- Lr_o : Lr matrix
-- dec_rx_o : corrected ldpc word.
101
architecture rtl of ldpc_first_iter_block is
-- Lc vector initialization
component Lc_init_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
rx_i : in row_t;
Lc_o : out row_t
);
end component;
signal Lc_s : row_t;
-- Lq initialization
component Lq_init_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
rx_i : in row_t;
Lq_init_o : out Lq_t
);
end component;
signal Lq_s : Lq_t;
-- Lrji update
component Lr_calc_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lq_i : in Lq_t;
Lr_o : out Lr_t
);
end component;
signal Lr_s : Lr_t;
-- Decision block
component ldpc_decision_block is
port(
102
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lc_i : in row_t;
Lr_i : in Lr_t;
--valid_word_o : out std_logic;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end component;
-- LDPC control block
component ldpc_ctrl_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
new_word_i : in std_logic;
ctrl_pulse_o : out std_logic_vector(2 downto 0)
);
end component;
signal ctrl_pulse_s : std_logic_vector(2 downto 0) := (others => '0');
-- signal enable for the blocks
signal first_pulse_en, second_pulse_en, third_pulse_en : std_logic := '0';
begin
-- signal enables
first_pulse_en <= en_i and ctrl_pulse_s(0);
second_pulse_en <= en_i and ctrl_pulse_s(1);
third_pulse_en <= en_i and ctrl_pulse_s(2);
-- Lc initialization
Lc_init_block_inst: Lc_init_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => first_pulse_en,
rx_i => rx_i,
Lc_o => Lc_s
);
-- Lq initialization
Lq_init_block_inst: Lq_init_block
port map(
103
rst_i => rst_i,
mclk_i => mclk_i,
en_i => first_pulse_en,
rx_i => rx_i,
Lq_init_o => Lq_s
);
-- Lr update
Lr_calc_block_inst: Lr_calc_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => second_pulse_en,
Lq_i => Lq_s,
Lr_o => Lr_s
);
-- decision block
ldpc_decision_block_inst: ldpc_decision_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => third_pulse_en,
Lc_i => Lc_s,
Lr_i => Lr_s,
dec_rx_o => dec_rx_o
);
-- control block
ldpc_ctrl_block_inst: ldpc_ctrl_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => en_i,
new_word_i => new_word_i,
ctrl_pulse_o => ctrl_pulse_s
);
-- output signal
Lc_o <= Lc_s;
Lq_o <= Lq_s;
Lr_o <= Lr_s;
end rtl;
# ----------------------------------------------------------------------------
104
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This block performs the following iterations of the ldpc decoder.
-- At the first clock pulse occurs Lq update.
-- At the second clock pulse happens Lr update
-- At the third clock pulse decision is performed.
entity ldpc_middle_iter_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
-- input
new_word_i : in std_logic;
Lc_i : in row_t;
Lr_i : in Lr_t;
-- output
Lr_o : out Lr_t;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end ldpc_middle_iter_block;
-- new_word_i : flag to indicate a incoming data.
-- rx_i : ldpc word.
-- Lq_o : Lq matrix
-- Lr_o : Lr matrix
-- dec_rx_o : corrected ldpc word.
architecture rtl of ldpc_middle_iter_block is
-- Lq update
component Lq_calc_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lr_i : in Lr_t;
105
Lq_o : out Lq_t
);
end component;
signal Lq_s : Lq_t;
-- Lrji update
component Lr_calc_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lq_i : in Lq_t;
Lr_o : out Lr_t
);
end component;
signal Lr_s : Lr_t;
-- Decision block
component ldpc_decision_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lc_i : in row_t;
Lr_i : in Lr_t;
--valid_word_o : out std_logic;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end component;
-- LDPC control block
component ldpc_ctrl_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
new_word_i : in std_logic;
ctrl_pulse_o : out std_logic_vector(2 downto 0)
);
end component;
signal ctrl_pulse_s : std_logic_vector(2 downto 0) := (others => '0');
106
-- signal enable for the blocks
signal first_pulse_en, second_pulse_en, third_pulse_en : std_logic := '0';
begin
-- signal enables
first_pulse_en <= en_i and ctrl_pulse_s(0);
second_pulse_en <= en_i and ctrl_pulse_s(1);
third_pulse_en <= en_i and ctrl_pulse_s(2);
-- Lq update
Lq_calc_block_inst: Lq_calc_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => first_pulse_en,
Lr_i => Lr_i,
Lq_o => Lq_s
);
-- Lr update
Lr_calc_block_inst: Lr_calc_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => second_pulse_en,
Lq_i => Lq_s,
Lr_o => Lr_s
);
-- decision block
ldpc_decision_block_inst: ldpc_decision_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => third_pulse_en,
Lc_i => Lc_i,
Lr_i => Lr_s,
dec_rx_o => dec_rx_o
);
-- control block
ldpc_ctrl_block_inst: ldpc_ctrl_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
107
en_i => en_i,
new_word_i => new_word_i,
ctrl_pulse_o => ctrl_pulse_s
);
-- output signal
Lr_o <= Lr_s;
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This block performs the last iteration of the ldpc decoder.
-- At the first clock pulse occurs Lq update.
-- At the second clock pulse happens Lr update
-- At the third clock pulse decision is performed.
entity ldpc_last_iter_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
-- input
new_word_i : in std_logic;
Lc_i : in row_t;
Lr_i : in Lr_t;
-- output
dec_data_o : out std_logic_vector(n_c-1 downto 0)
);
end ldpc_last_iter_block;
-- new_word_i : flag to indicate a incoming data.
-- rx_i : ldpc word.
-- Lc_i : matrix that stores the initial value of rx_i
-- Lr_i : Lr matrix
108
-- dec_data_o : decoded ldpc word.
architecture rtl of ldpc_last_iter_block is
-- Lq update
component Lq_calc_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lr_i : in Lr_t;
Lq_o : out Lq_t
);
end component;
signal Lq_s : Lq_t;
-- Lrji update
component Lr_calc_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lq_i : in Lq_t;
Lr_o : out Lr_t
);
end component;
signal Lr_s : Lr_t;
-- Decision block
component ldpc_decision_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lc_i : in row_t;
Lr_i : in Lr_t;
--valid_word_o : out std_logic;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end component;
-- LDPC control block
109
component ldpc_ctrl_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
new_word_i : in std_logic;
ctrl_pulse_o : out std_logic_vector(2 downto 0)
);
end component;
-- ldpc control signals
signal ctrl_pulse_s : std_logic_vector(2 downto 0) := (others => '0');
-- signal enable for the blocks
signal first_pulse_en, second_pulse_en, third_pulse_en : std_logic := '0';
-- decoded data
signal dec_data_s : std_logic_vector(n_c-1 downto 0):= (others => '0');
begin
-- signal enables
first_pulse_en <= en_i and ctrl_pulse_s(0);
second_pulse_en <= en_i and ctrl_pulse_s(1);
third_pulse_en <= en_i and ctrl_pulse_s(2);
-- Lq update
Lq_calc_block_inst: Lq_calc_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => first_pulse_en,
Lr_i => Lr_i,
Lq_o => Lq_s
);
-- Lr update
Lr_calc_block_inst: Lr_calc_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => second_pulse_en,
Lq_i => Lq_s,
Lr_o => Lr_s
);
-- decision block
110
ldpc_decision_block_inst: ldpc_decision_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => third_pulse_en,
Lc_i => Lc_i,
Lr_i => Lr_s,
dec_rx_o => dec_data_s
);
-- control block
ldpc_ctrl_block_inst: ldpc_ctrl_block
port map(
rst_i => rst_i,
mclk_i => mclk_i,
en_i => en_i,
new_word_i => new_word_i,
ctrl_pulse_o => ctrl_pulse_s
);
-- decoded data
dec_data_o <= dec_data_s;
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This block performs the initialization of Lc matrix.
entity Lc_init_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
rx_i : in row_t;
Lc_o : out row_t
);
end Lc_init_block;
111
-- rx_i : incoming data
-- Lc_o : matrix Lc
architecture rtl of Lc_init_block is
begin
process(rst_i,mclk_i)
begin
if rst_i = '1' then
Lc_o <= (others => (others => '0'));
elsif mclk_i'event and mclk_i = '1' then
if en_i = '1' then
for j in 0 to n_c-1 loop
Lc_o(j) <= rx_i(j);
end loop;
end if;
end if;
end process;
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
entity Lq_init_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
rx_i : in row_t;
Lq_init_o : out Lq_t
);
end Lq_init_block;
architecture rtl of Lq_init_block is
-- Lq array
signal Lq_init_s : Lq_t;
112
begin
process(rst_i,mclk_i)
variable value_col_v : integer;
begin
if rst_i = '1' then
Lq_init_s <= (others => (others => (others => '0')));
elsif mclk_i'event and mclk_i = '1' then
if en_i = '1' then
for j in 1 to k_c loop
for i in 1 to ncol_Hzon_c loop
value_col_v := Hzon_c(j,i);
Lq_init_s(j-1)(i-1) <= rx_i(value_col_v-1);
end loop;
end loop;
end if;
end if;
end process;
Lq_init_o <= Lq_init_s;
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This block performs the update of Rij.
-- Vertical step
entity Lr_calc_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lq_i : in Lq_t;
Lr_o : out Lr_t
);
end Lr_calc_block;
-- Lq_i: matrix that stores Qij values
113
-- Lr_i: matrix that stores Rij values
architecture rtl of Lr_calc_block is
-- Lrji = min(Lqji) excluding Lqji for the corresponding (j,i)
function lr_update_f(Lq_v : Lq_t)
return Lr_t is
variable min_value_v : std_logic_vector(bit_c-1 downto 0);
variable row_Hver_v, col_Hver_v : integer;
variable Lr_v : Lr_t;
begin
-- It is necessary to walk through the row, excluding the value of (j,i)
for j in 1 to k_c loop
for i in 1 to ncol_Hzon_c loop
-- Minimum value initialization
if i /= 1 then
min_value_v := Lq_v(j-1)(0);
else
min_value_v := Lq_v(j-1)(1);
end if;
-- Getting the minimum value
for l in 1 to ncol_Hzon_c loop
if l /= i then
min_value_v := min_f(min_value_v,Lq_v(j-1)(l-1));
else
min_value_v := min_value_v;
end if;
end loop;
-- Assigning Rji
row_Hver_v := Hzon_c(j,i);
-- The column is searched
col_Hver_v := 0;
for k in 1 to ncol_Hver_c loop
if Hver_c(row_Hver_v,k) = j then
col_Hver_v := k;
end if;
end loop;
114
Lr_v(row_Hver_v-1)(col_Hver_v-1) := min_value_v;
end loop;
end loop;
return Lr_v;
end lr_update_f;
begin
process(rst_i,mclk_i)
variable value_col_v : integer;
begin
if rst_i = '1' then
Lr_o <= (others => (others => (others => '0')));
elsif mclk_i'event and mclk_i = '1' then
if en_i = '1' then
Lr_o <= lr_update_f(Lq_i);
end if;
end if;
end process;
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This block performs the update of Rij.
-- Vertical step
entity Lq_calc_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
Lq_i : in Lq_t;
Lr_i : in Lr_t;
Lq_o : out Lq_t
);
115
end Lq_calc_block;
-- Lq_i: matrix that stores Qij values
-- Lr_i: matrix that stores Rij values
architecture rtl of Lq_calc_block is
signal Lq_s : Lq_t;
-- function
function lq_update_f(Lr_v: Lr_t; iLq_v : Lq_t)
return Lq_t is
variable Lq_v : Lq_t;
variable row_Hzon_v, col_Hzon_v : integer;
variable sum_value_v : std_logic_vector(bit_c-1 downto 0);
variable old_Lq_value_v, new_Lq_value_v : std_logic_vector(bit_c-1 downto 0);
begin
for j in 1 to n_c loop
for i in 1 to ncol_Hver_c loop
-- It is necessary to walk through the row, excluding the value of (i,j).
-- sum value initialization
sum_value_v := conv_std_logic_vector(0,bit_c);
-- Summing the values
for l in 1 to ncol_Hver_c loop
if l /= i then
sum_value_v := sum_f(sum_value_v,Lr_v(j-1)(l-1));
else
sum_value_v := sum_value_v;
end if;
-- Discovering the place to write at Lq
row_Hzon_v := Hver_c(j,i);
-- The Hzon row is searched in order to find the value of i
for k in 1 to ncol_Hzon_c loop
if Hzon_c(row_Hzon_v,k) = j then
col_Hzon_v := k;
end if;
end loop;
-- The Lq value is read and the updated
116
old_Lq_value_v := iLq_v(row_Hzon_v-1)(col_Hzon_v-1);
new_Lq_value_v := sum_f(old_Lq_value_v,sum_value_v);
Lq_v(row_Hzon_v-1)(col_Hzon_v-1) := new_Lq_value_v;
end loop;
end loop;
end loop;
return Lq_v;
end Lq_update_f;
begin
process(rst_i,mclk_i)
begin
if rst_i = '1' then
Lq_s <= (others => (others => (others => '0')));
elsif mclk_i'event and mclk_i = '1' then
if en_i = '1' then
Lq_s <= lq_update_f(Lr_i, Lq_i);
end if;
end if;
end process;
Lq_o <= Lq_s;
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library ldpc_lib;
use ldpc_lib.rasc_pkg.all;
-- This block sum up all values of Rji por each colunm and decides what
-- is the new value the ldpc vector.
-- Q(j) = Lc(j) + sumj(Rji)
-- if L(Qj) < 0 c(j) = 1 else c(j) = 0
entity ldpc_decision_block is
port(
rst_i : in std_logic;
117
mclk_i : in std_logic;
en_i : in std_logic;
-- input
Lc_i : in row_t;
Lr_i : in Lr_t;
-- output
--valid_word_o : out std_logic;
dec_rx_o : out std_logic_vector(n_c-1 downto 0)
);
end ldpc_decision_block;
-- Lc_i : matrix that stores the values of rx_i.
-- Lr_i : Lr matrix.
-- valid_word_o : flag that indicates if dec_rx_o is a valid word.
-- dec_rx_o : corrected ldpc word.
architecture rtl of ldpc_decision_block is
-- vector used to perform the decision oof the new value of rx_i
signal Q_s : row_t;
-- function
function Q_update_f(Lc_v: row_t; Lr_v: Lr_t)
return row_t is
variable Q_v : row_t;
variable sum_value_v : std_logic_vector(bit_c-1 downto 0);
begin
for j in 1 to n_c loop
-- It is necessary to walk through the row and sum up all values.
sum_value_v := conv_std_logic_vector(0,bit_c);
-- Summing the values
for k in 1 to ncol_Hver_c loop
sum_value_v := sum_f(sum_value_v,Lr_v(j-1)(k-1));
end loop;
-- Q(j) value
Q_v(j-1) := sum_f(sum_value_v,Lc_v(j-1));
end loop;
118
return Q_v;
end Q_update_f;
begin
-- Calculating Q(j)
process(rst_i,mclk_i)
begin
if rst_i = '1' then
Q_s <= (others => (others => '0'));
dec_rx_o <= (others => '0');
elsif mclk_i'event and mclk_i = '1' then
if en_i = '1' then
Q_s <= Q_update_f(Lc_i, Lr_i);
-- decision
for j in 1 to n_c loop
dec_rx_o(j-1) <= decision_f(Q_s(j-1));
end loop;
end if;
end if;
end process;
-- Decision
--process(Q_s)
--begin
-- for j in 1 to n_c loop
-- if min_f(zero_c,Q_s(j-1)) = Q_s(j-1) then
-- dec_rx_o(j-1) <= '1';
-- else
-- dec_rx_o(j-1) <= '0';
-- end if;
-- end loop;
--end process;
-- syndrome calculation
end rtl;
# ----------------------------------------------------------------------------
library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.numeric_std.all;
119
-- This block performs the update of Rij.
-- Vertical step
entity ldpc_ctrl_block is
port(
rst_i : in std_logic;
mclk_i : in std_logic;
en_i : in std_logic;
new_word_i : in std_logic;
ctrl_pulse_o : out std_logic_vector(2 downto 0)
);
end ldpc_ctrl_block;
-- new_word_i : new incoming data
-- ctrl_pulse_o(0) : first pulse
-- For first iteration: Lc and Lq initialization
-- For following iterations: Lq update
-- ctrl_pulse_o(1) : second pulse
-- Lr update
-- ctrl_pulse_o(2) : third pulse
-- Q update and new vector decision
architecture rtl of ldpc_ctrl_block is
-- state machine that controls the data propagation
type control_t is (idle_st, pulse_1st_st, pulse_2nd_st, pulse_3rd_st);
signal pr_control_mq, nx_control_mq: control_t;
begin
process(pr_control_mq, new_word_i)
begin
case pr_control_mq is
when idle_st =>
if new_word_i = '1' then
nx_control_mq <= pulse_1st_st;
else
nx_control_mq <= idle_st;
end if;
when pulse_1st_st =>
nx_control_mq <= pulse_2nd_st;
when pulse_2nd_st =>
120
nx_control_mq <= pulse_3rd_st;
when pulse_3rd_st =>
if new_word_i = '1' then
nx_control_mq <= pulse_1st_st;
else
nx_control_mq <= idle_st;
end if;
when others =>
nx_control_mq <= idle_st;
end case;
end process;
process(rst_i,mclk_i)
begin
if rst_i = '1' then
pr_control_mq <= idle_st;
elsif mclk_i'event and mclk_i = '1' then
if en_i = '1' then
pr_control_mq <= nx_control_mq;
end if;
end if;
end process;
-- Flags to signalize the pulse in which pulse clock the block is working.
-- first pulse
ctrl_pulse_o(0) <= '1' when pr_control_mq = pulse_1st_st else
'0';
-- second pulse
ctrl_pulse_o(1) <= '1' when pr_control_mq = pulse_2nd_st else
'0';
-- third pulse
ctrl_pulse_o(2) <= '1' when pr_control_mq = pulse_3rd_st else
'0';
end rtl;
# ----------------------------------------------------------------------------
121
ANEXO C – Código-fonte dos arquivos utilizados na validação da simulação dos codificadores e
decodificadores implementados em VHDL.
% ---------------------------------------------------------------------------
% min-sum ldpc decoder
function res = min_sum_ldpc_dec(rx_aux,H);
%% Files
% Lc
fid_Lc = fopen('print_Lc.txt','w');
% Lr
fid_Lr = fopen('print_Lr_tb.txt','w');
fid1_Lr = fopen('print_Lr_hex.txt','w');
% Lq
fid_Lq = fopen('print_Lq_tb.txt','w');
fid1_Lq = fopen('print_Lq_hex.txt','w');
% data output
fid_dout = fopen('decoded_data.txt','w');
fid1_dout = fopen('Q_values_hex.txt','w');
%% Truncating rx
rx = truncate_f(rx_aux);
%%
% rx: received data
% H: sparse matrix
% matrix dimensions
[nrow,ncol] = size(H);
% number of iterations
iter = 1;
% i -> used for colunms
% j -> used for rows
% The matrices Hrow and Hcol are generated from the matrix H.
122
% Hzon -> horizontal step
% Hzon stores the colunm values for each row of H.
% Hzon has dimension ncol x nº1per_row
% Hver -> vertical step
% Hver stores the row values for each colunm of H.
% Hver has dimension nrow x nº1per_col
% Hver and Hzon dimensions depend on the number of 1s per colunm and row.
% Generating Hzon e Hver.
Hzon = hzon_f(H);
Hver = hver_f(H);
[nrow_Hzon,ncol_Hzon] = size(Hzon);
[nrow_Hver,ncol_Hver] = size(Hver);
Lc = zeros(1,ncol);
%% Initialization of Lc(i)
for i = 1:ncol
Lc(i) = rx(i);
end
printf_Lc_matrix_f(rx,fid_Lc);
%% Initialization of Qij
% Lqij = Lci for each i
Lq = zeros(nrow,ncol_Hzon);
for j = 1:nrow % row
for i = 1:ncol_Hzon % colunm
% colunm value is stored at the row of Hver
value_col = Hzon(j,i);
Lq(j,i) = Lc(value_col);
Q(j,i) = Lc(value_col);
end
end
% Imprimo em um arquivo para comparar com a simulação em VHDL.
printf_Lq_init_f(Lq,nrow,ncol_Hzon,fid_Lq,fid1_Lq);
fprintf(fid_Lq,'\n\n\n');
fprintf(fid1_Lq,'\n\n\n');
123
%% Calculation of Rij
% Lrij = min(Lqij), excluding Lqij for the corresponding (i,j).
Lr = zeros(ncol,ncol_Hver);
Lr = Lr_update_f(Lq,Hzon,Hver,nrow,ncol,ncol_Hzon,ncol_Hver,fid_Lr,fid1_Lr);
fprintf(fid_Lr,'\n\n\n');
fprintf(fid1_Lr,'\n\n\n');
%% Update of Q
% Q = Lc
%Q = Lc + sum(Lrij)
Q = Q_update_f(Lc,Lr,ncol,ncol_Hver,fid_dout,fid1_dout)
fprintf(fid_dout,'\n\n\n');
fprintf(fid1_dout,'\n\n\n');
%% Following iterations
for it = 1:iter
%% Calculation of Qij
Lq = Lq_update_f(Lq,Lr,Hzon,Hver,nrow,ncol,ncol_Hzon,ncol_Hver,fid_Lq,fid1_Lq);
fprintf(fid_Lq,'\n\n\n');
fprintf(fid1_Lq,'\n\n\n');
%% Calculation of Rij
Lr = Lr_update_f(Lq,Hzon,Hver,nrow,ncol,ncol_Hzon,ncol_Hver,fid_Lr,fid1_Lr);
fprintf(fid_Lr,'\n\n\n');
fprintf(fid1_Lr,'\n\n\n');
%% Update of Q
Q = Q_update_f(Lc,Lr,ncol,ncol_Hver,fid_dout,fid1_dout);
fprintf(fid_dout,'\n\n\n');
fprintf(fid1_dout,'\n\n\n');
end
res = Lq;
%% Closing the files
fclose(fid_Lc);
124
fclose(fid_Lr);
fclose(fid1_Lr);
fclose(fid_Lq);
fclose(fid1_Lq);
fclose(fid_dout);
fclose(fid1_dout);
% ----------------------------------------------------------------------------
function rx_o = truncate_f(rx)
% Função que trunca um valor real para a representação mais próxima em um
% número binário de 12 bits.
% A representação armazena valores no intervalor [-128,127].
% A parte fracionária tem precisão mínima de 1/8 = 0.0625
% O valor são arredondados para baixo.
% Exemplo: 0,7 -> valor mais próximo: 0.5 + 0.125 + 0.0625 = 0.6875.
[a,n] = size(rx);
rx_o = zeros(1,n);
%%
for j = 1:n
%% Verifico se o número está no intervalo [-128,127]
if rx(j) >= -128 && rx(j) <= 127
real_number = rx(j);
else
if real_number > 127
real_number = 127;
else
real_number = -128;
end
end
%% Sinal
% O bit mais significativo será 1, se o número for negativo, ou 0, caso
% contrário.
if real_number >= 0
bit11 = 0;
125
else
bit11 = 1;
end
%% Parte Inteira
if bit11 == 0
% positive value: arrendondo pra cima
int_value = floor(real_number);
else
% negative value: arredondo pra baixo
int_value = ceil(real_number);
end
%% Parte Fracionária
frac_part = abs(real_number) - abs(int_value);
% Verifico em qual intervalo a parte fracionária se localiza.
if frac_part >= 0 && frac_part < 0.0625
frac_value = 0;
else
if frac_part >= 0.0625 && frac_part < 0.125
frac_value = 0.0625;
elseif frac_part >= 0.125 && frac_part < 0.1875
frac_value = 0.125;
elseif frac_part >= 0.1875 && frac_part < 0.25
frac_value = 0.1875;
elseif frac_part >= 0.25 && frac_part < 0.3125
frac_value = 0.25;
elseif frac_part >= 0.3125 && frac_part < 0.375
frac_value = 0.3125;
elseif frac_part >= 0.375 && frac_part < 0.4375
frac_value = 0.375;
elseif frac_part >= 0.4375 && frac_part < 0.5
frac_value = 0.4375;
elseif frac_part >= 0.5 && frac_part < 0.5625
frac_value = 0.5;
elseif frac_part >= 0.5625 && frac_part < 0.625
frac_value = 0.5625;
elseif frac_part >= 0.625 && frac_part < 0.6875
frac_value = 0.625;
elseif frac_part >= 0.6875 && frac_part < 0.75
frac_value = 0.6875;
elseif frac_part >= 0.75 && frac_part < 0.8125
frac_value = 0.75;
elseif frac_part >= 0.8125 && frac_part < 0.875
frac_value = 0.8125;
126
elseif frac_part >= 0.875 && frac_part < 0.9375
frac_value = 0.875;
else
frac_value = 0.9375;
end
%% Valor Final
if bit11 == 0
value = int_value + frac_value;
else
value = (int_value - frac_value);
end
rx_o(j) = value;
end
% ----------------------------------------------------------------------------
% This function generates a matrix that stores the colunm values for each
% row.
function Hzon = hzon_f(H);
% matrix dimensions
[nrow,ncol] = size(H);
for j = 1:nrow
ihzon = 1;
for i = 1:ncol
if H(j,i) == 1
% the column value is stored
Hzon(j,ihzon) = i;
ihzon = ihzon + 1;
end
end
end
% ----------------------------------------------------------------------------
% This function generates a matrix that stores the colunm values for each
% row.
function Hver = hver_f(H);
127
% matrix dimensions
[nrow,ncol] = size(H);
for i = 1:ncol
iver = 1;
for j = 1:nrow
if H(j,i) == 1
% the column value is stored
Hver(i,iver) = j;
iver = iver + 1;
end
end
end
% ----------------------------------------------------------------------------
function printf_Lc_matrix_f(rx,fid_Lc)
[nrow, ncol] = size(rx);
fprintf(fid_Lc,'rx_i <= (\n');
for j = 1:ncol
s_bin = real2bin_f(rx(j));
if j == ncol
fprintf(fid_Lc,' %d => "%s"\n', j-1, s_bin);
else
fprintf(fid_Lc,' %d => "%s",\n', j-1, s_bin);
end
end
fprintf(fid_Lc,');\n');
% ----------------------------------------------------------------------------
function printf_Lq_init_f(Lq,nrow,ncol_Hzon,fid_Lq,fid1_Lq)
% Imprimo em um arquivo para simular a entrado do bloco Lr_calc_block.vhd
for j = 1:nrow % row
for i = 1:ncol_Hzon % colunm
if j == nrow && i == ncol_Hzon
% binary array
s_bin = real2bin_f(Lq(j,i));
fprintf(fid_Lq,' Lq_i(%d)(%d) => "%s" \n',j-1, i-1, s_bin);
else
128
% binary array
s_bin = real2bin_f(Lq(j,i));
fprintf(fid_Lq,' Lq_i(%d)(%d) => "%s", \n',j-1, i-1, s_bin);
end
end
end
% hexadecimal values
for j = 1:nrow % row
for i = 1:ncol_Hzon % colunm
% to hexadecimal convertion
s_bin = real2bin_f(Lq(j,i));
dec_value = bin2dec(s_bin);
hex_value = dec2hex(dec_value,3);
fprintf(fid1_Lq,'%s ',hex_value);
end
fprintf(fid1_Lq,'\n');
end
% ----------------------------------------------------------------------------
% Calculation of Rij
% Lrij = min(Lqij), excluding Lqij for the corresponding (i,j).
function Lr = Lr_update_f(Lq,Hzon,Hver,nrow,ncol,ncol_Hzon,ncol_Hver,fid_Lr,fid1_Lr)
betaij = abs(Lq);
alfaij = sign(Lq);
% Lrij = min(Lqij), excluding Lqij for the corresponding (i,j).
for j = 1:nrow
for i = 1:ncol_Hzon
% It is necessary to walk through the row, excluding the value of
% (i,j).
% Minimum value initialization
if i ~= 1
min_value = betaij(j,1);
signal = alfaij(j,1);
else
min_value = betaij(j,2);
signal = alfaij(j,2);
end
% Getting the modulus of the minimum value
for l = 1:ncol_Hzon
if l ~= i
if min_value > betaij(j,l)
min_value = betaij(j,l);
129
end
end
signal = signal * alfa(j,l);
end
% Assigning Rij
row_Hver = Hzon(j,i);
% the column is searched
col_Hver = 0;
for k = 1:ncol_Hver
if Hver(row_Hver,k) == j;
%col_Hver = Hver(row_Hver,k)
col_Hver = k;
end
end
Lr(row_Hver,col_Hver) = signal * min_value;
end
end
% The values of the matrix Lr is printed in a file.
for j = 1:ncol
for i = 1:ncol_Hver
s_bin = real2bin_f(Lr(j,i));
fprintf(fid_Lr,' Lr_i(%d)(%d) <= "%s";\n',j-1,i-1,s_bin);
end
end
% hex values file
for j = 1:ncol
for i = 1:ncol_Hver
s_bin = real2bin_f(Lr(j,i));
dec_value = bin2dec(s_bin);
hex_value = dec2hex(dec_value,3);
fprintf(fid1_Lr,'%s ',hex_value);
end
fprintf(fid1_Lr,'\n');
end
% ----------------------------------------------------------------------------
% Q update
function Q = Q_update_f(Lc,Lr,ncol,ncol_Hver,fid_dout,fid1_dout)
dec_data = zeros(1,ncol);
% Q = Lc
130
%Q = Lc + sum(Lrij)
for j = 1:ncol
% percorro a linha
Qsum_value = 0;
for k = 1:ncol_Hver
Qsum_value = Qsum_value + Lr(j,k);
end
Q(j) = Lc(j) + Qsum_value;
end
for j = 1:ncol
if Q(j) >= 0
dec_data(j) = 1;
else
dec_data(j) = 0;
end
end
% Imprimindo os dados
for j = 1:ncol
fprintf(fid_dout,'%d',dec_data(j));
end
for j = 1:ncol
s_bin = real2bin_f(Q(j));
dec_value = bin2dec(s_bin);
hex_value = dec2hex(dec_value,3);
fprintf(fid1_dout,'%s ',hex_value);
end
% ----------------------------------------------------------------------------
function Lq = Lq_update_f(Lq,Lr,Hzon,Hver,nrow,ncol,ncol_Hzon,ncol_Hver,fid_Lq,fid1_Lq)
for j = 1:ncol
for i = 1:ncol_Hver
% It is necessary to walk through the row, excluding the value of
% (i,j).
% sum value initialization
sum_value = 0;
% Summing the values
for l = 1:ncol_Hver
if l ~= i
sum_value = sum_value + Lr(j,l);
else
sum_value = sum_value;
end
131
end
% Discovering the place to write at Lq
row_Hzon = Hver(j,i);
% the Hzon row is searched in order to find the value of i
for k = 1:ncol_Hzon
if Hzon(row_Hzon,k) == j
col_Hzon = k;
end
end
% The Lq value is read and then updated
old_Lq_value = Lq(row_Hzon,col_Hzon);
new_Lq_value = old_Lq_value + sum_value;
Lq(row_Hzon,col_Hzon) = new_Lq_value;
end
end
Lq
% The values of the matrix Lq is printed in a file.
for j = 1:nrow
for i = 1:ncol_Hzon
s_bin = real2bin_f(Lq(j,i));
fprintf(fid_Lq,' Lq_i(%d)(%d) <= "%s";\n',j-1,i-1,s_bin);
end
end
% hex values file
for j = 1:nrow
for i = 1:ncol_Hzon
s_bin = real2bin_f(Lq(j,i));
dec_value = bin2dec(s_bin);
hex_value = dec2hex(dec_value,3);
fprintf(fid1_Lq,'%s ',hex_value);
end
fprintf(fid1_Lq,'\n');
end
% ----------------------------------------------------------------------------