PCI Express em FPGAs da série V da Intel: recursos básicos de interface e recursos principais de hardware

Introdução


A interface PCI Express ou PCIe, familiar a muitos, já estava disponível para desenvolvedores de sistemas FPGA quando estava começando a se espalhar na tecnologia digital. Nesse momento, havia uma solução na qual o núcleo do software era conectado a um microcircuito externo de nível físico [ 5 ]. Isso possibilitou a criação de uma linha PCIe de pista única a uma velocidade de 2,5 gigatransações por segundo. Além disso, graças ao desenvolvimento de tecnologias, a camada física da interface migrou para os blocos de hardware PCIe dentro dos próprios FPGAs; o número de canais possíveis aumentou para 8 e, em vários novos microcircuitos - para 16; Seguindo padrões modernos, as possíveis taxas de transferência de dados aumentaram.

Ao mesmo tempo, ainda é difícil encontrar materiais auxiliares para trabalhar com os núcleos de hardware dos FPGAs modernos em fontes no idioma russo; não há muita informação disponível na própria interface PCIe. O guia para núcleos de hardware PCI Express implica que o desenvolvedor já se familiarizou com o padrão e entende os conceitos básicos da transferência de dados entre o dispositivo e um computador pessoal (PC). No entanto, a abundância de informações no próprio padrão PCIe não entende imediatamente quais etapas devem ser tomadas para transferir com êxito os dados do dispositivo para a memória do PC ou vice-versa. Para obter uma imagem mais completa, uma parte considerável da informação deve ser coletada pouco a pouco de várias fontes. Para desenvolvedores de sistemas Intel FPGA, a dificuldade também éque a maioria dos materiais e artigos disponíveis descreve o trabalho com núcleos de hardware Xilinx FPGA.

Neste artigo, o autor tentará falar sobre o que o designer do sistema FPGA precisa saber para trabalhar com a interface PCI Express; considerará os recursos do trabalho com os núcleos de hardware PCI Express FPGAs da série V da Intel na versão Avalon-ST.

Níveis PCIe e tipos de pacotes


Apesar de o PCI Express ser frequentemente chamado de barramento, essa interface é uma rede de dispositivos conectados por grupos de canais duplex serial. A rede PCI Express em si consiste em vários nós principais: a raiz (raiz), o ponto final (ponto final) e o roteador (comutador) (Figura 1). Para transferir dados apenas entre dois dispositivos, basta ter uma raiz e um terminal. No caso de PCs modernos, a raiz da rede está localizada em um substrato junto com os núcleos do processador central. Independentemente de onde a raiz do PCIe esteja localizada, ela está associada à memória do sistema.


Figura 1 - Rede PCIe

O protocolo de transferência de dados PCIe é dividido em três camadas: a camada de transação, a camada de enlace de dados e a camada física. Os dados da interface são transmitidos na forma de pacotes. Uma visão generalizada dos pacotes é mostrada na Figura 2.


Figura 2 - Uma visão generalizada dos pacotes PCIe

No nível da transação, qualquer pacote (TLP) consiste em pelo menos um cabeçalho. Dependendo do tipo de pacote, o cabeçalho pode ser seguido por dados - o conteúdo útil do pacote. Uma soma de verificação adicional também pode ser adicionada no final do pacote. Existem os seguintes tipos principais de pacotes no nível da transação (tabela 1):

Tabela 1 - Tipos de pacotes no nível da transação
Não. P.Vista do pacoteNome do tipo de embalagem de acordo com a especificação
1 1Pedido de leitura de memóriaPedido de leitura de memória
2Pedido de Gravação de MemóriaPedido de gravação na memória
3Pedido de leitura de espaço de E / SPedido de Leitura de E / S
4Pedido de gravação de espaço de E / SSolicitação de gravação de E / S
5Ler solicitação de configuraçãoSolicitação de leitura de configuração
6Gravar solicitação de configuraçãoPedido de Gravação de Configuração
7Resposta de leituraConclusão
8mensagemmensagem

Na camada de link, um número de sequência de pacotes e uma soma de verificação de link são adicionados a cada pacote no nível da transação. A camada de enlace de dados também forma seus próprios tipos de pacotes (DLLP), que incluem (tabela 2):

Tabela 2 - Tipos de pacotes de enlace de dados
Não. P.Vista do pacoteNome do tipo de embalagem de acordo com a especificação
1 1Confirmação de pacote no nível de transaçãoTLP Ack
2Rejeição de pacote no nível de transaçãoTLP Nack
3Gerenciamento de energiaGerenciamento de energia
4Controle de fluxo de dadosControle de fluxo

Finalmente, a camada física complementa os pacotes com símbolos do início e do fim dos pacotes, que são emprestados do padrão IEEE 802.3. Para pacotes no nível da transação, os símbolos K27.7 e K29.7 são usados, respectivamente; para pacotes de enlace de dados, símbolos K28.2 e K29.7.
Ao trabalhar com núcleos de hardware FPGA, o desenvolvedor precisa formar apenas pacotes no nível da transação; pacotes de camada física e de canal são formados por blocos de kernel.

Roteamento de pacotes em nível de transação


No total, diferentes tipos de pacotes podem chegar do remetente ao destinatário de três maneiras:

  • roteamento para o endereço;
  • Roteamento de ID
  • roteamento indireto.

O relacionamento entre o método de roteamento e o tipo de pacote no nível da transação é apresentado na Tabela 3.

Tabela 3 - Correspondência do método de roteamento e tipo de pacote
№p
1.
I/O I/O
2.
ID.

3ID

.


Cada nó de extremidade possui seu próprio espaço de configuração, onde estão localizados vários registros de instruções e status. Entre eles estão o Base Address Register ou BAR. Ao inicializar os terminais, o BIOS ou sistema operacional varre a BAR dos terminais para determinar quanta memória e espaço são necessários para cada terminal. Em seguida, em cada BAR ativa, o endereço inicial da parte alocada da memória do sistema é gravado. Como resultado, o terminal adquire um endereço para o qual as solicitações apropriadas podem ser enviadas. Normalmente, no ponto final, um mapa de registro é formado, vinculado às áreas de memória alocadas.

Além disso, cada nó de extremidade, ou melhor, o dispositivo lógico interno, obtém seu identificador exclusivo, que consiste em três partes: número do barramento, número do dispositivo, número do dispositivo lógico (função).

Dessa maneira, o sistema possui informações suficientes para se comunicar com o terminal. No entanto, a transmissão de dados usando consultas na BAR apresenta baixo desempenho. Em primeiro lugar, para uma BAR de 32 bits de largura, o tamanho da solicitação utilizável é limitado a uma palavra dupla (DWORD); para uma BAR de 64 bits, duas palavras duplas. Em segundo lugar, cada solicitação ocorre com a participação do processador central. Para reduzir a carga no processador central e aumentar o tamanho de cada pacote, é necessário que o nó de extremidade mova os dados independentemente para ou da memória do sistema. Para fazer isso, o terminal deve saber em quais endereços de memória do sistema ele pode gravar ou ler dados.

Dado o exposto, o esquema geral de transferência de dados entre o terminal e a memória do sistema pode ser representado da seguinte maneira:

  1. o driver do terminal aloca buffers na memória do sistema para gravar dados;
  2. o driver forma na memória do sistema um conjunto de endereços e tamanhos de buffer - descritores de buffer para gravação de dados;
  3. o driver do terminal grava o endereço do conjunto de descritores nos registros do dispositivo associados às áreas BAR;
  4. o driver do terminal programa os registros de controle de transferência de dados associados às áreas BAR;
  5. o terminal envia uma solicitação para ler a memória do sistema para obter um conjunto de descritores para gravar na memória do sistema;
  6. o terminal envia solicitações de gravação para a memória do sistema e preenche os buffers de armazenamento;
  7. / , , , ;
  8. PCIe.


No estágio em que o driver configura os registros do terminal, dependendo do tipo de espaço de endereço associado à BAR, o terminal receberá uma solicitação de gravação na memória (Figura 3) ou uma solicitação de gravação no espaço de E / S. Se o driver ler um registro durante a configuração do registro, o terminal também receberá as solicitações de leitura correspondentes (Figura 4).

imagem
Figura 3 - Exemplo de uma solicitação para gravar na memória 1 DW de comprimento Figura 4 - Exemplo de uma solicitação para gravar


na memória 1 DW de comprimento

Diferentemente das solicitações de gravação ou leitura, as solicitações de E / S têm várias limitações. Primeiro, as solicitações de gravação e leitura exigem uma resposta do destinatário. Isso leva ao fato de que a taxa de transferência de dados usando solicitações para o espaço de E / S se torna muito menor do que a largura de banda PCIe teórica permite. Em segundo lugar, o endereço das solicitações de espaço de E / S é limitado a 32 bits, o que não permite o acesso a fragmentos da memória do sistema além de 4 GB. Terceiro, as solicitações de espaço de E / S não podem exceder uma palavra dupla e não podem usar vários canais virtuais para transporte. Por esses motivos, os pedidos de gravação e leitura no espaço de E / S não serão mais considerados. Não obstante,o conteúdo dos cabeçalhos da memória de gravação / leitura e do espaço de E / S diferem apenas em vários campos; portanto, as estruturas de pacotes mostradas nas Figuras 3 e 4 também são aplicáveis ​​a solicitações no espaço de E / S.

Quando um nó de extremidade ou raiz do PCIe recebe uma solicitação para ler memória ou espaço de E / S, o dispositivo deve enviar uma resposta. Se o remetente da solicitação não receber uma resposta dentro de um determinado período, isso levará a um erro ao aguardar uma resposta. Se, por algum motivo, o dispositivo não puder enviar os dados solicitados, ele deverá gerar uma resposta de erro. Os possíveis motivos podem ser: o destinatário não suporta esta solicitação (solicitação não suportada); o destinatário não está pronto para aceitar a solicitação de configuração e solicita sua repetição mais tarde (Status de Nova Tentativa da Solicitação de Configuração), ocorreu um erro interno, devido ao qual o destinatário não pode responder e rejeita a solicitação (Interrupção Completa).

Formatos para uma resposta bem-sucedida a uma solicitação de leitura e uma resposta de erro para uma solicitação não suportada são mostrados nas Figuras 5, 6.


Figura 5 - Exemplo de uma resposta bem-sucedida para leitura


Figura 6— Exemplo de uma resposta sobre uma solicitação não suportada

Enquanto o terminal está acessando uma área de memória com 4 GB, o formato dos cabeçalhos de pacotes não difere dos cabeçalhos mostrados nas Figuras 3, 4. Para solicitações de gravação ou lendo a memória além de 4 GB, uma palavra dupla adicional com bits de ordem superior do endereço de destino é usada no cabeçalho (Figura 7).


Figura 7 - Um exemplo de cabeçalho de solicitação de gravação de 128

bytes.Explicações de nomes abreviados de campos de cabeçalho de pacote são apresentadas na Tabela 4.

Tabela 4 - Lista de abreviações para campos de cabeçalho
Não. P.Designação de campoNome do campoCompromisso
1 1TCCategoria de tráfego - classe de tráfegoDefine a associação ao canal virtual
2AtrAtributos: , , ID, ID.
3TH‒ TLP Processing Hint, [1..0] .
4TD‒ TLP Digest, .
5EP, .
6AT‒ Address Translation, : , ,
7BE‒ Byte Enable
8PHDica de processamento de pacotes - Dica de processamentoDicas ao destinatário do pacote como o pacote deve ser usado, bem como a estrutura de dados
9BCMA presença de uma alteração no número de bytesIndica se o número de bytes no pacote foi alterado. Somente um remetente em face de um dispositivo PCI-X pode definir um sinalizador

Se um terminal usa interrupções para relatar um evento, também deve formar um pacote apropriado. No total, o PCIe pode usar três tipos de interrupções:

  • interrupções herdadas (interrupções herdadas ou INT);
  • interrupções na forma de mensagens (interrupções sinalizadas por mensagem ou MSI);
  • mensagem estendida interrompe (mensagem sinalizada interrompe estendida ou MSI-X).

As interrupções INT herdadas são usadas para compatibilidade com sistemas que não suportam interrupções de mensagens. De fato, esse tipo de interrupção é uma mensagem (um pacote do tipo Message) que simula a operação de uma linha de interrupção física. Em um evento especificado, o terminal envia uma mensagem para a raiz do PCIe de que a interrupção INT foi ativada e aguarda a ação do manipulador de interrupções. Até que o manipulador de interrupção execute a ação especificada, a interrupção INT estará no estado ativado. As interrupções herdadas não permitem determinar a origem do evento, o que força o manipulador de interrupções a varrer sequencialmente todos os pontos de extremidade na árvore do PCIe para atender a essa interrupção. Quando a interrupção é atendida, o terminal envia uma mensagem informando queque a interrupção INT é mais inativa. Os núcleos de hardware FPGA, em um sinal da lógica do usuário, geram independentemente as mensagens necessárias para interrupções do INT, para que a estrutura de pacotes não seja considerada.

As interrupções de mensagens, juntamente com sua versão estendida, são o tipo principal e obrigatório de interrupção no PCIe. Na verdade, ambos os tipos de interrupções são uma solicitação para gravar na memória do sistema com o comprimento de uma palavra dupla. A diferença de uma solicitação regular é que o endereço de gravação e o conteúdo do pacote sejam alocados para cada dispositivo no estágio de configuração do sistema. Nesse caso, o LAPIC (Advanced Programmable Interrupt Controller) local dentro do processador central se torna o destino. Ao usar esse tipo de interrupção, não é necessário pesquisar sequencialmente todos os dispositivos na árvore PCIe. Além disso, se o sistema permitir que o dispositivo use vários vetores de interrupção, cada vetor poderá ser associado ao seu próprio evento.Juntos, isso reduz o tempo do processador para processar interrupções e aumenta o desempenho geral do sistema.

As interrupções MSI permitem a formação de até 32 vetores separados. O número exato depende dos recursos do terminal. Nesse caso, o sistema pode permitir o uso de apenas parte dos vetores. No estágio de configuração, o sistema grava o endereço de interrupção e os dados iniciais para gravação nos registros especiais do espaço de configuração do nó de extremidade. Todas as interrupções ativas usam o mesmo endereço. Mas para cada vetor, o ponto final altera os bits dos dados iniciais. Por exemplo, permita que um nó de extremidade suporte no máximo 4 vetores de interrupção, todos os 4 vetores são permitidos no sistema e os dados iniciais para gravação são 0x4970. Então, para formar o primeiro vetor, o ponto final passa os dados iniciais inalterados. Para o segundo vetor, o dispositivo altera o primeiro bit e transmite o número 0x4971.Para o terceiro e quarto vetores, o dispositivo transmitirá os números 0x4972 e 0x4973, respectivamente.

Os núcleos de hardware FPGA formam independentemente um pacote com uma interrupção MSI por um sinal da lógica do usuário. Entretanto, antes de comandar o kernel para enviar uma interrupção, a lógica do usuário também deve fornecer o conteúdo do pacote para o vetor necessário a uma interface especial do kernel.

As interrupções do MSI-X permitem a formação de até 2048 vetores individuais. Nos registros correspondentes do espaço de Configuração, o terminal indica em quais espaços de endereço BAR e com que deslocamento do endereço base estão localizadas a tabela de interrupção (Figura 8) e a tabela de sinalizadores de interrupção pendentes (Pending Bit Array - PBA, Figura 9), bem como os tamanhos de ambos tabelas. O sistema grava um endereço e dados separados para gravar em cada linha da tabela de interrupção e também permite ou proíbe o uso de um vetor específico através do primeiro bit do campo Controle de vetor. Para um determinado evento, o terminal define um sinalizador na tabela de sinalizadores de interrupções pendentes. Se nenhuma máscara for configurada para essa interrupção no campo Controle de vetor, o nó de extremidade enviará uma interrupção para o endereço da tabela de interrupções com o conteúdo especificado do pacote.


Figura 8 - Tabela de vetores de interrupção do MSI-X


Figura 9 - Tabela de sinalizadores para interrupções pendentes Os

núcleos de hardware do FPGA não possuem uma interface especializada para interrupções do MSI-X. O próprio desenvolvedor deve criar uma tabela de interrupção na lógica do usuário e uma tabela de sinalizadores de interrupções pendentes. Um pacote de interrupção também é completamente gerado pelo usuário e transmitido através da interface geral do kernel, juntamente com outros tipos de pacotes. O formato do pacote, neste caso, como já mencionado acima, corresponde a uma solicitação de gravação na memória do sistema com o comprimento de uma palavra dupla.

Recursos dos núcleos de hardware PCI Express FPGA série V da Intel na versão Avalon-ST


Apesar do fato de que os núcleos de hardware dos FPGAs PCI Express de diferentes fabricantes implementam funcionalidades semelhantes, as interfaces principais individuais ou a ordem de operação podem diferir.
Os núcleos de hardware PCI Express FPGA da série V da Intel estão disponíveis em duas versões: com Avalon-MM e Avalon-ST. Este último, embora exija mais esforço do desenvolvedor, permite que você obtenha o máximo de largura de banda. Por esse motivo, um kernel com uma interface Avalon-MM não será considerado.

A documentação do núcleo do PCI Express com a interface Avalon-ST descreve em detalhes suficientes os parâmetros do kernel, sinais de entrada e saída. No entanto, o kernel possui vários recursos aos quais um desenvolvedor deve prestar atenção.

O primeiro grupo de recursos refere-se a métodos que permitem configurar FPGAs dentro de 100 ms, de acordo com os requisitos do PCIe. Além do carregamento paralelo do tipo FPP, o desenvolvedor oferece métodos como Configuração via Protocolo (CvP) e o modo autônomo do kernel (modo autônomo). O desenvolvedor deve garantir que a configuração via protocolo ou modo de kernel independente seja suportada para a velocidade PCIe selecionada (parâmetro "Taxa de faixa"). Para configuração através do protocolo, informações relevantes podem ser encontradas na documentação do kernel. No caso do modo offline, não existe essa informação, então você precisa compilar o projeto. Se o modo independente do kernel não for suportado para a velocidade atual do kernel, o Quartus gerará um erro correspondente (Figura 10).


Figura 10 - Erro ao compilar um kernel PCIe para o modo offline

Se um desenvolvedor planeja usar a configuração por meio de um protocolo, ele também deve prestar atenção em qual núcleo FPGA o conector PCIe está conectado. Isto é especialmente verdade se o desenvolvedor não usar uma placa pronta, mas seu próprio dispositivo. Nos FPGAs com vários núcleos de hardware PCIe, apenas um núcleo permite que o CvP seja ativado. A localização do núcleo com suporte ao CvP é indicada na documentação do FPGA.
O segundo grupo de recursos está relacionado à própria interface de transferência de dados Avalon-ST. É essa interface usada para transferir pacotes no nível da transação entre a lógica do usuário e o kernel.

No lado de recebimento, o kernel possui dois sinais que permitem ao usuário pausar o recebimento de pacotes recebidos: o sinal rx_st_mask e o sinal rx_st_ready.
Usando o sinal rx_st_ready, o desenvolvedor pode pausar a saída de todos os tipos de pacotes. No entanto, se você ativar esse sinal, o kernel interromperá a saída de pacotes após apenas dois ciclos de clock da freqüência de operação. Portanto, durante a ativação do sinal, a lógica do usuário deve estar pronta para receber uma quantidade adicional de dados. Se, por exemplo, um desenvolvedor usa um buffer na forma de um FIFO, ele deve evitar estouros de buffer. Caso contrário, parte do conteúdo do pacote será perdida.

Usando o sinal "rx_st_mask", o desenvolvedor suspende a emissão de solicitações cujas respostas devem ser enviadas. Este sinal também não interrompe imediatamente a saída de pacotes. De acordo com a documentação, após ativar o sinal, o kernel pode emitir até 10 solicitações. Se a lógica do usuário ativar "rx_st_mask" e não houver espaço suficiente no buffer para processar pacotes recebidos, isso também poderá ativar o sinal "rx_st_ready". Nessa situação, a lógica do usuário para de ler todos os pacotes do buffer interno do kernel do hardware. Isso não só substitui os buffers do kernel de hardware, como também viola os requisitos de pedido de pacotes. O dispositivo deve ignorar solicitações que não exigem resposta e ler respostas. Caso contrário, o canal de dados será firmemente bloqueado.Por esse motivo, o desenvolvedor deve usar um buffer adicional para processar solicitações com respostas e não permitir que a lógica bloqueie pacotes de prioridade mais alta.

No lado da transmissão, os sinais tx_st_valid e tx_st_ready podem causar problemas. Se o sinal tx_st_ready estiver ativo, é proibido que a lógica do usuário redefina o tx_st_valid no meio do pacote de saída. Isso significa que, durante a transferência, o desenvolvedor deve fornecer todo o conteúdo do pacote. Se a fonte de dados for mais lenta que a interface do kernel, a lógica do usuário deverá acumular a quantidade necessária de dados antes do início do pacote.
Tanto no lado de recebimento quanto no de transmissão, o desenvolvedor deve prestar atenção à ordem dos bytes no cabeçalho e no conteúdo do pacote, bem como no alinhamento dos dados.

No pacote Avalon-ST do núcleo do hardware, em cada palavra dupla dentro do cabeçalho do pacote PCIe, os bytes seguem de baixo para alto; dentro do conteúdo da embalagem - do mais antigo para o mais novo. O desenvolvedor deve usar uma ordem semelhante nos pacotes de saída para transferir com êxito dados do terminal para a raiz.

A interface Avalon-ST do núcleo do hardware alinha os dados em múltiplos de 64 bits. Dependendo da largura da interface Avalon-ST, do comprimento do cabeçalho do pacote no nível da transação e do endereço do pacote, o kernel pode adicionar uma palavra dupla vazia entre o cabeçalho do pacote e seu conteúdo. Por sua vez, ao transmitir dados, a lógica do usuário deve adicionar uma palavra dupla vazia antecipadamente, por analogia com o kernel. Essa palavra dupla vazia não é levada em consideração no tamanho do pacote e é necessária apenas para a operação correta do kernel de hardware.

O próximo recurso está relacionado às respostas de leitura recebidas. A descrição do kernel diz que não perde as respostas recebidas cujo identificador não corresponde à solicitação de saída. Ao mesmo tempo, a lógica do usuário deve seguir o tempo de espera pelas respostas. Se o tempo de espera for excedido, a lógica do usuário deverá elevar o sinalizador “cpl_err [0]” ou “cpl_err [1]”. Não está claro na documentação como a filtragem funcionará quando o terminal enviar várias solicitações de leitura. A lógica do usuário informa apenas ao kernel que o tempo limite expirou para uma das solicitações, mas não pode passar o identificador dessa solicitação para o kernel. Existe a possibilidade de o kernel transmitir às respostas do lado do usuário uma solicitação com um tempo limite expirado. Portanto, o desenvolvedor deve criar seu próprio filtro para respostas recebidas.

Por fim, os desenvolvedores são fortemente encorajados a usar as informações sobre empréstimos disponíveis para pacotes de saída. A documentação principal diz que isso não é necessário, pois o kernel verifica empréstimos e bloqueia pacotes quando não há empréstimos suficientes. No entanto, todos os tipos de pacotes chegam ao kernel através de uma única interface. Se o buffer do pacote do kernel exceder, o kernel baixará o sinal tx_st_ready para zero. Até que o sinal tx_st_ready seja definido como um, a lógica do usuário, em princípio, não poderá enviar nenhum pacote. O número de empréstimos disponíveis é atualizado por meio de pacotes de um dispositivo parceiro. Se a lógica do usuário não apenas escreve, mas também lê, a velocidade com que o kernel atualiza os contadores de limites diminui. No final, o desempenho geral do sistema sofre.

Conclusão


O artigo descreveu os princípios gerais da transferência de dados via PCI Express, os formatos dos principais pacotes de dados. No entanto, o autor omitiu componentes da interface como canais virtuais, o controle do volume de respostas recebidas para leitura e a ordem dos pacotes não é rigorosa. Esses tópicos são discutidos em detalhes em várias fontes estrangeiras [ 4 , 6 ].
O artigo também inclui os recursos dos núcleos de hardware FPGA FPGA Intel Express da série V que o autor encontrou ao trabalhar no controlador de interface. Essa experiência pode ser útil para outros desenvolvedores.

Lista de fontes utilizadas


  1. Uma arquitetura PCIe DMA para transmissão de dados de vários gigabytes por segundo / L. Rota, M. Caselle, et. al. // TRANSAÇÕES IEEE EM CIÊNCIA NUCLEAR, VOL. 62, NO. 3 de junho de 2015.
  2. An Efficient and Flexible Host-FPGA PCIe Communication Library / Jian Gong, Tao Wang, Jiahua Chen et. al. // 2014 24th International Conference on Field Programmable Logic and Applications.
  3. Design and Implementation of a High-Speed Data Acquisition Card Based on PCIe Bus / Li Mu-guo, Huang Ying, Liu Yu-zhi // 《测控技术》2013年第32卷第7期。
  4. Down to the TLP: How PCI express devices talk (Part I) / Eli Billauer
  5. Low-Cost FPGA Solution for PCI Express Implementation / Intel Corporation.
  6. Managing Receive-Buffer Space for Inbound Completions / Xilinx // Virtex-7 FPGA Gen3 Integrated Block for PCI Express v4.3, Appendix B
  7. PCIe Completion Timeout / Altera Forum
  8. PCIe packet in cyclone VI GX / Altera Forum
  9. PCIe simple transaction / Altera Forum
  10. PCIe w/ Avalon ST: Equivalent of ko_cpl_spc_vc0? / Altera Forum
  11. Point me in the right Direction – PCIe / Altera Forum
  12. Solicitar tempos limite no fórum PCIE / Altera
  13. Design de interface de alta velocidade baseado no PCIe da plataforma não cooperativa de verificação de receptores / Li Xiao-ning, Yao Yuan-cheng e Qin Ming-wei // Conferência Internacional de 2016 sobre Mecânica, Controle, Elétrica, Mecatrônica, Informação e Computador
  14. Revisão 3.0 da especificação básica do PCI Express / PCI-SIG
  15. Interface Stratix V Avalon-ST para soluções PCIe / Intel Corporation
  16. Interface Avalon-ST do ciclone V para soluções PCIe / Intel Corporation

All Articles