Search code examples
graphicsvhdlfpgavgapicoblaze

VHDL - reading from VGA's framebuffer


I have an FPGA school project and I'm having some problems. We're using Digilent's Nexys2 board (Xilinx XC3S500E FPGA).

We built a few controllers including VGA (640x480) with a framebuffer. At least we called it a framebuffer - it's actually a distributed 30x40 RAM that stores pixels to be displayed (1 bit - "one square", so we actually have a 30 by 40 resolution, no colors).

Then we used the 8-bit Picoblaze microcontroller core and now we have to build a Snake game (you know, the one from the old Nokias). Now my problem is that Picoblaze only has a 64 Byte scratchpad RAM, so the snake can't get really long if I keep it in there.

So I was thinking I could just read where the snake is from VGA's RAM, but I don't know how, as VGA is reading from it and there's also the problem of addressing or reading whole line of data (picoblaze has a 8-bit in_port). Here's the process:

process(clk_i, vert_data_on, hor_data_on, read_data)
begin
    if vert_data_on = '1' and hor_data_on = '1' then
        if read_data(conv_integer(column_calc)) = '1' then
            red_o <= "000";
            green_o <= "000";
            blue_o <= "00";
        else
            red_o <= "111";
            green_o <= "111";
            blue_o <= "11";
        end if;
    else            
        red_o <= "000";
        green_o <= "000";
        blue_o <= "00";
    end if;
end process;

The RAM component and its instance:

component RAM30x40 is
    Port(
        clk_i           : in  STD_LOGIC;
        we_i            : in  STD_LOGIC;
        addrInX_i       : in  STD_LOGIC_VECTOR(5 downto 0);
        addrInY_i       : in  STD_LOGIC_VECTOR(4 downto 0);
        addrOutY_i      : in  STD_LOGIC_VECTOR(4 downto 0);
        data_i          : in  STD_LOGIC;
        data_o          : out STD_LOGIC_VECTOR(0 to 39)
    );
end component;

inst_RAM: RAM30x40
Port map(
    clk_i           => clk_i,
    we_i            => write_enable,
    addrInX_i       => write_addr_x,
    addrInY_i       => write_addr_y,
    addrOutX_i      => read_addr_x,
    addrOutY_i      => row_calc,
    data_i          => write_data,
    data_o          => read_data
);

How is this solved in PCs? Is it common to read from graphic card's memory? What are my options here? I could use block RAM with two clocks and have one for VGA's reading and the other for the picoblaze but I don't know and can't find how to generate another clock signal properly.


Solution

  • I would just define a second read port that is only active during flyback like this:

    process(clk_i, vert_data_on, hor_data_on, read_data)
    begin
        if vert_data_on = '1' and hor_data_on = '1' then
            if read_data(conv_integer(column_calc)) = '1' then
                red_o <= "000";
                green_o <= "000";
                blue_o <= "00";
            else
                red_o <= "111";
                green_o <= "111";
                blue_o <= "11";
            end if;
            data2_valid <= '0';
        else            
            red_o <= "000";
            green_o <= "000";
            blue_o <= "00";
    
            read_data2 <= conv_integer(read_request2);
            data2_valid <= '1';
        end if;
    end process;
    

    data2_valid would then define the trigger for valid data from the read_request2 address. You should probably trigger the process on clk_i instead of the flyback signals, however.