0

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.

Luka
  • 7
  • 6
  • 1
    I think it is not common to read from the VGA read buffer. Your game logic should have its own current state of the field and snake. The posted process has a clock `clk_i` in its sensitivity list, but does not describe synchronous logic. Is this intended? And `column_calc` is missing if it should be a combinational process. – Martin Zabel Mar 03 '16 at 13:46
  • If the scratchpad memory is not large enough you should consider adding an external BRAM to your Picoblaze design for data storage. you may need some glue logic like an output port for the BRAM address etc., there is plenty of documentation of how I/O works for the Picoblaze processor. – andrsmllr Mar 03 '16 at 16:09
  • `vert_data_on` and `horiz_data_on` are apparently used for the horizontal and vertical flyback. The VGA output does not need memory during this timeframe. You do not show how you generate this signals, but there is probably enough time to do something else with the memory during this. – mfro Mar 04 '16 at 06:07
  • @MartinZabel Thank you, that clk_i should not be in the sensitivity list and column_calc is indeed missing. P.S. (intended to the downvoter) why did I get a minus? – Luka Mar 04 '16 at 11:22
  • @damage Thank you, I looked into that and decided to ditch the distributed RAM and go with a bigger BRAM which shall serve me as a framebuffer and I won't have 1 bit pixels anymore, but instead at least a byte wide ones, so that I will be able to implement colors and save some additional info from the game (sequential numbers etc.) into them. – Luka Mar 04 '16 at 11:22
  • @mfro Thanks and yes, those really are used for that and I've tried that before but I couldn't get it working properly. – Luka Mar 04 '16 at 11:22
  • If I image the solution from @mfro correctly, then you must ensure that you have only one read statement. The address of the read statement is then the pixel address (during VGA output) or a secondary address (during blanking). – Martin Zabel Mar 04 '16 at 11:53

1 Answers1

0

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.

mfro
  • 3,286
  • 1
  • 19
  • 28
  • Like I said, I then decided to go for a bigger dual port BRAM with the same clock for both ports, so I did it a bit differently. But this is helpful so I'll accept it as an answer (but I can't upvote it due to my low reputation). – Luka Mar 06 '16 at 11:37