Eu tenho uma placa Altera DE2 e tentando desenhar sprites. Estou com problemas para implementar um buffer de tela.
Eu tenho uma entidade de exibição que a uma taxa de 25 MHZ gera pixels para exibição vga.
Eu esperava implementar um buffer no SDRAM. A idéia original era carregar pixels no próximo pixel a uma taxa de 25 MHZ da SDRAM. Isso funciona, mas não consigo gravar pixels no SDRAM a esse ritmo nem limpar a tela com rapidez suficiente para cada novo quadro. São necessários dois relógios para gravar dados e minha placa opera a 50 MHZ, portanto, tenho tempo suficiente para fazer uma leitura completa.
Eu diria que estou fazendo algo terrivelmente errado. Como essa tela de desenho é normalmente implementada em VHDL?
A coisa mais próxima que pude encontrar é usar um esquema de cores 2-3-3 (RGB) para recuperar cada pixel e gravar na ram de tela durante o tempo VGA "vazio" (em branco). Isso significa que em cada um dos relógios de 25 mhz eu posso atualizar apenas 15% da tela e, de alguma forma, preciso do meu circuito para saber quais 15% estão sendo atualizados?
Não consigo descobrir como usar o buffer duplo porque não consigo descobrir como gravar dados na memória durante a leitura. Existe uma maneira de evitar a quebra de protocolo? Como esse cara faz isso?
Respostas:
Algumas abordagens que podem ser úteis para alguns estilos de exibição são dividir o painel de exibição em blocos e
- restringir cada bloco a usar um pequeno conjunto de cores, permitindo o uso de menos de 8 bits por pixel ou
- use um ou dois bytes de cada bloco para selecionar um local para ler os dados de bitmap.
A primeira abordagem poderia reduzir a taxa na qual os dados precisavam ser lidos na memória de exibição. Por exemplo, se alguém usasse blocos de 16 x 16 e cada um pudesse ter quatro cores escolhidas em um conjunto de 256, sem usar RAM extra no FPGA, seria possível reduzir o número de leituras de memória por 16 pixels para oito (quatro valores de cores, mais quatro bytes para o bitmap). Se você adicionar 160 bytes de buffer / RAM (*) ao FPGA, poderá reduzir o número de leituras de memória por 16 pixels para quatro, usando 160 leituras extras a cada 16 linhas de digitalização para ler o próximo conjunto de cores do bloco. Se alguém quisesse 16 cores por bloco, a segunda abordagem exigiria 640 bytes extras de RAM, a menos que se colocasse algumas restrições no número de paletas diferentes que poderiam existir em uma linha.A segunda abordagem provavelmente aumentaria, em vez de reduzir a largura de banda total de memória necessária para produzir uma exibição, mas reduziria a quantidade de memória que precisaria ser atualizada para alterar a exibição - é possível alterar um byte ou dois para atualizar um 8x8 ou 8x8. Área 16x16 da tela. Dependendo do que você está tentando exibir, pode ser útil ao usar esse estilo de abordagem usar um dispositivo de memória para manter as formas de ladrilho e outro para manter a seleção de ladrilho. Pode-se, por exemplo, usar uma RAM rápida de 32Kx8 para armazenar alguns mapas de blocos de 80x60 com dois bytes por bloco. Se o FPGA não tivesse nenhum buffer, teria que ler um byte a cada quatro pixels; mesmo com uma RAM estática de 40ns, isso deixaria bastante tempo para a CPU atualizar a exibição (uma tela inteira seria apenas 9600 bytes).
Aliás, se alguém não quisesse adicionar uma RAM de 32Kx8, mas poderia adicionar 320 bytes de buffer / RAM (**) ao FPGA, poderia usar uma abordagem de mapa de blocos, mas fazer com que a CPU ou o DMA alimentasse 160 bytes para o exibir a cada 8 linhas de digitalização. Isso sobrecarregaria um pouco o controlador, mesmo quando nada no visor estivesse mudando, mas poderia simplificar o circuito.
(*) O buffer pode ser implementado como RAM ou como uma sequência de 32 registros de deslocamento de 40 bits, além de um pouco de lógica de controle.
(**) O buffer pode ser implementado como duas RAMs de 160 bytes ou como dois grupos de dezesseis registros de deslocamento de 80 bits.
fonte
Sprites normalmente não são feitos com um buffer de quadro (como eu entendo a palavra). Em vez disso, você compara as coordenadas xey com xmin, ymin e xmax, ymax do sprite. Se a posição atual da digitalização estiver dentro do sprite, produza a cor relevante na memória do sprite.
Se você estiver tentando exibir um buffer de quadro, tenha coragem. Este foi o meu primeiro grande projeto FPGA. A SDRAM não deve ser um problema a 100 MHz (fiz isso há cerca de uma década e o silício está mais rápido agora), então multiplique seu relógio de 50 MHz. Escrever seu próprio controlador será educativo :)
Com isso, você tem bastante largura de banda para jogar, pode dobrar o buffer, sem problemas. A VGA de 60Hz precisa de uma média de 18Mpixels / s. Se você possui um dispositivo de 16 bits de largura, possui 200 MBytes / s de largura de banda de pico. Mesmo que você consiga apenas 50% de eficiência (o que deve ser possível), é 100Mpixels / s @ 16 bits por pixel ou 50Mpixels / s @ 32 bits por pixel.
Por exemplo, pode ser que a sua RAM precise de 60ns para configurar uma leitura, mas depois pode explodir 8 palavras em 80 ns - 8 bytes em ~ 140ns. Se você conseguir que sua RAM faça rajadas mais longas, isso ajudaria a amortizar o custo de configurar a leitura.
Com base no seu comentário de que é uma RAM do lado dos bytes, é um pouco mais de 50 MBytes / s, apenas 16 Mpixels / s @ 24 bits por pixel :( Você simplesmente não tem largura de banda suficiente para fazer uma exibição de cores reais, mesmo em VGA. poderia fazer 8 bits por pixel com muita facilidade, mas são apenas 2 ou 3 bits por cor - o que pode ser bom para o seu aplicativo, eu não sei, ou você pode fazer uma tabela de pesquisa de 256 cores como nos velhos tempos - depois Ao ler a partir do buffer de quadros, você usa o valor para procurar em um relógio de RAM interno para obter as cores de 24 bits (ou 18 bits, que se encaixariam perfeitamente em um BRAM) para o monitor.
O buffer duplo ainda funciona:
Exiba um quadro do endereço 0 (basta ler todos os pixels por vez, pausando as leituras durante os intervalos de apagamento).
Escreva seu próximo quadro em outro local. Para esse buffer duplo, seu controlador DRAM precisará priorizar entre as demandas concorrentes dos canais de leitura e gravação. Dica, priorize as leituras, pois são de tempo crítico :)
fonte