The RAH (Real-time Application Handler) protocol is designed to facilitate the transfer of data between a CPU and an FPGA, which is developed by Vicharak, And It allows the CPU to run various applications that send data to the FPGA. The RAH Services encapsulate the data into distinguishable data-frames identified by an app_id
and deliver these frames to the FPGA. On the FPGA side, the RAH design decodes the data and writes it to the corresponding APP_WR_FIFO
. Similarly, during the read cycle, the FPGA writes data into APP_RD_FIFO
, which is then encapsulated and delivered back to the CPU where it gets decoded.
This guide includes the capability to generate and manage multiple applications on both the CPU and FPGA using header files.
- CPU Applications: These applications generate data that needs to be sent to the FPGA.
- RAH Services: Encapsulates and decapsulates data frames based on the
app_id
. - FPGA RAH Design: Handles the decoding of incoming data frames and writes to the appropriate FIFO.
- APP_WR_FIFO: FIFO buffer where decoded data from CPU is written.
- APP_RD_FIFO: FIFO buffer where data generated by FPGA applications is written before being sent to the CPU.
- CPU Application: Generates data to be sent to the FPGA.
- RAH Services on CPU: Encapsulates the data into a data-frame, including the
app_id
. - RAH Design on FPGA: Receives the data-frame and decodes it.
- FPGA Application: Reads the decoded data from the appropriate
APP_WR_FIFO
.
- FPGA Application: Writes data to the
APP_RD_FIFO
. - RAH Design on FPGA: Encapsulates the data from
APP_RD_FIFO
into a data-frame. - RAH Services on CPU: Receives the data-frame and decodes it.
- CPU Application: Processes the received data.
-
CPU Application:
- Generate the data you wish to send to the FPGA.
- Identify the
app_id
associated with this data. - The data width of the encapsulated data-frame is 48-bit (6-bytes).Send the data in multiple of 6-bytes, if the data is not in multiple of 6-bytes then append it with psuedo data bytes and access the data bytes at FPGA side using index of the data-bytes.
-
Encapsulation by RAH Services:
- Call the RAH API to encapsulate the data. The API function might look like
rah_write(app_id, data, length)
. Wherelength
is number of bytes. - Ensure that the data is correctly encapsulated into a data-frame with the specified
app_id
. - The data will be encapsulated as 6-bytes per data-line of data-frame.
- Call the RAH API to encapsulate the data. The API function might look like
-
Transmission:
- The RAH Services will transmit the data-frame to the FPGA.
-
Decoding by RAH Design on FPGA:
- The FPGA RAH design will receive the data-frame and decode it.
- The decoded data will be written to the corresponding
APP_WR_FIFO
.
-
Reading from
APP_WR_FIFO
:- FPGA applications can request data from the FIFO using a function like
fifo_read(app_id)
. - The data associated with the
app_id
will be available for the application to process. - This is a 48-bit FIFO.
- FPGA applications can request data from the FIFO using a function like
-
FPGA Application:
- Generate the data you wish to send to the CPU.
- Write this data to the
APP_RD_FIFO
using APP_RD_FIFO_EN signal. - This is a 48-bit FIFO.
- Write data in FIFO in multiple of 6-bytes and is data is not multiple of 6-bytes then append it with psuedo data bytes and access the data at CPU side using index of data bytes.
-
Encapsulation by RAH Design on FPGA:
- The RAH design will read the data from
APP_RD_FIFO
. - The data will be encapsulated into a data-frame with the specified
app_id
.
- The RAH design will read the data from
-
Transmission:
- The data-frame will be transmitted to the CPU by the RAH design.
-
Decapsulation by RAH Services on CPU:
- The CPU RAH Services will receive the data-frame and decapsulate it.
- The decapsulated data will be made available to the CPU application.
-
Processing by CPU Application:
- The CPU application can access the received data using a function like
rah_read(app_id)
. - The data associated with the
app_id
will be available for the application to process. - The data will be received as 6-bytes per data-line.
- The CPU application can access the received data using a function like
NOTE: The allignment of the data to be send and recieve through out the RAH protocol is user defined. The user have to make sure that the data is sampled in the same way as it is alligned at the time of transmission. This valids for both (write and read) cycles.
-
Enable FPGA Communication from the Vicharak Utility
-
Install RAH service on the board by,
sudo apt update sudo apt install rah-service
Note
Rah service is being updated very frequently. So, it is recommended to update the rah service before using it.
To manage multiple applications on both the CPU and FPGA, you can define and include header files that specify the application identifiers (app_id
) and related configurations.
-
Define Applications and Use Application IDs in CPU Code:
// main.c #include <rah.h> #define APP_ID_1 1 #define APP_ID_2 2 #define APP_ID_3 3 void app1() { char data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; rah_write(APP_ID_1, data, 6); } void app2() { char data[] = { 0x00, 0x01, 0x00, 0x05, 0x05, 0x02, 0x70, 0x01, 0x03, 0x04, 0x05, 0x02 }; rah_write(APP_ID_2, data, sizeof(data)); } void app3() { char data[] = { 0x90, 0x01, 0x25, 0x05, 0x34, 0x02, 0x70, 0x01, 0x03, 0x04, 0x05, 0x02, 0x70, 0x67, 0x03, 0x78, 0x05, 0x65 }; rah_write(APP_ID_3, &data, sizeof(data)); } int main() { app1(); app2(); app3(); return 0; }
- Installation and running
//Compilation gcc filename.c -lrah //Running the executable ./a.out
For more information on the RAH API functions, refer to the RAH protocol's API documentation.
-
Define Applications in a Header File (rah_var_defs.vh):
// rah_var_defs.vh `define TOTAL_APPS 3 `define APP_ID_1 1 `define APP_ID_2 2 `define APP_ID_3 3 // Add more application IDs as needed `define GET_DATA_RAH(a) rd_data[a * RAH_PACKET_WIDTH +: RAH_PACKET_WIDTH] `define SET_DATA_RAH(a) wr_data[a * RAH_PACKET_WIDTH +: RAH_PACKET_WIDTH]
-
Include and Use Application IDs in FPGA Code:
// top.v `include "rah_var_defs.vh" module top ( .......... ); /* Accesssing data from APP_WR_FIFO */ assign rd_clk[`APP_ID_1] = rd_clk_app1; app1_recv #( .RAH_PACKET_WIDTH(RAH_PACKET_WIDTH) ) er ( .clk (rd_clk_app1), .data_queue_empty (data_queue_empty[`APP_ID_1]), .data_queue_almost_empty(data_queue_almost_empty[`APP_ID_1]), .request_data (request_data[`APP_ID_1]), .data_frame (`GET_DATA_RAH(`APP_ID_1)), .uart_tx_pin (uart_tx_pin) ); /* Writing data into APP_RD_FIFO */ assign wr_clk[`APP_ID_1] = wr_clk_app1; /* Include your module */ app1_trans #( .RAH_PACKET_WIDTH(RAH_PACKET_WIDTH) ) et ( .clk (wr_clk_app1), .data (`SET_DATA_RAH(`APP_ID_1)), .send_data (write_apps_data[`APP_ID_1]) ); // Add Applications as needed. endmodule
Note
The FIFOs used here for data transfer are asynchronous. So, it is mandatory to assign the read and write clocks for every application FIFO. It facilitates us Clock Domain Crossing (CDC) among RAH and different applications.
- Read from
APP_WR_FIFO
:reg [1:0] state = 0; localparam IDLE = 2'b00; localparam WAIT = 2'b01; localparam READ = 2'b10; always @(posedge clk) begin case (state) IDLE: begin if (!APP_WR_FIFO_empty_1) begin APP_WR_FIFO_EN_1 <= 1'b1; state <= WAIT; end end WAIT: begin APP_WR_FIFO_EN_1 <= 0; state <= READ; end READ: begin READ_DATA <= APP_WR_FIFO_READ_DATA_1 ; state <= IDLE; end default : state <= IDLE; endcase end
- Check if
APP_WR_FIFO
is empty. - Assert FIFO Enable signal.
- Wait for one clock period.
- Sample the data.
- Read data from FIFO using the read pointer.
-
Read from
APP_RD_FIFO
:char data[6]; rah_read(app_id, data, 6); // 6 is length of the data
-
Call
rah_read(app_id)
to get the data associated withapp_id
.
- Write to
APP_RD_FIFO
.:always @(posedge clk) begin case(state) .... WRITE: begin APP_RD_FIFO_EN <= 1; APP_RD_FIFO_DATA <= DATA; end .... end
- Assert high the Enable signals of FIFO.
- Write data to FIFO at the same clk edge.
- Write to
APP_WR_FIFO
:char data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; rah_write(app_id, data, sizeof(data));
- Call
rah_write(app_id, data, length)
to encapsulate and send data to FPGA. length
is the number of bytes.
This enhanced guide covers the essentials of using the RAH protocol for data transfer between a CPU and FPGA, including the management of multiple applications using header files. For more detailed API functions and specific implementation details, refer to the RAH protocol's technical documentation.