eu eu nunca fui muito adepto desses recursos de debug em FPGAs... quando eu comecei a estudar mais a fundo verilog, no
http://www.asic-world.com (recomendo fortemente!), eu considerava CPLD, FPGA, ASIC, etc tudo farinha do mesmo saco. eu tambem conversei com muita gente da area de design de circuitos integrados, o que consolidou minha opcao por verilog e acabou me levando a um fluxo de trabalho parecido com este:

curiosamente, nao eh o fluxo de trabalho tipico para FPGAs, mas acaba encaixando bem: tal como no caso de um ASIC, eu nao tenho onde testar previamente, pq a placa onde a FPGA vai estar ainda estah em fase de projeto (especificacao, esquematico, layout, encomenda, producao, etc). entao eu sigo aquele fluxo: especificacao de como as coisas deveriam funcionar, projeto de alto nivel (descrevo em verilog o sistema como um todo) e projeto de baixo nivel (descrevo cada sub-sistema logico com detalhes). neste caso, o que eu tenho eh uma simulacao do sistema como um todo em verilog: a logica que vai dentro da FPGA, a logica que vai na placa que contem a FPGA e, eventualmente, as placas que se conectam nessa placa. eventualmente, eu posso ir lah no backplane do sistema e medir sinais, me certificar de que as simulacoes geram sinais identicos. tendo esse nivel de detalhismo, consigo comecar o ciclo do RTL: escrever o codigo que vai dentro da FPGA, testar pontualmente modulo por modulo, fazer a sintese e verificar se tanto a sintese como a simulacao estao de acordo. a ideia eh atingir 100% do objetivo apenas com simulacao, mas note que, embora nao teste a sintese na FPGA, eu costumo vasculhar o que a ferramenta estah gerando a procura de "interpretacoes erroneas". por exemplo, as vezes vc descreve um MUX, mas a ferramenta nao entende como tal pq vc nao ocupou um numero de entradas multiplo de 2^n. vc percebe isso no esquematico da sintese, corrige o codigo, sintetiza e verifica novamente para ver se agora o seu MUX estah lah. enfim, a ideia eh que esse loop continue ateh que as coisas estejam suficientemente boas para funcionar de primeira. no caso de um ASIC, isso eh essencial: custa caro e demora para produzir um prototipo, entao vc tem que garantir que esteja tudo funcionando. no caso de uma FPGA, vc quer garantir que o cara que vai ligar a placa pela primeira vez vai descarregar a FPGA e ela vai funcionar de primeira. claro, atualizar a FPGA eh infinitamente mais simples que um ASIC em caso de falha, mas em um sistema complexo com processador, memorias e N interfaces para dar problema, a FPGA rodar de primeira eh um bonus consideravel.
desta forma, enquanto o pessoal de HW e SW estah feliz debugando seus detalhes especificos, vc comeca a trabalhar em cima do mundo real, ou seja, fora da FPGA, onde os sinais possuem tempo e amplitude reais!
neste caso eu abandono totalmente a simulacao (usada para verificar as entranhas da FPGA) e vou para o osciloscopio, conferir se as coisas estao boas do ponto de vista eletrico. a forma com que trabalho eh bem simples: normalmente eu reservo quatro pinos de GPIO para conectar um osciloscopio e em cada modulo eu reservo 4 sinais para funcoes de debug. essas linhas de debug de cada modulo acabam indo para um MUX no top level que eu posso setar por algum registro, de modo que eu posso selecionar modulo por modulo os 4 sinais de debug que eu escolhi no modulo e observar no osciloscopio. no caso, esse debug eh parte integral do projeto, portanto nao fico com aquele classico risco de "funciona quando o debug estah sintetizado junto e para de funcionar quando retira o debug". e bom, aqui vc percebe que simulacoes sao perfeitas, mas nao sao completas. no caso de um projeto em que colocamos um cluster de DSPs em uma FPGA, conseguimos no maximo simular algo em torno de 1 segundo de operacao. para coisas simples, eh suficiente, mas normalmente nao dah nem para o comeco: problemas criticos podem acontecer depois de horas e horas de perfeita operacao! jah peguei o caso de um ASIC que funcionava perfeitamente por horas e horas, mas sempre gerava um pequeno glitch que fazia o sistema todo parar... demoramos semanas para cercar o problema, mas acabamos pegando o momento exato com um osciloscopio de persistencia infinita. vc pode simular de todo jeito uma FPGA e, do ponto de vista logico, funcionar tudo perfeitamente, daih coloca para funcionar e falha miseravelmente. o problema, quase sempre eh justamente pq os sinais no mundo real possuem tempo e amplitude reais. e para isso vc precisa de um osciloscopio, pq o debug da FPGA soh trabalha com tempo e amplitude discretos.
em uma certa ocasiao eu pensei em usar os recursos de debug da FPGA, pois era um caso em que a funcionalidade de aquisicao de dados discretos era suficiente (operacoes bem comportadas de leitura/escrita), mas rapidamente percebi que era um volume de informacao fora da realidade. bom, o debug da FPGA, na realidade, funciona como uma janela de aquisicao de um osciloscopio: algum evento externo trigga a captura, ele armazena em uma memoria e transfere via JTAG... mas eh meio limitado em termos de capacidade. no caso, eu precisava espiar um barramento de processador em realtime e pelo tempo que demorasse para o sistema subir e comecar a funcionar, ou seja, quase 10 minutos de captura continua! daih eu tirei uma solucao da manga: capturar evento por evento e armazenar em um buffer em alta velocidade. obviamente o buffer eh tao grande quando seria com o mecanismo de debug proprio da FPGA, mas o pulo do gato eh esvaziar o buffer de forma igualmente rapida, enviando os dados para um PC. o recurso de debug da FPGA faz isso via JTAG, mas eu acredito que o software para isso nao esta preparado para trabalhar com um volume gigantesco de informacao e/ou com um taxas de transferencias continuas elevadas. entao eu montei minha propria solucao para transferir quantidades cavalares de dados em alta velocidade para o PC. eu acho que eh uma opcao bem consideravel e escala muito bem, por exemplo, se vc usar uma interface GbE, vc pode capturar barramentos a taxas de 125Mbytes/s! :O
a galera mais antiga, por outro lado, utilizava bastante esse recurso de debug... eu acompanhei os caras mais de perto ano passado e, bom... nao senti muita firmeza.
jah comecou o classico "funciona quando o debug estah sintetizado junto e para de funcionar quando retira o debug". e claro, o pessoal usava VHDL... como usuario de verilog, eu francamente nao boto muita feh que o cara consiga dominar bem todos os aspectos da linguagem, enfim, era evidente que algumas descricoes de alto nivel simplesmente nao produziam codigo e eram silenciosamente ignoradas na sintese. eh facil explicar a diferenca: em verilog vc usa apenas dois tipos (reg e wire) e eles correspondem a entidades fisicas definidas (flip-flops e fios), que se organizam em arrays (registros e barramentos). por outro lado, em VHDL vc pode usar uma infinidade de tipos (inteiro, ponto flutuante, etc) e organizar em uma infinidade de formas (arrays, estruturas, etc). em verilog vc tem que esculpir silicio flip-flop por flip-flop para expressar problemas do mundo real, enquanto que em VHDL vc simplesmente programa e magia gera o hardware. o problema eh quando a magia nao acontece e nada eh gerado! ironicamente, quando vc vai tentar olhar pq nao funciona, vc acaba induzindo a ferramenta da sintese a gerar aquela parte do codigo e as coisas funcionam... daih vc tira o recurso de debug, para de funcionar. e nesse trem tem projetos antigos com todo tipo de defeito: FPGA que para de funcionar quando esquenta, FPGA que para de funcionar quando coloca uma placa do lado, FPGA que para de funcionar quando vc espirra, etc. ter mais recursos, como VHDL fornece, ateh seria legal. mas as limitacoes de sintaxe do verilog sao meio que presas as limitacoes do proprio HW, o que impede de extrapolar alem do que o HW consegue fazer bem... mas daih jah eh assunto para outro dia! hehehe
bom, sao os meus dois centavos sobre o assunto... e olha que eu nem sou muito xiita em termos de simulacao: tem um colega que projetou um DSP integralmente apenas com simulacao e sintese. quer dizer, eu nunca vi ele descarregar o projeto em uma FPGA para ver se funcionava! isso que ele gosta de usar recursos "low-level" obscuros da FPGA que vc tem certeza que nem tem como simular, sem falar nos 10 warnings por linha na hora de fazer o build... mas nao eh que no final das contas funcionou de primeira? eu simplesmente peguei o codigo do DSP, construi as interfaces de IO em volta, usei um generate para criar um cluster com multiplos cores, escrevi um firmare de teste (o assembler para o DSP foi feito em awk e foi testado, imagina soh, apenas na simulacao...), fiz o build da FPGA e bingo: 20 mil MIPS de performance de pico funcionando feito um relogio. se fosse um ASIC, ele tinha acertado no primeiro prototipo! :O