Skip to content

Commit b262030

Browse files
committed
Adding VGA module and its testbench
1 parent b5b3e3d commit b262030

File tree

3 files changed

+232
-0
lines changed

3 files changed

+232
-0
lines changed

modules/vga/Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Include common Makefile
2+
include ../Makefile
3+
4+
INCDIR+=-I$(SYSTEMC_AMS_HOME)/include
5+
LIBDIR+=-L$(SYSTEMC_AMS_HOME)/lib-linux64
6+
LIBS+=-lsystemc-ams
7+
8+
# Defining preprocessor directive for debug
9+
ifdef IPS_DEBUG_EN
10+
CFLAGS += -DIPS_DEBUG_EN
11+
LFLAGS += -DIPS_DEBUG_EN
12+
endif # IPS_DEBUG_EN
13+
14+
# Defining preprocessor directive for dumping enable
15+
ifdef IPS_DUMP_EN
16+
CFLAGS += -DIPS_DUMP_EN
17+
LFLAGS += -DIPS_DUMP_EN
18+
endif # IPS_DUMP_EN
19+
20+
# Run the compiled file
21+
run:
22+
@./$(TARGET)
23+
24+
# Show waveform
25+
waveform:
26+
@gtkwave ips_vga.vcd

modules/vga/include/vga.hpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#ifndef IPS_VGA_MODEL_HPP
2+
#define IPS_VGA_MODEL_HPP
3+
4+
#include <systemc.h>
5+
6+
#define IPS_VGA_ACTIVE true
7+
#define IPS_VGA_INACTIVE false
8+
9+
/**
10+
* @brief VGA representation class
11+
*
12+
* @tparam CLK_FREQ - clock frequency in HHz of the VGA
13+
* @tparam H_ACTIVE - output horizontal active video pixels
14+
* @tparam H_FP - wait after the display period before the sync
15+
* horizontal pulse
16+
* @tparam H_SYNC_PULSE - assert HSYNC
17+
* @tparam H_BP - wait after the sync horizontal pulse before starting
18+
* the next display period
19+
* @tparam V_ACTIVE - output vertical active video pixels
20+
* @tparam V_FP - wait after the display period before the sync
21+
* vertical pulse
22+
* @tparam V_SYNC_PULSE - assert VSYNC
23+
* @tparam V_BP - wait after the sync vertical pulse before starting
24+
* the next display period
25+
*/
26+
template <
27+
unsigned int H_ACTIVE = 640,
28+
unsigned int H_FP = 16,
29+
unsigned int H_SYNC_PULSE = 96,
30+
unsigned int H_BP = 48,
31+
unsigned int V_ACTIVE = 480,
32+
unsigned int V_FP = 10,
33+
unsigned int V_SYNC_PULSE = 2,
34+
unsigned int V_BP = 33
35+
>
36+
SC_MODULE(vga)
37+
{
38+
protected:
39+
// Horizontal count
40+
int h_count;
41+
// Vertical count
42+
int v_count;
43+
public:
44+
// Input clock
45+
sc_core::sc_in<bool> clk;
46+
// Output horizontal synch
47+
sc_core::sc_out<bool> o_hsync;
48+
// Output vertical synch
49+
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
55+
56+
SC_CTOR(vga) : o_hsync("o_hsync"), o_vsync("o_vsync")
57+
{
58+
this->h_count = 0;
59+
this->v_count = 0;
60+
61+
SC_METHOD(run);
62+
sensitive << clk.pos();
63+
}
64+
65+
/**
66+
* @brief Override method
67+
* Compute the values output of the VGA
68+
*
69+
*/
70+
void run()
71+
{
72+
if (this->clk.read())
73+
{
74+
#ifdef IPS_DEBUG_EN
75+
std::cout << "@" << sc_core::sc_time_stamp().to_seconds() * 1e6 << "us" << std::endl;
76+
#endif // IPS_DEBUG_EN
77+
78+
// Increment H counter
79+
this->h_count++;
80+
81+
// HSYNC pulse
82+
if (this->h_count == H_SYNC_PULSE)
83+
{
84+
this->o_hsync.write(IPS_VGA_ACTIVE);
85+
}
86+
// End of H-sync pulse
87+
else if (this->h_count == (H_SYNC_PULSE + H_BP))
88+
{
89+
this->o_hsync.write(IPS_VGA_ACTIVE);
90+
}
91+
// H front porch
92+
else if (this->h_count == (H_SYNC_PULSE + H_BP + H_ACTIVE))
93+
{
94+
this->o_hsync.write(IPS_VGA_INACTIVE);
95+
}
96+
// End of HSYNC
97+
else if (this->h_count == (H_SYNC_PULSE + H_BP + H_ACTIVE + H_FP))
98+
{
99+
// Restart H counter
100+
this->o_hsync.write(IPS_VGA_ACTIVE);
101+
this->h_count = 0;
102+
103+
// Increment H counter
104+
this->v_count++;
105+
106+
// VSYNC pulse
107+
if (this->v_count == V_SYNC_PULSE)
108+
{
109+
this->o_vsync.write(IPS_VGA_INACTIVE);
110+
}
111+
// End of V-sync pulse
112+
else if (this->v_count == (V_SYNC_PULSE + V_BP))
113+
{
114+
this->o_vsync.write(IPS_VGA_ACTIVE);
115+
}
116+
// V front porch
117+
else if (this->v_count == (V_SYNC_PULSE + V_BP + V_ACTIVE))
118+
{
119+
this->o_vsync.write(IPS_VGA_INACTIVE);
120+
}
121+
// End of VSYNC
122+
else if (this->v_count == (V_SYNC_PULSE + V_BP + V_ACTIVE + V_FP))
123+
{
124+
this->o_vsync.write(IPS_VGA_ACTIVE);
125+
this->v_count = 0;
126+
}
127+
}
128+
129+
#ifdef IPS_DEBUG_EN
130+
this->o_v_count.write(this->v_count);
131+
this->o_h_count.write(this->h_count);
132+
#endif // IPS_DEBUG_EN
133+
}
134+
}
135+
};
136+
#endif // IPS_VGA_MODEL_HPP

modules/vga/src/vga_tb.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include <systemc.h>
2+
3+
#include "vga.hpp"
4+
5+
// 120 MHz
6+
#define CLK_FREQ 120000000
7+
#define H_ACTIVE 640
8+
#define H_FP 16
9+
#define H_SYNC_PULSE 96
10+
#define H_BP 48
11+
#define V_ACTIVE 480
12+
#define V_FP 10
13+
#define V_SYNC_PULSE 2
14+
#define V_BP 33
15+
#define TOTAL_PIXELES ((H_ACTIVE + H_FP + H_SYNC_PULSE + H_BP) *\
16+
(V_ACTIVE + V_FP + V_SYNC_PULSE + V_BP))
17+
18+
19+
int sc_main(int, char*[])
20+
{
21+
const double CLK_TIME = 1.0 / static_cast<double>(CLK_FREQ);
22+
const double SIM_TIME = CLK_TIME * static_cast<double>(TOTAL_PIXELES);
23+
24+
sc_time total_sim_time = sc_time(SIM_TIME, SC_SEC);
25+
26+
sc_core::sc_clock s_clk("clk", CLK_TIME, sc_core::SC_SEC);
27+
sc_core::sc_signal<bool> s_hsync;
28+
sc_core::sc_signal<bool> s_vsync;
29+
30+
#ifdef IPS_DEBUG_EN
31+
sc_core::sc_signal<int> s_h_count;
32+
sc_core::sc_signal<int> s_v_count;
33+
#endif // IPS_DEBUG_EN
34+
35+
vga<
36+
H_ACTIVE, H_FP, H_SYNC_PULSE, H_BP,
37+
V_ACTIVE, V_FP, V_SYNC_PULSE, V_BP
38+
> ips_vga("ips_vga");
39+
ips_vga.clk(s_clk);
40+
ips_vga.o_hsync(s_hsync);
41+
ips_vga.o_vsync(s_vsync);
42+
#ifdef IPS_DEBUG_EN
43+
ips_vga.o_h_count(s_h_count);
44+
ips_vga.o_v_count(s_v_count);
45+
#endif // IPS_DEBUG_EN
46+
47+
#ifdef IPS_DUMP_EN
48+
sca_util::sca_trace_file* tf = sca_util::sca_create_vcd_trace_file("ips_vga");
49+
sca_trace(tf, s_clk, "clk");
50+
sca_trace(tf, s_hsync, "hsync");
51+
sca_trace(tf, s_vsync, "vsync");
52+
#ifdef IPS_DEBUG_EN
53+
sca_trace(tf, s_h_count, "h_count");
54+
sca_trace(tf, s_v_count, "v_count");
55+
#endif // IPS_DEBUG_EN
56+
#endif // IPS_DUMP_EN
57+
58+
std::cout << "@" << sc_time_stamp() << std::endl;
59+
std::cout << "Expected total sim time: " << total_sim_time << std::endl;
60+
61+
sc_start(SIM_TIME, sc_core::SC_SEC);
62+
63+
std::cout << "@" << sc_time_stamp() << std::endl;
64+
65+
#ifdef IPS_DUMP_EN
66+
sca_util::sca_close_vcd_trace_file(tf);
67+
#endif // IPS_DUMP_EN
68+
69+
return 0;
70+
}

0 commit comments

Comments
 (0)