Image processing on FPGA using Verilog HDL

This FPGA project is aimed to show in details how to process an image using Verilog from reading an input bitmap image (.bmp) in Verilog, processing and writing the processed result to an output bitmap image in Verilog. The full Verilog code for reading image, image processing, and writing image is provided.

In this FPGA Verilog project, some simple processing operations are implemented in Verilog such as inversion, brightness control and threshold operations. The image processing operation is selected by a "parameter.v" file and then, the processed image data are written to a bitmap image output.bmp for verification purposes. The image reading Verilog code operates as a Verilog model of an image sensor/ camera, which can be really helpful for functional verifications in real-time FPGA image processing projects. The image writing part is also extremely useful for testing as well when you want to see the output image in BMP format. In this project, I added some simple image processing code into the reading part to make an example of image processing, but you can easily remove it to get raw image data. All the related questions asked by students are answered at the bottom of this article.First of all, Verilog cannot read images directly. To read the .bmp image on in Verilog, the image is required to be converted from the bitmap format to the hexadecimal format. Below is a Matlab example code to convert a bitmap image to a .hex file. The input image size is 768x512 and the image .hex file includes R, G, B data of the bitmap image.

To read the image hexadecimal data file, Verilog uses this command: $readmemh or $readmemb if the image data is in a binary text file. After reading the image .hex file, the RGB image data are saved into memory and read out for processing.

The header data for the bitmap image is very important and it is published here. If there is no header data, the written image could not be correctly displayed. In Verilog HDL, $fwrite command is used to write data to file.

Finally, we have everything to run a simulation to verify the image processing code. Let's use the following image as the input bitmap file:

Input bitmap image

Run the simulation for 6ms, close the simulation and open the output image for checking the result. Followings are the output images which are processed by the selected operations in parameter.v:

Output bitmap image after inverting

Output bitmap image after threshold operation

Output bitmap image after subtracting brightness

Since the reading code is to model an image sensor/camera for simulation purposes, it is recommended not to synthesize the code. If you really want to synthesize the processing code and run this directly on FPGA, you need to replace these image arrays (total_memory, temp_BMP, org_R, org_B, org_G) in the code by block memory (RAMs) and design address generators to read image data from the block memory.

After receiving so many questions related to this project, followings are the answers to your questions:

1. Explanation and tutorial on how to run the simulation:

2. The full Verilog code for this image processing project can be downloaded here. Run the simulation about 6ms and close the simulation, then you will be able to see the output image.3. The reading part operates as a Verilog model of an image sensor/camera (output RGB data, HSYNC, VSYNC, HCLK). The Verilog image reading code is extremely useful for functional verification in real-time FPGA image/video projects.4. In this project, I added the image processing part to make an example of image enhancement. You can easily remove the processing part to get only raw image data in the case that you want to use the image sensor model only for verifying your image processing design.5. The image saving into three separate RGB mems: Because Matlab code writes the image hexadecimal file from the last row to the first row, the RGB saving codes (org_R, org_B, org_G) do the same in reading the temp_BMP memory to save RGB data correctly. You can change it accordingly if you want to do it differently.6. You might find the following explanation for the BMP header useful if you want to change the image size:Image size = 768*512*3= 1179648 bytesBMP header = 54 bytesBMP File size = Image size + BMP Header = 1179702 Bytes Convert it to hexadecimal numbers: 1179702 in Decimal = 120036 in HexadecimalThen 4-byte size of BMP file: 00H, 12 in Hexa = 18 Decimal, 00H, 36 in Hexa = 54 DecimalThat's how we get the following values:BMP_header[ 2] = 54;BMP_header[ 3] = 0 ;BMP_header[ 4] = 18;BMP_header[ 5] = 0 ;Image width = 768 => In hexadecimal: 0x0300. The 4 bytes of the image width are 0, 3, 0, 0. That's how you get the following values:BMP_header[18] = 0;BMP_header[19] = 3;BMP_header[20] = 0;BMP_header[21] = 0; Image height = 512 => In hexadecimal: 0x0200. The 4 bytes of the image width are 0, 2, 0, 0. That's how we get the following values:BMP_header[22] = 0;BMP_header[23] = 2;BMP_header[24] = 0;BMP_header[25] = 0;7. You should not synthesize this code because it is not designed for running on FPGA, but rather for functional verification purposes. If you really want to synthesize this code (read and process) and load the image into FPGA for processing directly on FPGA, replace all the temp. variables (org_R, org_B, org_G, tmp_BMP = total_memory) by block RAMs and generate addresses to read the image data (remove the always @(start) and all the "for loops" - these are for simulation purposes). There are two ways: 1. write a RAM code and initialize the image data into the memory using $readmemh; 2. generate a block memory using either Xilinx Core Generator or Altera MegaFunction and load the image data into the initial values of memory (.coe file for Xilinx Core Gen. and .mif for Altera MegaFunction), then read the image data from memory and process it (FSM Design). 8. In this project, two even and old pixels are read at the same time for speeding up the processing, but you can change the number of pixels being read depending on your design. 9. The writing Verilog code is also very helpful for testing purposes as you can see the output in BMP format.10. If you want to do real-time image processing, you can check this for the camera interface code: Basys 3 FPGA OV7670 Camera

194 comments:

My name is Jewel. I'm from India doing B.tech in Manipal University Your code on image processing using verilog HDL was really helpful. I'm doing a project called JPEG encoder using verilog HDL for grayscale image. Can u please help me with a code for this topic?

Sir,i have followed your blog since 2016 and currently i am doing a project on verilog to design a codec using wavelet transform algorithm,sir i require your help regarding this.Can you help me in completing my project?

Bravo sir. you have done a great job it will assist the new learners like me a lot. Sir can you plz share the code with me so i can practice it. sir please share the full code with me at my email address nasirkhanpak25@gmail.comThanks in advance. Wish you best for luck.

Hi Lợi, can you send me full code for this project? I have a project about image processing using Machine Learning and I do not know read a file to a buffer and transfer data from a buffer to another buffer. My email is lehongtuandinh@gmail.com. Thanh you very much for your help!!!

hello sir, please could yo e-mail me the full code (juanrome93@gmail.com) i'm trying to do a project in which i need to load an image in a fpga to do some processing to it, it would very helpfully to have you full code.

Sir, I'm unable to execute the code because I did not understand that what are the total memory and SizeOflengthReal-1. I'm doing a project on that.So can you send me the code please...?my g-mail address is:sandhyavasanthapanduri@gmail.com

The provided code is a good start in image processing on FPGA. Spend some time to figure it out. Total memory is the memory to read the image data from .hex file.SizeOflengthReal-1 is the size of the total memory. Image size is 768x512 pixels. Each pixel has 3 data (R-G-B). Each datum R or G or B has 8 bits. Then you can calculate the total memory size.

Could anyone explain how he computed file size in byte (the 4 bytes after 2 signature bytes 'BM' in BITMAP header) please? I'm very confuse. I tried to convert to hexadecimal then compute the file size but it look like not true.

Hi all, The provided information on this post are pretty enough for you to get started with image processing on FPGA. Please spend some time to figure it out so that you can learn a lot from the experience. This post is a tutorial for image processing on FPGA. Full code will not be provided.Thanks. Admin

This post is a tutorial for image processing on FPGA. Full code is not given, but the major part for reading and writing image were provided. Please spend some time to figure it out so that you can learn a lot from the experience.

Yes,but i am not able to undertsand where the syntax error is ,even in write module it shows same errors,like near "[": expecting: ';',as above errors,i don't know how to correct it.There is also error for parameter in read as well as write module,near "#": expecting: ';'

Amazing... Thanks for uploading this project online. I am new to FPGAs and trying to learn image processing on FPGA. This project is an ideal to start up with. Could you please share source code with me on prashantborhade36@gmail.com

Hello, I am a project with Xilinx FPGA. currently, I can not input a bitmap in my project code.If you share your full code. my project will upgrade.Could you send me full code?My email address is shun435@gmail.com.Thank you for your help.

Hello, I am a project with Xilinx FPGA. currently, I can not input a bitmap in my project code.If you share your full code. my project will upgrade.Could you send me full code?My email address is shun435@gmail.com.Thank you for your help.

Hi, first of all many thanks for putting up these codes. I have used this as a reference material to build a verilog code that could invert a grayscale image. You have here used system verilog functions like $fopen and $fwirte. When I compile the program it states that these system functions are not synthesizable. Did you have the same issue?

Can i have the full coding please ? Because it is a very useful reference for my fyp which is implementation of fractal image compression on FPGA. I can share you my full coding once I get the results. My email is matrices3176@gmail.com

Helloi want to use an image in my laptop as input of testbench.i do not know verilog code for this.my mean is that i give the address of image(address of place that my image saved in my laptop) and use from that image such as input.please help me.thank you

Hi VanI have a trouble processing the imageand I can't see the right output resultthis is my email:ayn77543@gmail.comIf you see this comment can you send a email to me so that I can tell more details.Thanks a lot.