📜 ⬆️ ⬇️

Graphic VGA-controller on SoC without HDL knowledge


Hello!
In a previous article, my colleague Des333 implemented a framebuffer for an LCD that runs on an ILI9341 graphics controller. However, writing it required substantial experience in developing the RTL code.

In addition, not everyone has an embedded LCD display at hand, but for sure there is a monitor with a VGA input. What can you do if there is not enough development experience for FPGA, but there is SoC, but do you want to do something interesting?

In this article we will describe how to develop a graphics controller, having a board with SoC (Altera Cyclone V), a display with VGA and minimal knowledge of HDL languages ​​(in our case, Verilog).
')
For example, we will use our scarves, but everything described will work on others.
Who cares, I ask under the cat.



I plan to tell in the following order:
  1. First, a little about the interaction architecture
  2. Briefly about connecting to VGA
  3. How to get the firmware using only Quartus Qsys
  4. How to explain to the kernel that there is a graphics controller. I'll tell you what to add to dtb and build drivers
  5. How to get the terminal and X on the display


I will use the CB-CV-SOM debug card that works in conjunction with the CV-SE-SOM SoDIMM module:

We have a shield for this debug board, in addition to VGA there are many interesting things (see metrotek.spb.ru/cbcvsom.html )

Architecture



To display the image on the display, we need a framebuffer , a driver and a scanning module, which will provide a link between the processor and the display, as well as provide a continuous frame update.

In SoC, the ARM (also called HPS - Hard Processing System) is connected to DDR3 memory (1 GB in our case), and it will contain our framebuffer. And in the FPGA there will be a module that we will need to do with Qsys.

Here is the diagram:



Everything will work like this:


How does VGA work



VGA (Video Graphics Array) is a video interface that uses an analog signal to transmit color information. The format of the signals and their behavior are similar to the television signal.
List of signals:
vga_vs_o - vertical sync
vga_hs_o - horizontal sync
vga_r_o - data of the red pixel component
vga_g_o - data of the green pixel component
vga_b_o - data is the blue component of the pixel

Shield supports 16 bits per color, which means that 5 bits are allocated to blue and red, and 6 bits to green. DAC is made according to the R2R scheme.

Monitors have different resolutions and image refresh rates. These parameters are adjusted in VGA using vertical and horizontal synchronization. Which have the following parameters:
  1. The clock frequency of the appearance of new pixels.
  2. Front porch - sync pulse quenching time.
  3. Back porch is the rise time of the sync pulse.
  4. Sync - the duration of synchronization.
  5. Display Area is the point in time when information is transmitted.


Timeliness looks like this:



We will use the VGA 800x600 mode at 60 Hz, so the parameters are as follows ( parameters for other modes ):
Clock frequency 40 MHz
Horizontal sync:

Vertical sync:

FPGA Firmware



To get the firmware, we need the following modules in Qsys:


The processor comes with AXI H2F and F2H interfaces, the Altera IP cores have Avalon-ST and Avalon-MM interfaces, so an Interconnect module is also needed, which must convert from one interface to another and multiplex data streams. It will appear automatically when generating files.

Learn more about Frame Reader and Clocked Video Output here .
How to assemble the firmware and what settings are needed for HPS can be found in this article .

Altera pll


PLL settings.
Altera pll



Frame reader


Here are configured:

The parameters Bits per pixel per color plane and Number of color planes in parallel are associated with the driver and are explained below. Please note that the dimension of the interface with HPS coincides with the dimension of the Master port width .
Frame reader


Clocked Video Output


Here:

Clocked Video Output



Qsys Connections


And now we connect everything. Settings for the Frame Reader module are “hooked” to the h2f master, an interface for transferring f2h slave data. We connect Clocked Video Output with Frame Reader avalon_streaming_source -> din. Everything is outclk0 clocked.
Qsys Connections



And generate files by clicking Generate HDL ....

As mentioned above, the board is 16 bits, and 32 bits come out of the module, so you need to carefully assign the pins in the qsf file, or edit the output for yourself conveniently in the top project file. We need high bits of each color, they are more informative than low bits.

Please note that this is the first and only place where we edit the code. This is no longer required.

logic vga_v_sync; logic vga_h_sync; logic [31:0] vga_data; logic [7:0] vid_r; logic [7:0] vid_g; logic [7:0] vid_b; assign vga_r_o = vid_r[7:3]; assign vga_g_o = vid_g[7:2]; assign vga_b_o = vid_b[7:3]; assign vga_hs_o = vga_h_sync; assign vga_vs_o = vga_v_sync; assign { vid_r, vid_g, vid_b } = vga_data; 


Driver and dtb



We need an altvipfb driver.

Let us return to the parameters Bits per pixel per color plane and Number of color planes in parallel in Frame Reader . The driver says:
 if (bits_per_color != 8) { dev_err(&fbdev->pdev->dev, "bits-per-color is set to %i. Curently only 8 is supported.", bits_per_color); return -ENODEV; } if (!(fbdev->mem_word_width >= 32 && fbdev->mem_word_width % 32 == 0)) { dev_err(&fbdev->pdev->dev, "mem-word-width is set to %i. must be >= 32 and multiple of 32.", fbdev->mem_word_width); return -ENODEV; } 


The number of bits per color is only 8 and the word width must be greater or a multiple of 32. What is the reason for this restriction? Look further and see:

 /* settings for 32bit pixels */ info->var.red.offset = 16; info->var.red.length = 8; info->var.red.msb_right = 0; info->var.green.offset = 8; info->var.green.length = 8; info->var.green.msb_right = 0; info->var.blue.offset = 0; info->var.blue.length = 8; info->var.blue.msb_right = 0; 


It becomes clear that the driver works in the True color mode, writing the color in a 32-bit word (it is more convenient to align than 24), and it works only in this mode.

In order to build this driver, the following changes need to be made in the kernel config.

 CONFIG_FB_CFB_FILLRECT=m CONFIG_FB_CFB_COPYAREA=m CONFIG_FB_CFB_IMAGEBLIT=m CONFIG_FB_ALTERA_VIP=m 


In order for linux to know that we have a frame from Altera in the FPGA, the following magic words need to be written in dtb:
 hps_0_h2f: bridge@0xc0000000 { compatible = "altr,bridge-1.0", "simple-bus"; reg = < 0xc0000000 0x20000000 >; #address-cells = < 1 >; #size-cells = < 1 >; ranges = <0x00000000 0xc0000000 0x4080 >; alt_vip_vfr_1: vip2@0x0 { compatible = "ALTR,vip-frame-reader-13.0", "ALTR,vip-frame-reader-9.1"; reg = < 0x4000 0x00000080 >; max-width = < 800 >; /* MAX_IMAGE_WIDTH type NUMBER */ max-height = < 600 >; /* MAX_IMAGE_HEIGHT type NUMBER */ mem-word-width = < 0x80 >; bits-per-color = < 0x8 >; }; }; 


In the range parameter, the range of valid addresses from which the driver will read, and in reg = <0x4000 0x00000080> , the starting address and how many addresses are occupied by alt_vip. Mem-word-width is the Master port width parameter in Frame Reader .

Read more about dtb .

Starting the terminal and X's



Go to the device and load the driver:
 modprobe altvipfb modprobe fbcon 


Then we check if everything is good with the help of dmesg, and see if there is a similar line:
 [ 66.424283] altvipfb c0000000.vip2: fb0: altvipfb frame buffer device at 0x2c000000+0x12c000 


Hooray! Fb0 appeared:
 ls -l /dev/fb0 crw-rw---T 1 root fb 29, 0 Nov 26 10:13 /dev/fb0 


Then we display the console on the screen connected to the board:
 /sbin/getty 38400 tty1 

Set icewm and start with startx:

 apt-get install icewm icewm-themes startx 


Icewm



Total: we got a graphics controller, with minimal knowledge of HDL languages.

Source: https://habr.com/ru/post/282189/


All Articles