Search Microcontrollers

Sunday, September 7, 2014

FPGA - VGA Interface / 2

In the previous post I discussed the VGA standard and the implementation of a
vga_sync module using Verilog.

In this post we will try to understand how to use such sync module to output some graphics from the FPGA to a VGA compatible monitor,

Before going into that, a small issue I encountered with my FPGA board :

When outputting rgb colors from it, I clearly get a voltage which is lower than the expected 0.7V maximum, since the colors I can see on the monitor are pretty dark.
I initially thought that the I/O Bank used by signals was wrongly set to 2.5 or less Volts instead of 3.3V... but checking in Quartus II I found it was correctly set.


So, I wondered if the board designer / manufacturer chose the wrong resistors for the R,G and B signals (expecting 270 or 330 Ohm maximum)...


1K ?? Seriously??!! I mean, dude (or dudes/gals), whoever you are, you designed a wonderful board with LCD, RAM etc... and you fail a voltage divider calculation??!!


I don't know, there might be good reasons for going for very dark colors and anyhow I think I could fix the issue by soldering resistors in parallel.

Implementing the control module

Again, I am illustrating the example provided with my board, check previous post for details.

module vga_control_module
(
    CLK, RSTn,
Ready_Sig, Column_Addr_Sig, Row_Addr_Sig,
Red_Sig, Green_Sig, Blue_Sig
);
    input CLK;
    input RSTn;
    input Ready_Sig;
    input [10:0]Column_Addr_Sig;
    input [10:0]Row_Addr_Sig;
    output Red_Sig;
    output Green_Sig;
    output Blue_Sig;

This module gets the clock and reset signals from external pins and receives Ready_Sig plus the X and Y counters from the sync_module (check previous post for a detailed explanation).
It uses all this information to drive the three color components which, in the case of my board, are single bit, but it would be quite easy to provide a resistor based DAC to give more color depth and driving it with multiple bits.




Back to our module, at this point we need to use the  X / Y coordinates to assign a value to the R, G and B components.
In my example I will use a condition, but eventually you might fetch the value from RAM and display an image.

what I did was to add a 4 bit counter i and use it to generate binary color patterns

  reg [3:0]i;
 
always @ ( posedge CLK or negedge RSTn )
 if( !RSTn ) 
   i <=4'b0;
else if (Column_Addr_Sig == 11'd0 && Row_Addr_Sig == 11'd0) i <= 4'b0;
  else if (i == 4'b1111) i <=4'b0;
   else i <= i + 1'b1;

assign Red_Sig = Ready_Sig && Column_Addr_Sig[i];
assign Green_Sig = Ready_Sig && Row_Addr_Sig[i];
assign Blue_Sig = Ready_Sig && Row_Addr_Sig[2];

As you can see the Red and Green signals use the "i" bit of the X and Y coordinates, while the Blue signal always uses the third bit (2) of the Y coordinates (which will generate 8 pixel "fat" horizontal lines).
All the signals are masked with Ready_Sig to ensure they are silent outside the active area as per VGA specs.

Ah, by the way, in case you are wondering what the condition

else if (Column_Addr_Sig == 11'd0 
             && Row_Addr_Sig == 11'd0) i <= 4'b0;

is for, this is just to reset the i counter at the beginning of the frame, so that I can get a still image, else it might change at every frame since i is used together with X and Y. 
Also note that in my experiment I did not use a 100MHz clock, this is important because i is incremented at every clock, you might need to adjust that part if you are using a clock higher than the pixel clock (well, you might just get a different color pattern).

Finally you just need to wire everything together in a top_level design and assign the pins.
This is the result I obtained :


If we can consider this a form of art, I'd  like  to call this piece : "Art that makes sense, in a binary way".

:)

No comments: