Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Using BRAM to store image/pixels in VGA

Status
Not open for further replies.

anccc

Newbie level 3
Joined
Apr 9, 2013
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Estonia
Activity points
1,363
Hello!

I'm fairly new to this board and to FPGA/VHDL in general, but I've had some courses in the subject before. What I'm trying to do is to implement a sort of a music sheet, where different notes can be placed according to given signals. I would also like to have the note pixels stored preferrably in a block RAM (or any easy way of storing pixels I'm currently ) according to the previous shown location so that when I move the note around, a sort of a copy of the note is placed in that location that stays there. At the moment, I'm using a single clef to move around in a small area for testing if the placement stays the same when I move the clef to another location but I'm unable to have the clef displayed in the previous location. I have a working VGA controller using 640*480 resolution and I have inferred a block RAM using examples, I've found on the Internet. I am using a Basys2 board with 250k logic gates. Here is what I've done so far:

I have defined the note/clef in a 2 dimensional array like this

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
type clefGenType is array (0 to 35) of std_logic_vector(15 downto 0); -- two-dimensional array for storing clef pixels
  constant clefGenLT : clefGenType := (
  
conv_std_logic_vector(  1024    , 16),
conv_std_logic_vector(  1536    , 16),
conv_std_logic_vector(  3840    , 16),
conv_std_logic_vector(  2944    , 16),
conv_std_logic_vector(  2176    , 16),
conv_std_logic_vector(  2176    , 16),
conv_std_logic_vector(  2176    , 16),
conv_std_logic_vector(  2176    , 16),
conv_std_logic_vector(  3200    , 16),
conv_std_logic_vector(  3200    , 16),
conv_std_logic_vector(  1664    , 16),
conv_std_logic_vector(  1920    , 16),
conv_std_logic_vector(  960 , 16),
conv_std_logic_vector(  480 , 16),
conv_std_logic_vector(  496 , 16),
conv_std_logic_vector(  504 , 16),
conv_std_logic_vector(  316 , 16),
conv_std_logic_vector(  1950    , 16),
conv_std_logic_vector(  4046    , 16),
conv_std_logic_vector(  7654    , 16),
conv_std_logic_vector(  14694   , 16),
conv_std_logic_vector(  12662   , 16),
conv_std_logic_vector(  12662   , 16),
conv_std_logic_vector(  13174   , 16),
conv_std_logic_vector(  12902   , 16),
conv_std_logic_vector(  12868   , 16),
conv_std_logic_vector(  12940   , 16),
conv_std_logic_vector(  6680    , 16),
conv_std_logic_vector(  3632    , 16),
conv_std_logic_vector(  1984    , 16),
conv_std_logic_vector(  1024    , 16),
conv_std_logic_vector(  1040    , 16),
conv_std_logic_vector(  1080    , 16),
conv_std_logic_vector(  1592    , 16),
conv_std_logic_vector(  784 , 16),
conv_std_logic_vector(  480 , 16) );


And I use this code to draw out the clef. I've also set EN and WE to '1' so I could forward the dataOut to the BRAM I have inferred in another file and defined the BRAM address

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
--  NOTE* constants and signals used for placement and drawing of image 
--  adrHor: in integer range 0 to cstHorSize - 1; -- pixel counter (800;-- cstHorAl + cstHorFp + cstHorPw + cstHorBp; -- pixel/total line)
--  adrVer: in integer range 0 to cstVerSize - 1; -- lines counter (521 --cstVerAf + cstVerFp + cstVerPw + cstVerBp; -- lines/total frame)
--  constant cstHorPlayFieldSize: integer := 128;
--  constant cstVerPlayFieldSize: integer := 128;
--  constant cstHorPlayFieldPos: integer := cstHorAl/2 - cstHorPlayFieldSize/2; -- Al - active line
--  constant cstVerPlayFieldPos: integer := cstVerAf/2 - cstVerPlayFieldSize/2; -- Af - active frame
  
--  constant clefSizeHor: integer := 16; -- clef horizontal size in pixels
--  constant clefSizeVer: integer := 36; -- clef vertical size in pixels
  
--  signal clefPix : integer range 0 to clefSizeHor - 1; -- horizontal position within the clef
--  signal clefLine : integer range 0 to clefSizeVer - 1; -- vertical position within the clef
 
--  signal cntClefPosHor: integer range 0 to cstHorPlayFieldSize - 1 := cstHorPlayFieldSize/2;
--  signal cntClefPosVer: integer range 0 to cstVerPlayFieldSize - 1 := cstVerPlayFieldSize/2;
 
        adrClefBRAM <= conv_std_logic_vector(cntClefPosHor + cntClefPosVer * cstHorPlayFieldSize, 14); -- should total 16383 - 1*16kbit RAM
 
        clefLine <= adrVer - cntClefPosVer;  
        clefPix  <= adrHor - cntClefPosHor;
 
    drawClef : process (ck25MHz, adrHor, adrVer, cntClefPosHor, cntClefPosVer)
    begin
         EN <= '1';
         WE <= '1';
         if ((adrHor >= cntClefPosHor and adrHor < cntClefPosHor + clefSizeHor) and
            (adrVer >= cntClefPosVer and adrVer < cntClefPosVer + clefSizeVer)) then
                    dataOut <= clefGenLT(clefLine)(clefPix);
         else
                    dataOut <= '0';
         end if;
    end process;
 
  red <= "111" when sendSignal = '1' else "000";
  blue <= "11" when DataIN = '1' else "00";


I inferred my BRAM as an array of std_logic:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use ieee.std_logic_unsigned.all;
 
entity rams_01 is
    Port ( ck25MHz : in  STD_LOGIC;
           WE : in  STD_LOGIC;
           EN : in  STD_LOGIC;
           ADDR : in  STD_LOGIC_VECTOR (13 downto 0); --adrClefBRAM
           DI : in  STD_LOGIC;
           DO : out  STD_LOGIC;
         sendSignal : out STD_LOGIC 
         );
end rams_01;
 
architecture Behavioral of rams_01 is
     type ram_type is array (16383 downto 0) of std_logic;
    signal RAM: ram_type;
 
    constant arrayLength : integer := 16384;
    signal counter : integer range 0 to arrayLength - 1;
begin
 
    RAMproc : process (ck25MHz)
     begin
        if ck25MHz'event and ck25MHz = '1' then
            if EN = '1' then
                if WE = '1' then
                    RAM(conv_integer(ADDR)) <= DI; -- dataOut
                end if;
                DO <= RAM(conv_integer(ADDR)); --dataIN
            end if;
        end if;
    end process;
 
    Counterproc: process (ck25MHz)
    begin
        if ck25MHz'event and ck25MHz = '1' then
          if counter < arrayLength - 1 then
            if RAM(counter) = '1' then
                sendSignal <= '1'; -- for the colour controller to display as red
            else
                sendSignal <= '0';
            end if;
            counter <= counter + 1;
          else
            counter <= 0;
          end if;
        end if;
    end process;
 
end Behavioral;


Now I checked the console log and I see that the BRAM is inferred as I expected. I am able to get the image just fine and as it is going through the memory, all the '1' and '0' pixels should be stored in the RAM, shouldn't they? The problem is that when I move the location on the screen, like this:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
HorMovement: process(ck10Hz)
  begin
    if ck10Hz'event and ck10Hz = '1' then
      if btnRight = '1' then
        if cntClefPosHor < cstHorPlayFieldSize - 1 then 
             cntClefPosHor <= cntClefPosHor + clefSizeHor + 10;
        end if;
      elsif btnLeft = '1' then
        if cntClefPosHor > 0 then -- starting position
            cntClefPosHor <= cntClefPosHor - clefSizeHor - 10;
        end if;
      end if;
   end if;
 end process;


the image moves, but the previous location is still blank. I though that if I could make a counter which goes through the contents of the RAM like I did with Counterproc, I should at least get some values to send back to the image controller and show as colour red, but I don't see anything other than the blue clef. I'm obviously doing something wrong with reading/writing into the RAM and I don't understand it very well. Any criticism would be appreciated. Also if there is another much easier or more efficient way of storing the image, I would be grateful. I will also attach the .vhd files if anyone is interested.
 

Attachments

  • VGASimpleRAM.rar
    8.6 KB · Views: 55
Last edited:

I haven't as a matter of fact, but I guess I have no other option at the moment yes, to be honest
 

Simulation will save you a lot of time and bother on the workbench
 
  • Like
Reactions: anccc

    anccc

    Points: 2
    Helpful Answer Positive Rating
Okay, through the simulation I was able to figure out that I'm only writing to only one address over and over again and the reason, I'm getting the image is that when I write a pixel to BRAM, I also get that same value into DO(DataOut) and thus am able to colour it if I'm correct.

But I seem to have run into a rock wall because I can't figure out a way to place the displayed pixel to the correct memory address. Like I said before, I've currently defined my address as a 14 bit logic_vector which is calculated with the horisontal and vertical placement of the image:

Code VHDL - [expand]
1
adrClefBRAM <= conv_std_logic_vector(cntClefPosHor + cntClefPosVer * cstHorPlayFieldSize, 14);


So if i'm drawing my image from the 2 dimensional array with the starting point of adrClefBRAM

Code VHDL - [expand]
1
2
3
4
5
if ((adrHor >= cntClefPosHor and adrHor < cntClefPosHor + clefSizeHor) and
    (adrVer >= cntClefPosVer and adrVer < cntClefPosVer + clefSizeVer)) then
    dataOut <= clefGenLT(clefLine)(clefPix);
else
    dataOut <= '0';


how could I make sure, that every pixel that is drawn ends up in the correct address slot for the BRAM? So probably the question would be in what way should I describe the adrClefBRAM signal so that it would point to the correct address of the BRAM I'm using in a 128*128 bit area according to the current displayed pixel drawn out with the clefGenLT?
 
Last edited:

I know this isnt relavent to your problem, but to make it actually implement a BRAM, you need to make the read process synchronous. I suggest you do this now so you dont have problems later.

I suggest you try and modify your test cases to keep debugging the problem in simulation.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top