Skip to content
Diogo Valadares Reis dos Santos edited this page Aug 26, 2025 · 2 revisions

[English]

[← Página Anterior | Próxima Página →]

A Tela

A tela é um componente que permite que gráficos sejam renderizados pelo processador. Ela funciona de forma simplificada em comparação com telas reais, onde cada pixel é mapeado para um endereço na memória. Esse design permite alterar a cor de qualquer pixel usando uma única instrução de armazenamento (store).

A tela possui proporção quadrada, com uma resolução que pode ser configurada para qualquer potência de dois abaixo de 256. Por razões práticas, a resolução padrão é definida como 64, utilizando 14 bits para endereçar cada pixel (endereços de 6 bits por eixo).

Como cada pixel requer pelo menos 24 bits para representar sua cor, cada um é mapeado para uma palavra completa de 32 bits. Portanto, para mover de um pixel para o próximo, é necessário incrementar ou decrementar o endereço em 4.

Embora a tela esteja disponível no Logisim, devido ao desempenho limitado da simulação, recomenda-se utilizar a simulação em SystemVerilog para tarefas de renderização mais complexas.

image

Na interface SystemVerilog, há duas opções importantes de configuração. A primeira é a resolução, que pode ser ajustada conforme necessário. A segunda é o Screen Refresh Delay (atraso de atualização da tela), que controla com que frequência o programa lê o arquivo — valores menores resultam em taxas de atualização mais rápidas.

image

Código em SystemVerilog

O código da tela contém uma matriz de registradores que armazena a imagem sendo exibida. Essa matriz é copiada para um arquivo de tempos em tempos, caso tenha havido modificações. O tamanho da tela é parametrizado, permitindo que sua dimensão seja alterada.

`timescale 1s/1s
module video_controller #(
    parameter SCREEN_WIDTH_BIT_WIDTH = 8,
    parameter SCREEN_HEIGHT_BIT_WIDTH = 8,
    parameter SCREEN_WIDTH = 1 << SCREEN_WIDTH_BIT_WIDTH,
    parameter SCREEN_HEIGHT = 1 << SCREEN_HEIGHT_BIT_WIDTH,
    parameter SCREEN_FILE = "screen.mem",
    parameter WRITE_INTERVAL = 100  // Ciclos de clock entre tentativas de escrita
)(
    input clock,
    input reset,
    input write,
    input [SCREEN_WIDTH_BIT_WIDTH + SCREEN_HEIGHT_BIT_WIDTH - 1 : 0] address,
    input [31:0] data
);

logic [23:0] screenBuffer [0 : SCREEN_WIDTH * SCREEN_HEIGHT - 1];
logic [31:0] write_counter;
logic buffer_modified;  // Flag de modificação
integer file_handle;

// Inicializa a memória
initial begin
    foreach (screenBuffer[i]) screenBuffer[i] = 24'b0;
    write_counter = 0;
    buffer_modified = 0;
end

// Controle principal do buffer e do arquivo
always @(posedge clock) begin
    if (reset) begin
        // Reinicia memória e flags
        foreach (screenBuffer[i]) screenBuffer[i] = 24'b0;
        write_counter <= 0;
        buffer_modified <= 0;
    end
    else begin
        // Lida com escritas na tela e rastreia modificações
        if (write) begin
            screenBuffer[address] <= data[23:0];
            buffer_modified <= 1'b1;  // Ativa flag de modificação
        end

        // Lógica de escrita no arquivo (somente se modificado)
        write_counter <= write_counter + 1;
        if (write_counter >= WRITE_INTERVAL && buffer_modified) begin
            write_counter <= 0;
            file_handle = $fopen(SCREEN_FILE, "w");
            if (file_handle) begin
                foreach (screenBuffer[i]) begin
                    $fdisplay(file_handle, "%h", screenBuffer[i]);
                end
                $fclose(file_handle);
                buffer_modified <= 1'b0;  // Limpa flag após escrita bem-sucedida
            end
        end
    end
end

endmodule

Clone this wiki locally