Image to MEM Tool

This tool coverts images to a .MEM file that can be used in an FPGA design. Some details:

  • Written in Matlab, therefore accepts pretty much any input (png, bmp, jpg, etc.)
  • Output .MEM file is a text file with binary values for each pixel
  • Reduces pixels down to using 64 colors, i.e. 2 bits each for R, G, and B components for a total of 6 bits/pixel
  • Shows previews of original image and the resulting image using the 6 bit color map
  • Output .MEM file tested with Altera Quartus Prime and Verilog using $readmemb() function to import data

Why?

I made this to support another project which is an FPGA-based 80’s retro video game. The game is all FPGA, i.e. no HPS, no soft MCU, no frame buffer, just on-the-fly generation of a VGA signal 800×600 at 60 Hz (40MHz pixel clock) and gameplay also implemented in the FPGA. A fun example of what FPGAs can do

More detail on that project here – Ganzvaders.

I use this tool mostly to convert sprites, or strips of sprites for animations, or even larger background tiles.

Example

The code for this tool and an example are up on GitHub.

Here’s an sample of the preview it produces for an image containing a vertical strip of sprites (the leftmost column). Please forgive the artwork quality. The tool shows 8 images, in columns: the original image, the reduced (64 color) image, and each of the RGB components for the original and 64 color images:

MEM File Format

MEM files are ASCII and allow hex or binary values. This tool outputs binary for reduced hassle and easier human readability. Since 6 bits/pixel is not a multiple of the 4 bit size of a hex digit, the output files would be a lot harder to read (for a human) had I generated hex. This is just for a game, and human readability during the development was helpful so it outputs binary.

An example output .MEM file is up on GitHub.

Why 6 bit color?

For an 80’s retro video game that’s plenty of color – better than CGA, or EGA, and even some modes of the original VGA standard. Also this keeps the usage of memory resources in the FPGA under control. 24 bit color would be 4x more expensive to store in the FPGA and provide many more colors than necessary for a retro game like Ganzvaders. If you do need higher color depth, modifying the Matlab code is pretty straightforward.

How use the MEM file?

Once the .MEM file is generated and added to your FPGA project, it can be read in from a Verilog file. This can be used to initialize a 2D array (which could be in distributed RAM or block RAM – that’s another story) using the $readmemb() function. A very generic example that allows the synthesis tools to decide where to place the memory for this sprite is seen below:

reg [5:0] sprite_data [0:(WIDTH*HEIGHT*NUM_SPRITES)-1];

initial begin
   $readmemb(MEMFILE,sprite_data);
end

Altera/Xilinx

I’ve used this tool successfully with Verilog and Altera’s Quartus Prime 20.1, Light Edition. I haven’t tested with Xilinx or other vendor’s tools, but if they can read a .MEM file, it should work as well.

Full source code is available on my GitHub.