Skip to content

Commit fa8dec3

Browse files
committed
Add VGA module to Virtual Prototype
1 parent b1699b8 commit fa8dec3

File tree

8 files changed

+441
-46
lines changed

8 files changed

+441
-46
lines changed

modules/VirtualPrototype/FreeRTOS/freertos_test.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -415,30 +415,58 @@ void save_image_from_mem(int image_id)
415415
printf("Saved image with id %0d\n", image_id);
416416
}
417417

418+
void receive_image()
419+
{
420+
unsigned char *start_reception = (unsigned char *) IMG_INPUT_START_ADDRESS_LO;
421+
unsigned char *receive_status = (unsigned char *) IMG_INPUT_DONE_ADDRESS_LO;
422+
unsigned char receive_status_result;
423+
424+
const TickType_t xDelay = 200;
425+
426+
printf("Preparing to receive image from VGA\n");
427+
428+
*start_reception = 1;
429+
430+
printf("Sent start signal to receiver\n");
431+
432+
memcpy(&receive_status_result, receive_status, sizeof(char));
433+
while(receive_status_result == 0)
434+
{
435+
printf("\tReceiver still receiving data\n");
436+
vTaskDelay(xDelay);
437+
memcpy(&receive_status_result, receive_status, sizeof(char));
438+
}
439+
printf("Receive process finished in the receiver\n");
440+
}
441+
418442
static void testbench(void *pParameter) {
443+
receive_image();
444+
445+
save_image_from_mem(0);
446+
419447
convert_to_grayscale();
420448

421449
save_image_from_mem(1);
422450

423-
filter_image();
451+
// filter_image();
424452

425-
save_image_from_mem(2);
453+
// save_image_from_mem(2);
426454

427-
obtain_gradients_sobel();
455+
// obtain_gradients_sobel();
428456

429-
save_image_from_mem(3);
457+
// save_image_from_mem(3);
430458

431-
unificate_img();
459+
// unificate_img();
432460

433-
save_image_from_mem(4);
461+
// save_image_from_mem(4);
434462

435-
copy_data();
463+
// copy_data();
436464

437-
save_image_from_mem(5);
465+
// save_image_from_mem(5);
438466

439-
transmit_data(IMAG_ROWS * IMAG_COLS);
467+
// transmit_data(IMAG_ROWS * IMAG_COLS);
440468

441-
save_image_from_mem(6);
469+
// save_image_from_mem(6);
442470
}
443471

444472
int main( void )

modules/VirtualPrototype/include/important_defines.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,44 @@
1616
#define IPS_OUT_TYPE_TB float
1717
#endif // IPS_OUT_TYPE_TB
1818

19+
// VGA settings
20+
#ifndef IPS_H_ACTIVE
21+
#define IPS_H_ACTIVE 640
22+
#endif // IPS_H_ACTIVE
23+
#ifndef IPS_H_FP
24+
#define IPS_H_FP 16
25+
#endif // IPS_H_FP
26+
#ifndef IPS_H_SYNC_PULSE
27+
#define IPS_H_SYNC_PULSE 96
28+
#endif // IPS_H_SYNC_PULSE
29+
#ifndef IPS_H_BP
30+
#define IPS_H_BP 48
31+
#endif // IPS_H_BP
32+
#ifndef IPS_V_ACTIVE
33+
#define IPS_V_ACTIVE 480
34+
#endif // IPS_V_ACTIVE
35+
#ifndef IPS_V_FP
36+
#define IPS_V_FP 10
37+
#endif // IPS_V_FP
38+
#ifndef IPS_V_SYNC_PULSE
39+
#define IPS_V_SYNC_PULSE 2
40+
#endif // IPS_V_SYNC_PULSE
41+
#ifndef IPS_V_BP
42+
#define IPS_V_BP 33
43+
#endif // IPS_V_BP
44+
// Compute the total number of pixels
45+
#define IPS_TOTAL_VERTICAL (IPS_H_ACTIVE + IPS_H_FP + IPS_H_SYNC_PULSE + IPS_H_BP)
46+
#define IPS_TOTAL_HORIZONTAL (IPS_V_ACTIVE + IPS_V_FP + IPS_V_SYNC_PULSE + IPS_V_BP)
47+
#define IPS_TOTAL_PIXELES (IPS_TOTAL_VERTICAL * IPS_TOTAL_HORIZONTAL)
48+
// Number of bits for ADC, DAC and VGA
49+
#ifndef IPS_BITS
50+
#define IPS_BITS 8
51+
#endif // IPS_BITS
52+
#ifndef IPS_VOLTAGE_MIN
53+
#define IPS_VOLTAGE_MIN 0
54+
#endif // IPS_VOLTAGE_MIN
55+
#ifndef IPS_VOLTAGE_MAX
56+
#define IPS_VOLTAGE_MAX 3300
57+
#endif // IPS_VOLTAGE_MAX
58+
1959
#endif // IMPORTANT_DEFINES_HPP
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#ifndef IPS_SEQ_ITEM_VGA_HPP
2+
#define IPS_SEQ_ITEM_VGA_HPP
3+
4+
#define int64 systemc_int64
5+
#define uint64 systemc_uint64
6+
#include <systemc.h>
7+
#include <systemc-ams.h>
8+
#undef int64
9+
#undef uint64
10+
#define int64 opencv_int64
11+
#define uint64 opencv_uint64
12+
#include <opencv2/opencv.hpp>
13+
#undef int64
14+
#undef uint64
15+
16+
#include "vunit.hpp"
17+
18+
// Image path
19+
#define IPS_IMG_PATH_TB "../../tools/datagen/src/imgs/car_rgb_noisy_image.jpg"
20+
21+
/**
22+
* @brief This class is used to generate the data for the AMS test
23+
*
24+
* @tparam BITS - the number of output bits of the digital pixel
25+
* @tparam H_ACTIVE - output horizontal active video pixels
26+
* @tparam H_FP - wait after the display period before the sync
27+
* horizontal pulse
28+
* @tparam H_SYNC_PULSE - assert HSYNC
29+
* @tparam H_BP - wait after the sync horizontal pulse before starting
30+
* the next display period
31+
* @tparam V_ACTIVE - output vertical active video pixels
32+
* @tparam V_FP - wait after the display period before the sync
33+
* vertical pulse
34+
* @tparam V_SYNC_PULSE - assert VSYNC
35+
* @tparam V_BP - wait after the sync vertical pulse before starting
36+
* the next display period
37+
*/
38+
template <
39+
unsigned int BITS = 8,
40+
unsigned int H_ACTIVE = 640,
41+
unsigned int H_FP = 16,
42+
unsigned int H_SYNC_PULSE = 96,
43+
unsigned int H_BP = 48,
44+
unsigned int V_ACTIVE = 480,
45+
unsigned int V_FP = 10,
46+
unsigned int V_SYNC_PULSE = 2,
47+
unsigned int V_BP = 33,
48+
int VMIN = 0,
49+
int VMAX = 5,
50+
VUnit VU = VUnit::v>
51+
SCA_TDF_MODULE(seq_item_vga)
52+
{
53+
protected:
54+
cv::Mat tx_img;
55+
// Min voltage value based on the voltage units
56+
const double V_MIN = static_cast<double>(VMIN) / static_cast<double>(VU);
57+
// Max voltage value based on the voltage units
58+
const double V_MAX = static_cast<double>(VMAX) / static_cast<double>(VU);
59+
// Max digital output code
60+
const double MAX_DIG = static_cast<double>((1 << BITS) - 1);
61+
62+
public:
63+
// Counters
64+
sca_tdf::sca_de::sca_in<unsigned int> hcount;
65+
sca_tdf::sca_de::sca_in<unsigned int> vcount;
66+
// Output pixel
67+
sca_tdf::sca_out<double> o_red;
68+
sca_tdf::sca_out<double> o_green;
69+
sca_tdf::sca_out<double> o_blue;
70+
71+
SC_CTOR(seq_item_vga)
72+
{
73+
// Read image
74+
const std::string img_path = IPS_IMG_PATH_TB;
75+
76+
cv::Mat read_img = cv::imread(img_path, cv::IMREAD_COLOR);
77+
78+
// CV_8UC3 Type: 8-bit unsigned, 3 channels (e.g., for a color image)
79+
read_img.convertTo(this->tx_img, CV_8UC3);
80+
81+
// Check if the image is loaded successfully
82+
if (this->tx_img.empty())
83+
{
84+
std::cerr << "Error: Could not open or find the image!" << std::endl;
85+
exit(EXIT_FAILURE);
86+
}
87+
}
88+
89+
void set_attributes()
90+
{
91+
// Propagation time from input to output
92+
set_timestep(sca_core::sca_time(1, sc_core::SC_NS));
93+
this->o_red.set_delay(17);
94+
this->o_green.set_delay(17);
95+
this->o_blue.set_delay(17);
96+
}
97+
98+
void processing()
99+
{
100+
const int IMG_ROW = static_cast<int>(this->vcount.read()) - (V_SYNC_PULSE + V_BP);
101+
const int IMG_COL = static_cast<int>(this->hcount.read()) - (H_SYNC_PULSE + H_BP);
102+
103+
if ((IMG_ROW < 0) || (IMG_COL < 0) || (IMG_ROW >= static_cast<int>(V_ACTIVE)) || (IMG_COL >= static_cast<int>(H_ACTIVE)))
104+
{
105+
this->o_red.write(0.0);
106+
this->o_green.write(0.0);
107+
this->o_blue.write(0.0);
108+
}
109+
else
110+
{
111+
if ((IMG_ROW >= this->tx_img.rows) || (IMG_COL >= this->tx_img.cols))
112+
{
113+
this->o_red.write(0.0);
114+
this->o_green.write(0.0);
115+
this->o_blue.write(0.0);
116+
}
117+
else
118+
{
119+
cv::Vec3b pixel = tx_img.at<cv::Vec3b>(IMG_ROW, IMG_COL, 0);
120+
121+
this->o_red.write(sc_uint2double(static_cast<sc_uint<BITS>>(pixel[0])));
122+
this->o_green.write(sc_uint2double(static_cast<sc_uint<BITS>>(pixel[1])));
123+
this->o_blue.write(sc_uint2double(static_cast<sc_uint<BITS>>(pixel[2])));
124+
}
125+
}
126+
}
127+
128+
/**
129+
* @brief Convert the digital signal into analog signal
130+
* The N-bit digital code is converted into an analog signal in a voltage
131+
* range from Vmin to Vmax
132+
*/
133+
double sc_uint2double(sc_uint<BITS> in)
134+
{
135+
double dig_in = static_cast<double>(in);
136+
return V_MIN + (dig_in / MAX_DIG) * (V_MAX - V_MIN);
137+
}
138+
};
139+
#endif // IPS_SEQ_ITEM_VGA_HPP
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#ifndef IPS_VGA_TLM_HPP
2+
#define IPS_VGA_TLM_HPP
3+
#include <systemc.h>
4+
using namespace sc_core;
5+
using namespace sc_dt;
6+
using namespace std;
7+
8+
#include <tlm.h>
9+
#include <tlm_utils/simple_initiator_socket.h>
10+
#include <tlm_utils/simple_target_socket.h>
11+
#include <tlm_utils/peq_with_cb_and_phase.h>
12+
13+
#include "common_func.hpp"
14+
#include "important_defines.hpp"
15+
#include "vga.hpp"
16+
#include "../src/img_target.cpp"
17+
18+
// Extended Unification TLM
19+
struct vga_tlm
20+
: public vga<
21+
IPS_BITS,
22+
IPS_H_ACTIVE, IPS_H_FP, IPS_H_SYNC_PULSE, IPS_H_BP,
23+
IPS_V_ACTIVE, IPS_V_FP, IPS_V_SYNC_PULSE, IPS_V_BP
24+
>, public img_target
25+
{
26+
protected:
27+
unsigned char* tmp_img;
28+
public:
29+
vga_tlm(sc_module_name name, bool use_prints_)
30+
: vga<
31+
IPS_BITS,
32+
IPS_H_ACTIVE, IPS_H_FP, IPS_H_SYNC_PULSE, IPS_H_BP,
33+
IPS_V_ACTIVE, IPS_V_FP, IPS_V_SYNC_PULSE, IPS_V_BP>((std::string(name) + "_HW_block").c_str()),
34+
img_target((std::string(name) + "_target").c_str())
35+
{
36+
this->use_prints = use_prints_;
37+
checkprintenableimgtar(use_prints);
38+
set_mem_attributes(IMG_INPUT_ADDRESS_LO, IMG_INPUT_SIZE+IMG_INPUT_START_SIZE+IMG_INPUT_DONE_SIZE);
39+
}
40+
41+
// Override do_when_transaction functions
42+
virtual void do_when_read_transaction(unsigned char *&data, unsigned int data_length, sc_dt::uint64 address);
43+
virtual void do_when_write_transaction(unsigned char *&data, unsigned int data_length, sc_dt::uint64 address);
44+
45+
//Backdoor access to memory
46+
void backdoor_write(unsigned char*&data, unsigned int data_length, sc_dt::uint64 address);
47+
void backdoor_read(unsigned char*&data, unsigned int data_length, sc_dt::uint64 address);
48+
49+
unsigned char *return_mem_ptr();
50+
};
51+
#endif // IPS_VGA_TLM_HPP

modules/VirtualPrototype/src/BusCtrl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ void BusCtrl::b_transport(tlm::tlm_generic_payload &trans,
5858
dbgmodprint(use_prints, "Writing/Reading to Sobel!");
5959
sobel_edge_detector_socket->b_transport(trans, delay);
6060
}
61-
else if ((IMG_INPUT_ADDRESS_LO / 4 <= adr && adr < IMG_INPUT_ADDRESS_HI / 4))
61+
else if ((IMG_INPUT_ADDRESS_LO / 4 <= adr && adr < IMG_INPUT_ADDRESS_HI / 4) ||
62+
(IMG_INPUT_START_ADDRESS_LO / 4 <= adr && adr < IMG_INPUT_START_ADDRESS_HI / 4) ||
63+
(IMG_INPUT_DONE_ADDRESS_LO / 4 <= adr && adr < IMG_INPUT_DONE_ADDRESS_HI / 4))
6264
{
6365
dbgmodprint(use_prints, "Writing/Reading to Receiver!");
6466
receiver_socket->b_transport(trans, delay);

0 commit comments

Comments
 (0)