Skip to content

Commit 3b43fe7

Browse files
committed
Adding image to the VGA testbench to send the RGB pixels
1 parent 5ca3318 commit 3b43fe7

File tree

2 files changed

+160
-27
lines changed

2 files changed

+160
-27
lines changed

modules/vga/include/vga.hpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,21 @@ SC_MODULE(vga)
4343
public:
4444
// Input clock
4545
sc_core::sc_in<bool> clk;
46+
// Input pixel
47+
sc_core::sc_in<sc_uint<N> > red;
48+
sc_core::sc_in<sc_uint<N> > green;
49+
sc_core::sc_in<sc_uint<N> > blue;
4650
// Output horizontal synch
4751
sc_core::sc_out<bool> o_hsync;
4852
// Output vertical synch
4953
sc_core::sc_out<bool> o_vsync;
50-
#ifdef IPS_DEBUG_EN
51-
// For debug
52-
sc_core::sc_out<int> o_h_count;
53-
sc_core::sc_out<int> o_v_count;
54-
#endif // IPS_DEBUG_EN
54+
// Counter outputs
55+
sc_core::sc_out<unsigned int> o_h_count;
56+
sc_core::sc_out<unsigned int> o_v_count;
57+
// Output pixel
58+
sc_core::sc_out<sc_uint<N> > o_red;
59+
sc_core::sc_out<sc_uint<N> > o_green;
60+
sc_core::sc_out<sc_uint<N> > o_blue;
5561

5662
SC_CTOR(vga) : o_hsync("o_hsync"), o_vsync("o_vsync")
5763
{
@@ -126,10 +132,11 @@ SC_MODULE(vga)
126132
}
127133
}
128134

129-
#ifdef IPS_DEBUG_EN
130135
this->o_v_count.write(this->v_count);
131136
this->o_h_count.write(this->h_count);
132-
#endif // IPS_DEBUG_EN
137+
this->o_red.write(this->red.read());
138+
this->o_green.write(this->green.read());
139+
this->o_blue.write(this->blue.read());
133140
}
134141
}
135142
};

modules/vga/src/vga_tb.cpp

Lines changed: 146 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1+
#define int64 systemc_int64
2+
#define uint64 systemc_uint64
13
#include <systemc.h>
24

5+
#undef int64
6+
#undef uint64
7+
#define int64 opencv_int64
8+
#define uint64 opencv_uint64
9+
#include <opencv2/opencv.hpp>
10+
#undef int64
11+
#undef uint64
12+
313
#include "vga.hpp"
414

515

6-
// Main clock frequency in Hz - 120 MHz
7-
#define CLK_FREQ 120000000
16+
// Image path
17+
#define IPS_IMG_PATH_TB "../../tools/datagen/src/imgs/car_rgb_noisy_image.jpg"
18+
// Main clock frequency in Hz - 25.175 MHz
19+
#define CLK_FREQ 25175000
820
// VGA settings
921
#define H_ACTIVE 640
1022
#define H_FP 16
@@ -15,64 +27,178 @@
1527
#define V_SYNC_PULSE 2
1628
#define V_BP 33
1729
// Compute the total number of pixels
18-
#define TOTAL_PIXELES ((H_ACTIVE + H_FP + H_SYNC_PULSE + H_BP) *\
19-
(V_ACTIVE + V_FP + V_SYNC_PULSE + V_BP))
30+
#define TOTAL_VERTICAL (H_ACTIVE + H_FP + H_SYNC_PULSE + H_BP)
31+
#define TOTAL_HORIZONTAL (V_ACTIVE + V_FP + V_SYNC_PULSE + V_BP)
32+
#define TOTAL_PIXELES (TOTAL_VERTICAL * TOTAL_HORIZONTAL)
2033

2134

2235
int sc_main(int, char*[])
2336
{
37+
// Read image
38+
const std::string img_path = IPS_IMG_PATH_TB;
39+
40+
cv::Mat read_img = cv::imread(img_path, cv::IMREAD_COLOR);
41+
42+
// CV_8UC3 Type: 8-bit unsigned, 3 channels (e.g., for a color image)
43+
cv::Mat tx_img;
44+
read_img.convertTo(tx_img, CV_8UC3);
45+
46+
cv::Mat rx_data(TOTAL_HORIZONTAL, TOTAL_VERTICAL, CV_8UC3);
47+
cv::Mat rx_img(tx_img.size(), CV_8UC3);
48+
49+
#ifdef IPS_DEBUG_EN
50+
std::cout << "Loading image: " << img_path << std::endl;
51+
#endif // IPS_DEBUG_EN
52+
53+
// Check if the image is loaded successfully
54+
if (tx_img.empty())
55+
{
56+
std::cerr << "Error: Could not open or find the image!" << std::endl;
57+
exit(EXIT_FAILURE);
58+
}
59+
60+
#ifdef IPS_DEBUG_EN
61+
std::cout << "TX image info: ";
62+
std::cout << "rows = " << tx_img.rows;
63+
std::cout << " cols = " << tx_img.cols;
64+
std::cout << " channels = " << tx_img.channels() << std::endl;
65+
66+
std::cout << "RX data info: ";
67+
std::cout << "rows = " << rx_data.rows;
68+
std::cout << " cols = " << rx_data.cols;
69+
std::cout << " channels = " << rx_data.channels() << std::endl;
70+
71+
std::cout << "RX image info: ";
72+
std::cout << "rows = " << rx_img.rows;
73+
std::cout << " cols = " << rx_img.cols;
74+
std::cout << " channels = " << rx_img.channels() << std::endl;
75+
#endif // IPS_DEBUG_EN
76+
2477
// Compute the clock time in seconds
2578
const double CLK_TIME = 1.0 / static_cast<double>(CLK_FREQ);
2679
// Compute the total simulation based on the total amount of pixels in the
2780
// screen
2881
const double SIM_TIME = CLK_TIME * static_cast<double>(TOTAL_PIXELES);
2982

3083
// Signals to use
84+
// -- Inputs
3185
sc_core::sc_clock clk("clk", CLK_TIME, sc_core::SC_SEC);
86+
sc_core::sc_signal<sc_uint<8> > s_tx_red;
87+
sc_core::sc_signal<sc_uint<8> > s_tx_green;
88+
sc_core::sc_signal<sc_uint<8> > s_tx_blue;
89+
// -- Outputs
3290
sc_core::sc_signal<bool> s_hsync;
3391
sc_core::sc_signal<bool> s_vsync;
34-
#ifdef IPS_DEBUG_EN
35-
sc_core::sc_signal<int> s_h_count;
36-
sc_core::sc_signal<int> s_v_count;
37-
#endif // IPS_DEBUG_EN
92+
sc_core::sc_signal<unsigned int> s_h_count;
93+
sc_core::sc_signal<unsigned int> s_v_count;
94+
sc_core::sc_signal<sc_uint<8> > s_rx_red;
95+
sc_core::sc_signal<sc_uint<8> > s_rx_green;
96+
sc_core::sc_signal<sc_uint<8> > s_rx_blue;
3897

3998
// VGA module instanciation and connections
4099
vga<
41100
H_ACTIVE, H_FP, H_SYNC_PULSE, H_BP,
42101
V_ACTIVE, V_FP, V_SYNC_PULSE, V_BP
43102
> ips_vga("ips_vga");
44103
ips_vga.clk(clk);
104+
ips_vga.red(s_tx_red);
105+
ips_vga.green(s_tx_green);
106+
ips_vga.blue(s_tx_blue);
45107
ips_vga.o_hsync(s_hsync);
46108
ips_vga.o_vsync(s_vsync);
47-
#ifdef IPS_DEBUG_EN
48109
ips_vga.o_h_count(s_h_count);
49110
ips_vga.o_v_count(s_v_count);
50-
#endif // IPS_DEBUG_EN
111+
ips_vga.o_red(s_rx_red);
112+
ips_vga.o_green(s_rx_green);
113+
ips_vga.o_blue(s_rx_blue);
51114

52115
// Signals to dump
53116
#ifdef IPS_DUMP_EN
54-
sca_util::sca_trace_file* tf = sca_util::sca_create_vcd_trace_file("ips_vga");
117+
sc_trace_file* wf = sc_create_vcd_trace_file("ips_vga");
55118

56-
sca_trace(tf, clk, "clk");
57-
sca_trace(tf, s_hsync, "hsync");
58-
sca_trace(tf, s_vsync, "vsync");
59-
#ifdef IPS_DEBUG_EN
60-
sca_trace(tf, s_h_count, "h_count");
61-
sca_trace(tf, s_v_count, "v_count");
62-
#endif // IPS_DEBUG_EN
119+
sc_trace(wf, clk, "clk");
120+
sc_trace(wf, s_tx_red, "tx_red");
121+
sc_trace(wf, s_tx_green, "tx_green");
122+
sc_trace(wf, s_tx_blue, "tx_blue");
123+
sc_trace(wf, s_hsync, "hsync");
124+
sc_trace(wf, s_vsync, "vsync");
125+
sc_trace(wf, s_h_count, "h_count");
126+
sc_trace(wf, s_v_count, "v_count");
127+
sc_trace(wf, s_rx_red, "rx_red");
128+
sc_trace(wf, s_rx_green, "rx_green");
129+
sc_trace(wf, s_rx_blue, "rx_blue");
63130
#endif // IPS_DUMP_EN
64131

65132
// Start time
66133
std::cout << "@" << sc_time_stamp() << std::endl;
67134

68-
sc_start(SIM_TIME, sc_core::SC_SEC);
135+
double total_sim_time = 0.0;
136+
137+
while (SIM_TIME > total_sim_time)
138+
{
139+
const int IMG_ROW = s_v_count.read() - (V_SYNC_PULSE + V_BP);
140+
const int IMG_COL = s_h_count.read() - (H_SYNC_PULSE + H_BP);
141+
142+
#ifdef IPS_DEBUG_EN
143+
std::cout << "TX image: ";
144+
std::cout << "row = " << IMG_ROW;
145+
std::cout << " col = " << IMG_COL;
146+
#endif // IPS_DEBUG_EN
147+
148+
if ((IMG_ROW < 0) || (IMG_COL < 0) || (IMG_ROW >= V_ACTIVE) || (IMG_COL >= H_ACTIVE))
149+
{
150+
s_tx_red.write(0);
151+
s_tx_green.write(0);
152+
s_tx_blue.write(0);
153+
154+
#ifdef IPS_DEBUG_EN
155+
std::cout << " dpixel = (0,0,0) " << std::endl;
156+
#endif // IPS_DEBUG_EN
157+
}
158+
else
159+
{
160+
cv::Vec3b pixel = tx_img.at<cv::Vec3b>(IMG_ROW, IMG_COL, 0);
161+
162+
s_tx_red.write(static_cast<sc_uint<8> >(pixel[0]));
163+
s_tx_green.write(static_cast<sc_uint<8> >(pixel[1]));
164+
s_tx_blue.write(static_cast<sc_uint<8> >(pixel[2]));
165+
166+
#ifdef IPS_DEBUG_EN
167+
std::cout << " ipixel = (" << static_cast<int>(pixel[0]) << ","
168+
<< static_cast<int>(pixel[1]) << "," << static_cast<int>(pixel[2])
169+
<< ")" << std::endl;
170+
#endif // IPS_DEBUG_EN
171+
}
172+
173+
total_sim_time += CLK_TIME;
174+
sc_start(CLK_TIME, sc_core::SC_SEC);
175+
176+
if ((IMG_ROW < 0) || (IMG_COL < 0) || (IMG_ROW >= V_ACTIVE) || (IMG_COL >= H_ACTIVE))
177+
{
178+
cv::Vec3b pixel(0, 0, 0);
179+
rx_data.at<cv::Vec3b>(s_v_count.read(), s_h_count.read()) = pixel;
180+
}
181+
else
182+
{
183+
cv::Vec3b pixel = cv::Vec3b(s_rx_red.read(), s_rx_green.read(), s_rx_blue.read());
184+
rx_data.at<cv::Vec3b>(s_v_count.read(), s_h_count.read()) = pixel;
185+
rx_img.at<cv::Vec3b>(IMG_ROW, IMG_COL) = pixel;
186+
}
187+
}
69188

70189
// End time
71190
std::cout << "@" << sc_time_stamp() << std::endl;
72191

73192
#ifdef IPS_DUMP_EN
74-
sca_util::sca_close_vcd_trace_file(tf);
193+
sc_close_vcd_trace_file(wf);
75194
#endif // IPS_DUMP_EN
76195

196+
// Show the images in their respective windows
197+
cv::imshow("TX image", tx_img);
198+
cv::imshow("RX image", rx_img);
199+
200+
// Wait for a key press indefinitely to keep the windows open
201+
cv::waitKey(0);
202+
77203
return 0;
78204
}

0 commit comments

Comments
 (0)