Skip to content

Commit d2e7335

Browse files
committed
Merge branch 'main' of https://github.com/amichai-bd/fpga_mafia_wiki into shmuel_doc
2 parents 5d388f0 + d9780e8 commit d2e7335

File tree

85 files changed

+1769
-297
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1769
-297
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
# Create a new Git repo in build directory
3737
cd build
3838
git init
39-
git remote add origin https://x-access-token:${DEPLOY_TOKEN}@github.com/amichai-bd/fpga_mafia_wiki.git
39+
git remote add origin https://x-access-token:${DEPLOY_TOKEN}@github.com/FPGA-MAFIA/fpga_mafia_wiki.git
4040
git checkout -b gh-pages
4141
git add .
4242
git commit -m "Deploy website"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
[![Deploy_Docusaurus_Pages](https://github.com/amichai-bd/fpga_mafia_wiki/actions/workflows/deploy.yml/badge.svg)](https://github.com/amichai-bd/fpga_mafia_wiki/actions/workflows/deploy.yml)
1+
[![Deploy_Docusaurus_Pages](https://github.com/FPGA-MAFIA/fpga_mafia_wiki/actions/workflows/deploy.yml/badge.svg)](https://github.com/FPGA-MAFIA/fpga_mafia_wiki/actions/workflows/deploy.yml)
22
# fpga_mafia_wiki
33
The documentation for the fpga_maifa project
4-
The website: https://amichai-bd.github.io/fpga_mafia_wiki/
4+
The website: https://fpga-mafia.github.io/fpga_mafia_wiki/
55

66

77
## Deploying the Wiki

docs/IPs/IPs_intro.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
In order to communicate with the outside world, we use three IPs: VGA, UART and Keyboard.
2+
3+
The VGA IP is used to display information like on the screen, the UART IP is used to communicate with the fpga and the Keyboard IP is used to get the input from the keyboard.
4+
5+
In that chapter we are going to briefly explain how those IPs works and how to use them in our project.

docs/IPs/uart.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
In that section we are going to briefly explain how the UART IP works and how to use it in our project. For complete information about the UART IP and how its implemented, please refer to the [UART Tile Project](https://github.com/amichai-bd/riscv-multi-core-lotr/blob/master/doc/UART_IO_doc/Uart%20Tile%20final%201p0.pdf) documentation.
2+
3+
- UART, or Universal Asynchronous Receiver-Transmitter, is a communication protocol commonly used to transmit and receive data between electronic devices. It enables the serial transmission of data, allowing devices to communicate over a pair of wires. UART operates asynchronously, meaning there is no separate clock signal; instead, both the transmitting and receiving devices agree on a specific baud rate to synchronize their communication. This makes UART a flexible and widely adopted standard for serial communication in various applications, such as connecting devices like microcontrollers, sensors, and other peripherals.
4+
5+
- We use UART to communicate with the FPGA. It helps us read data from the FPGA, like what's in its registers, debugging and more. We can also write data to the cores placed on the FPGA, such as initializing instruction and data memory. The write ability allows us to load programs to the FPGA and run them without creating `*.mif` files that represents instruction and data memory. Such process allows us to compile the design only once and then load different programs to the FPGA without the need to recompile the design.
6+
7+
## How to use the UART IP in our project
8+
### UART interface
9+
- We communicate with UART using software interface. The interface is just a piece of code running on a Host device. The interface on one side interacts with a user by a friendly Py-Terminal and communicates with the Device via USB serial transfers.
10+
- To run the interface please install the following packages:
11+
12+
```
13+
pip install serial
14+
```
15+
```
16+
pip install pySerial
17+
```
18+
note: if you have any problems installing the packages using `gitBash` then you can install them in `windows power shell`. To open `windows power shell` just type `windows power shell` in the search bar and click on the first result. Then you can install the packages using the same commands as above.
19+
20+
- To run the interface, go to `fpga_mafia\lotr_orig\pyterminal\src` folder and type `python ./uart_term.py`. This will open the terminal.
21+
- Choose the communication port. In our example we choose COM3 (you may have other available ports instead ).
22+
![uart_sw_interface.png](/snapshots/uart_sw_interface.png)
23+
24+
**important**:to make the following command works you should have the FPGA connected to the computer and to the UART. Since it may not be the case than now you may focus only on the interface options instead of the implementation. We will explain it on a real example [here](/docs/fpga/snake_game/connect_uart.md)
25+
-W write chosen single word to the device at a specific address.
26+
-R read a single word from the device at a specific address.
27+
-WB write a burst of words from a file on the host to the device starting at a specific address.
28+
-RB read a burst of words from the device starting at a specific address to a file on the host. You can choose the transfer size.
29+
-Q quit the terminal.
30+
31+
### UART cable
32+
The connection to the FPGA board is done using a USB to TTL converter [cable](https://www.amazon.com/Serial-Adapter-Signal-Prolific-Windows/dp/B08BLKBK1K?th=1). One side is connected to the computer and the other side is connected to the FPGA GPIO pins.
33+
34+
![usb_ttl_converter.png](/snapshots/usb_ttl_converter.png)
35+
![fpga_gpio.png](/snapshots/fpga_gpio.png)
36+
37+
| Source | Destination | Comment |
38+
|------------|-------------|----------|
39+
| White(TXD) | PIN_AA15 | |
40+
| Green(RXD) | PIN_AA14 | |
41+
| Black(GND) | GND | |
42+
| Red(VCC) | | floating |
43+
44+
![uart_gpio_connection.png](/snapshots/uart_gpio_connection.png)
45+
46+
**note**: In case you have USB to TTL converter with 6 pins than use the following table:
47+
- GND is black
48+
- VCC is red
49+
- TXD is orange
50+
- RXD is yellow
51+
52+
Generally speaking we finished the explanations we need to use the UART. We know that the explanations here are very general. Do not worry if you do not understand everything here. We will explain it in details in real example. Just remember what each option means in the sw interface and how to connect the UART cable to the FPGA.
53+
54+
55+
56+
57+
58+
59+
60+
61+

docs/IPs/vga.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
## Memory mapped I/O approach to access the VGA
2+
- Memory-mapped I/O (MMIO) is a technique where hardware devices communicate with the CPU via the same address space as the memory. This means that the memory and the I/O devices share the same address space. The CPU can read and write to specific memory addresses, and the hardware device will respond to these commands. This is a very simple and efficient way to communicate with hardware devices. each device has a specific address range in the memory.
3+
4+
- In our project we divide the memory into 4 parts:[^1,2]
5+
- The first part is the instruction memory, it hold the instructions of the program.
6+
- The second part is the data memory, it hold the data of the program, static data and dynamic data as defined in the linker script.
7+
- The third part is the CR_MEM which hold some control registers to communicate with the FPGA.
8+
- The fourth part is the VGA memory which hold the data to be displayed on the screen.
9+
10+
![mem_regions.png](/snapshots/mem_regions.png)
11+
12+
- VGA_MEM is the memory region that responsible for communicating with the screen. Any writing to a certain area in this memory region will be reflected to the screen and in addition to that the processor can read the status of a certain pixel assuming that the software is interested in it. There is an option for this memory area to be initialized to zero by the
13+
software that run on the processor if it so wishes. The memory size is control by the parameters inside `package file` of a specific core. The access to VGA_MEM is a dual-port access because both the processor and the VGA controller can access this memory area together. The processor accesses VGA_MEM in the Memory stage. The driver that pulls the information from this memory region to the screen is the VGA Controller. In the simulation we used behavioral memory, and on the FPGA, we used the on-die FPGA memory (as same as I_MEM and D_MEM).
14+
All the memory regions that have been described so far are wrapped by mem_wrap so that at the level of this component the address is checked, and the reference is made to the relevant memory space. In relation to VGA_MEM, this memory component is wrapped by the VGA Controller and the VGA Controller is a component of mem_wrap. That is, every request to the memory area of the VGA goes through the processor, passes through the mem_wrap to the VGA Controller and then reaches the memory area of the VGA.
15+
16+
## VGA controller and protocol specification
17+
- **Important Note** : Before reading the following information, you may refer to the following [video](https://www.youtube.com/watch?v=4enWoVHCykI) and also the following [link](https://embeddedthoughts.com/2016/07/29/driving-a-vga-monitor-using-an-fpga/) to get a better understanding of how the VGA works. [^4]. Its not that necessary to understand the following information, but it will help you to understand the VGA controller and the protocol specification.
18+
You can skip the technical details and go directly to the Implementation of VGA in our project section. For any question, please [contact us](/docs/contact_us/contact.md).
19+
20+
- The resolution of our target screen is 640×480. There are 640 vertical bits lines and 480 horizontal bits lines. Overall, the screen contains 80×480 = 38,400 bytes, and if we take into account that the size of a word is 4 bytes, the screen contains 9600 words. Each pixel on the screen is represented by a single bit, as a result, the total number of pixels is 640×480 = 307,200 pixels. The VGA support 12 bit RGB[^3], but we decided that having such a large amount of memory was a waste. So,
21+
we implemented a monochromatic screen, which each pixel is either on or off.
22+
23+
- The refresh rate of the screen is 60Hz, which means that the screen shows 60 frames(pictures) per second. Therefore the frequency of updating each pixel must be approximately 25.2Mhz(will be explained soon). **In our design we will choose 25Mhz because of technical issues involving of generating 25.2Mhz**
24+
25+
### Horizontal Synchronization
26+
The following diagram shows the wave diagram of the horizontal synchronization signal. We will look at the hsync (horizontal synchronization) signal and how it relates to how the electron beam of the [CRT monitor](https://en.wikipedia.org/wiki/Cathode-ray_tube) traverses across the CRT monitor. In the Figure we can see a CRT monitor with a black border, and the reason is because older CRT monitors did have that black border and it is part of the scanning pattern that we do. That is, we do pass the electron beam across the black border too, however we don't show any pixels over there. The hsync signal is a periodic digital signal that goes between zero and one logic. Based on the value of that signal the CRT monitor generates a sawtooth signal which moves the electron beam across the
27+
screen. The period of hsync signal is between 0 all the way to 799, which is 800. Suppose we start at the point marked 0 in the wave diagram of the hsync signal as shown in the figure, in principle we can start at any point we want because the signal is periodic. Point 0 is the start of the screen, this point located in the
28+
visible portion of the screen, not the border. We set the hsync signal to 1 all the way to 639 which means the electron beam will travels across the CRT monitor from left to right. We can observe that the sawtooth signal in this section is going all the way up, but it didn't finish though. What is happens next is
29+
that the electron beam goes through the right border (front porch) for exactly 16 clock cycles (not the system clock cycle). Then, the horizontal line must go backwards for 96 clock cycles, this is what we call the retrace and the sawtooth signal in this section is going all the way down to zero. In the final stage, relative to the point where we started (0) and because the signal is periodic the electron beam goes through the left border (back porch) for exactly 48 clock cycles. Realization of the hsync signal is
30+
basically by a simple counter which goes from 0 to 799 (modulo 800).
31+
32+
- Horizontal synchronization signal
33+
![horizontal_synchronization_signal.png](/snapshots/horizontal_synchronization_signal.png)
34+
35+
- Horizontal timing
36+
![horizontal_timing_vga.png](/snapshots/horizontal_timing_vga.png)
37+
38+
### Vertical Synchronization
39+
The following diagram shows the wave diagram of the vertical synchronization signal. Now, we will look at the vsync (vertical synchronization) signal and how it relates to how the electron beam of the CRT monitor traverses across the CRT monitor. The horizontal synchronization signal allowed us to move the electron beam or the scanning of the pixels from left to right, so we need another signal which goes from top to bottom, this is where the vertical synchronization signal comes into play. We want to go from top to
40+
bottom in 1/60 seconds because we have a refresh rate of 60Hz. vsync signal is very similar to hsync signal so the vsync signal is also a periodic digital signal that goes
41+
between zero and one logic. Suppose we start at the point marked 0 in the wave diagram of the vsync signal in Figure 12, here also we can start at any point we want because the signal is periodic. Point 0 is the start of the screen, this point located in the visible portion of the screen, not the border. We set the vsync signal to 1 all the way to 479 which means the electron beam will travers across the CRT monitor from top to bottom. What is happens next is that the electron beam goes through the bottom border (front porch) for exactly 10 clock cycles (not the system clock cycle). Then, the vertical line must go backwards for 2 clock cycles, this is the retrace. In the final stage, relative to the point where we started
42+
(0) and because the signal is periodic the electron beam goes through the top border (back porch) for exactly 33 clock cycles. Realization of the vsync signal is also basically by a simple counter which goes from 0 to 524 (modulo 525)
43+
44+
- Vertical synchronization signal
45+
![vertical_synchronization_signal.png](/snapshots/vertical_synchronization_signal.png)
46+
47+
- Vertical timing
48+
![vertical_timing_vga.png](/snapshots/vertical_timing_vga.png)
49+
50+
### Complete VGA screen scan picture
51+
![complete_vga_signals.png](/snapshots/complete_vga_signals.png)
52+
53+
54+
- explanation of the 25.2Mhz frequency: we need to update 60 times 800x525 pixels per second. So, the frequency of updating each pixel must be approximately 25.2Mhz.
55+
56+
## Implementation of VGA in our project
57+
- we divide VGA into 3 files
58+
- `big_core_vga_sync_gen.sv` (core name can be changed depending on the core). This file is responsible for generating the hsync and vsync signals and the counters that count the pixels.
59+
- `big_core_vga_ctrl.sv` (core name can be changed depending on the core). This file is responsible for reading and writing the pixels from and to the VGA_MEM, creating the RGB signals and 25Mhz clock signal. Each character represented in a rectangular (see the following sections) instead of turning on each picture at every line separably. We make it because its easier to represent characters in that way considering some technical limitations in our project. If you feel confused now, please let us now and we will explain it in more details.
60+
- `vga_mem.sv` is the memory component of VGA_MEM.
61+
62+
- VGA modules hierarchy
63+
![vga_modules_hierarchy.png](/snapshots/vga_modules_hierarchy.png)
64+
65+
### character representation
66+
We mentioned rectangular in the previous sections, now we will try to explain it in more details.
67+
- Each character represented in 8x8 matrix. The matrix is 64 bits. so, each character is represented by 64 bits. We can see from the following figure that we can show 80 characters in each line and 60 characters in each column. So, the total number of characters that we can show on the screen is 80x60 = 4800 characters.
68+
69+
![the_vga_screen.png](/snapshots/the_vga_screen.png)
70+
71+
72+
![character_a.png](/snapshots/character_a.png)
73+
74+
- Lets understand how to represent the character `A`
75+
We look at each row and each "on" pixel considered as 1 and each "off" pixel (white) considered as 0. So, the the first row is 0x00000000, the second row is 0x00011000, the third row is 0x00111100 and so on...
76+
- We divide the matrix into first 4 rows (TOP) and the last 4 rows (BOTTOM).
77+
- Than, we represent the letter `A` as two parameters representing consecutive 4 top rows and 4 bottom rows in hexadecimal format in `/app/graphic_vga.h` file.
78+
```
79+
#define A_TOP 0x663C1800
80+
#define A_BOTTOM 0x00667E66
81+
```
82+
- You can see the full list of characters in `/app/graphic_vga.h` file ordered by ASCII code.
83+
```
84+
/* ASCII tables */
85+
unsigned int ASCII_TOP[97] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SPACE_TOP,
86+
0,0,0,0,0,0,0,0,0,0,COMMA_TOP,0,POINT_TOP,0,ZERO_TOP,ONE_TOP,TWO_TOP,
87+
THREE_TOP,FOUR_TOP,FIVE_TOP,SIX_TOP,SEVEN_TOP,EIGHT_TOP,NINE_TOP,0,0,0,0,0,0,0,A_TOP,
88+
B_TOP,C_TOP,D_TOP,E_TOP,F_TOP,G_TOP,H_TOP,I_TOP,J_TOP,K_TOP,L_TOP,M_TOP,
89+
N_TOP,O_TOP,P_TOP,Q_TOP,R_TOP,S_TOP,T_TOP,U_TOP,V_TOP,W_TOP,X_TOP,Y_TOP,Z_TOP};
90+
unsigned int ASCII_BOTTOM[97] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
91+
SPACE_BOTTOM,0,0,0,0,0,0,0,0,0,0,COMMA_BOTTOM,0,POINT_BOTTOM,0,ZERO_BOTTOM,
92+
ONE_BOTTOM,TWO_BOTTOM,THREE_BOTTOM,FOUR_BOTTOM,FIVE_BOTTOM,SIX_BOTTOM,
93+
SEVEN_BOTTOM,EIGHT_BOTTOM,NINE_BOTTOM,0,0,0,0,0,0,0,A_BOTTOM,B_BOTTOM,C_BOTTOM,D_BOTTOM,
94+
E_BOTTOM,F_BOTTOM,G_BOTTOM,H_BOTTOM,I_BOTTOM,J_BOTTOM,K_BOTTOM,L_BOTTOM,
95+
M_BOTTOM,N_BOTTOM,O_BOTTOM,P_BOTTOM,Q_BOTTOM,R_BOTTOM,S_BOTTOM,T_BOTTOM,
96+
U_BOTTOM,V_BOTTOM,W_BOTTOM,X_BOTTOM,Y_BOTTOM,Z_BOTTOM};
97+
98+
```
99+
100+
101+
102+
### Running simple vga test
103+
- We will run it on `core_rrv` core. You can run it on any core that have VGA support.
104+
- Open or add the following test to your core `/verif/core_rrv/tests/alive_vga.c`.
105+
```
106+
107+
#include "big_core_defines.h"
108+
#include "graphic_vga.h"
109+
110+
int main() {
111+
112+
rvc_printf("HELLO_WORLD");
113+
rvc_printf("GOOD DAY");
114+
115+
int num = 7;
116+
rvc_print_int(num);
117+
118+
return 0;
119+
120+
} // main()
121+
```
122+
123+
- Please make sure to add `print_vga_screen task` to print the screen.
124+
You can use the `/verif/core_rrv/tb/core_rrv_vga_tb.sv` test as a template.
125+
Do not forget to change the link to new TB in `/verif/core_rrv/tb/core_rrv_verif_list.f` file.
126+
127+
- run `/.build -dut core_rrv -test alive_vga -app -sim -gui`.
128+
- You should see the output in `/target/core_rrv/test/alive_vga/screen.log` file.
129+
- The content of that file will be:
130+
![vga_screen_shot.png](/snapshots/vga_screen_shot.png)
131+
132+
[^1] Please note that the size and addresses of the memory regions can be changed. The current values are defined in `package files` of the specific core.
133+
[^2] CR_MEM and VGA_MEM are not defined in all the cores.
134+
[^3] When implementing the VGA controller on FPGA, please refer to its manual to see the exact RGB format cause some may have 8 bits resolution instead of 12.
135+
[^4] This link is not directly related to our project, but it is a good video to understand how the VGA works and the system verilog code.

0 commit comments

Comments
 (0)