Estoy tratando de usar un búfer de pantalla para almacenar, cambiar y enviar los bits de datos de video a la interfaz de transmisión DVI.
No puedo decidir qué tipo de RAM usar como búfer de pantalla. Después de leer un poco, llegué a la conclusión de que la RAM inferida de doble puerto sería la mejor opción. Sin embargo, no estoy seguro de cómo usar sus puertos de lectura y escritura. Ya logré inferir un bloque ram y lo instalé usando una función que genera un archivo .mif.
Mi progreso actual es el siguiente:
Así que estoy tratando de escribir y leer SIMULTÁNEAMENTE. El reloj para ambos es el mismo.
No incrusté ningún código por simplicidad, y traté de ser lo más claro posible. Si es necesario o deseado, publicaré fragmentos de código.
Mi pregunta es la siguiente: ¿Hay una mejor manera de abordar este tema, porque mis intentos hasta ahora no han tenido éxito? Parece que no puedo escribir en la RAM y no puedo encontrar el motivo. Algo me dice que tengo problemas con el tiempo, si alguien puede relacionarse con eso, por favor, ayúdame.
¡Gracias!
Editar:
Sí, estoy almacenando 1 bit por píxel con fines de almacenamiento y estoy decidiendo el color en el bloque de transmisión DVI que viene después. La decisión se basa en las coordenadas de hcounter y vcounter del DVI. Ejemplifico la RAM con '1' en cada celda. Verifico esto leyendo y enviándolo a la pantalla con un color constante:
if vcounter < 900 then
if hcounter < 1440 then
if pixel_in_sgnl = '0' then
dviRed <= "11111111";
dviGreen<= "00000000";
dviBlue <= "00000000";
else
dviRed <= "00000000";
dviBlue <= "11111111";
dviGreen <= "00000000";
end if;
Sin embargo, cuando trato de modificar el contenido de la RAM y luego lo leo y lo envío a la pantalla, todavía lo leo como 1, porque el color no cambia. Por ejemplo, en el siguiente código, quiero escribir "0000000000000000" en la ubicación 10000 y, como resultado, debería observar una línea de color diferente en un fondo constante. Espero haber sido lo suficientemente claro.
FB: FrameBuffer port map ( data_a => "0000000000000000",
data_b => "ZZZZZZZZZZZZZZZZ",
addr_a => 10000, --address_write_sgnl,
addr_b => address_read_sgnl,
we_a => '1',
we_b => '0',
clk_106 => DVI_clock,
q_a => open,
q_b => pixel_data_sgnl);
Esta es la RAM inferida que encontré en línea y modifiqué ligeramente:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FrameBuffer is
port
(
data_a : in std_logic_vector(15 downto 0);
data_b : in std_logic_vector(15 downto 0);
addr_a : in natural range 0 to 80999;
addr_b : in natural range 0 to 80999;
we_a : in std_logic ;
we_b : in std_logic ;
clk_106 : in std_logic;
q_a : out std_logic_vector(15 downto 0);
q_b : out std_logic_vector(15 downto 0)
);
end FrameBuffer;
architecture rtl of FrameBuffer is
-- Build a 2-D array type for the RAM
subtype word_t is std_logic_vector(15 downto 0);
type memory_t is array(0 to 80999) of word_t;
FUNCTION initialize_ram
return memory_t is
variable result : memory_t;
BEGIN
FOR i IN 0 to 80999 LOOP
result(i) := "1111111111111111";
END LOOP;
RETURN result;
END initialize_ram;
-- Declare the RAM
shared variable ram : memory_t :=initialize_ram ;
begin
-- Port A
process(clk_106)
begin
if(rising_edge(clk_106)) then -- Port A
if(we_a = '1') then
ram(addr_a) := data_a;
-- Read-during-write on the same port returns NEW data
q_a <= data_a;
else
-- Read-during-write on the mixed port returns OLD data
q_a <= ram(addr_a);
end if;
end if;
end process;
-- Port B
process(clk_106)
begin
if(rising_edge(clk_106)) then -- Port B
if(we_b = '1') then
ram(addr_b) := data_b;
-- Read-during-write on the same port returns NEW data
q_b <= data_b;
else
-- Read-during-write on the mixed port returns OLD data
q_b <= ram(addr_b);
end if;
end if;
end process;
end rtl;
Edit2:
Creo que logré resolver el problema de escribir en RAM, sin embargo, todavía puedo discutirlo para mejorar mi diseño. Ahora estoy atascado con la alimentación de mi salida de búfer a DVI. Como mencioné anteriormente, tengo 1 bit por píxel en la RAM, pero el ancho de salida de la RAM es de 16 bits. Así que necesito almacenar estos 16 bits y enviarlos a DVI uno por uno en cada borde del reloj DVI. Lo hago de la siguiente manera:
process(clk106M, locked_sgnl)
begin
if locked_sgnl = '0' then
address_counter <= (others => '0');
counter <= "10000";
pixel_in_register <= (others => '0');
elsif rising_edge(clk106M) and (locked_sgnl = '1') then
if (address_counter < "10011110001101000") then
if counter >= 16 then
pixel_in_register <= pixel_in;
address_counter <= address_counter + '1';
counter <= "00000";
else
pixel_in_sgnl <= pixel_in_register(0);
pixel_in_register <= '0' & pixel_in_register(15 downto 1);
counter <= counter + '1';
end if;
else
address_counter <= (others => '0');
end if;
end if;
end process;
buffer_address_dvi <= address_counter;
Uso un registro y mantengo la salida del búfer dentro. Luego, en cada ciclo de reloj durante 16 ciclos, saco el LSB del contenido del registro y cambio los datos a la derecha. Lo que se me queda en la cabeza es si necesito generar la dirección de lectura antes o no.
Actualmente, si hay un 0 en el búfer, ese píxel corresponde a verde. Si es 1, corresponde a azul. Lo que hago es instanciar la memoria RAM llena de '1'. Luego escribo '0' en una parte e intento observar una línea horizontal gruesa en la pantalla. Afortunadamente, veo esa línea horizontal, pero no está estacionaria. Es barrer la pantalla de arriba hacia abajo o de abajo hacia arriba, no puedo diferenciar. ¿Cuál podría ser la causa de este problema en particular?
Lo encontré hace un par de días:
Estaba aumentando la dirección del búfer de cuadros no solo durante la parte activa del DVI sino también en los períodos de borrado. Esto resultó en un cambio en la pantalla. Gracias a todos por sus respuestas o comentarios.
david tweed
Pistola de juguete Başaklar
gestión
Pistola de juguete Başaklar
gestión