Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the interface DE and TDF #26

Merged
merged 8 commits into from
Jul 23, 2024
12 changes: 9 additions & 3 deletions modules/adc/include/adc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,21 @@ SCA_TDF_MODULE(adc)
// Input analog voltage
sca_tdf::sca_in<double> in;
// Output digital code
sca_tdf::sca_out<sc_dt::sc_uint<BITS> > out;
sca_tdf::sca_de::sca_out<sc_dt::sc_uint<BITS> > out;

/**
* @brief Construct a new adc object
*
*/
SCA_CTOR(adc) : in("in"), out("out") {
SCA_CTOR(adc) : in("in"), out("out")
{
}

void set_attributes()
{
// Propagation time from input to output
set_timestep(sca_core::sca_time(0.1, sc_core::SC_US));
set_timestep(sca_core::sca_time(1, sc_core::SC_NS));
this->out.set_delay(13);
}

/**
Expand Down
20 changes: 15 additions & 5 deletions modules/adc/include/seq_item_adc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,33 @@
/**
* @brief This class is used to generate the analog signal for the test
*
* @tparam N
* @tparam N - the number of output bits of the digital code
* @tparam VMIN - lowest voltage value
* @tparam VMAX - highest voltage value
* @tparam VU - voltage unit based on VUnit
*/
template <unsigned int N>
template <unsigned int N = 8, int VMIN = 0, int VMAX = 5, VUnit VU = VUnit::v>
SCA_TDF_MODULE(seq_item_adc)
{
protected:
// Min voltage value based on the voltage units
const double V_MIN = static_cast<double>(VMIN) / static_cast<double>(VU);
// Max voltage value based on the voltage units
const double V_MAX = static_cast<double>(VMAX) / static_cast<double>(VU);
// Max digital output code
const int MAX_CODE = (1 << N);
public:
sca_tdf::sca_out<double> o_ana;
const int MAX_CODE = (1 << N);

SCA_CTOR(seq_item_adc)
{
set_timestep(sca_core::sca_time(0.1, sc_core::SC_US));
set_timestep(sca_core::sca_time(13, sc_core::SC_NS));
}

void processing()
{
this->o_ana.write(static_cast<double>(rand() % MAX_CODE) / MAX_CODE);
const double NORM_ANA = static_cast<double>(rand() % MAX_CODE) / MAX_CODE;
this->o_ana.write((V_MAX + V_MIN) * NORM_ANA + V_MIN);
}
};

Expand Down
8 changes: 5 additions & 3 deletions modules/adc/src/tb_adc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "seq_item_adc.hpp"

#define N 8
#define VOLTAGE_MIN 0
#define VOLTAGE_MAX 3300


int sc_main(int, char*[])
Expand All @@ -15,12 +17,12 @@ int sc_main(int, char*[])
sca_tdf::sca_signal<sc_dt::sc_uint<N> > s_dig_out;

// DUT
adc<N> ips_adc("ips_adc");
adc<N, VOLTAGE_MIN, VOLTAGE_MAX, VUnit::mv> ips_adc("ips_adc");
ips_adc.in(s_ana);
ips_adc.out(s_dig_out);

// Sequence item generator for ADC
seq_item_adc<N> ips_seq_item_adc("ips_seq_item_adc");
seq_item_adc<N, VOLTAGE_MIN, VOLTAGE_MAX, VUnit::mv> ips_seq_item_adc("ips_seq_item_adc");
ips_seq_item_adc.o_ana(s_ana);

// Dump waveform
Expand All @@ -32,7 +34,7 @@ int sc_main(int, char*[])
std::cout << "@" << sc_time_stamp() << std::endl;

// Run test
sc_start(MAX_SEQ_ITEMS * 0.1, SC_US);
sc_start(MAX_SEQ_ITEMS * 13, SC_NS);

// End time
std::cout << "@" << sc_time_stamp() << std::endl;
Expand Down
30 changes: 30 additions & 0 deletions modules/ams/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Include common Makefile
include ../Makefile

SRCDIR+=../adc/src ../dac/src ../vga/src ../utils/src
INCDIR+=-I$(SYSTEMC_AMS_HOME)/include -I../adc/include -I../dac/include -I../vga/include -I../utils/include
LIBDIR+=-L$(SYSTEMC_AMS_HOME)/lib-linux64
LIBS+=-lsystemc-ams

SOURCES:=$(foreach DIR, $(SRCDIR), $(wildcard $(DIR)/*.cpp))
INCLUDES:=$(foreach DIR, $(INCDIR), $(wildcard $(DIR)/*.hpp))

# Defining preprocessor directive for debug
ifdef IPS_DEBUG_EN
CFLAGS += -DIPS_DEBUG_EN
LFLAGS += -DIPS_DEBUG_EN
endif # IPS_DEBUG_EN

# Defining preprocessor directive for dumping enable
ifdef IPS_DUMP_EN
CFLAGS += -DIPS_DUMP_EN
LFLAGS += -DIPS_DUMP_EN
endif # IPS_DUMP_EN

# Run the compiled file
run:
@./$(TARGET)

# Show waveform
waveform:
@gtkwave ips_ams.vcd
42 changes: 42 additions & 0 deletions modules/ams/include/memory.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef IPS_MEMORY_HPP
#define IPS_MEMORY_HPP
#include <systemc.h>

template <unsigned int SIZE>
SC_MODULE(memory)
{
protected:
int *mem;

public:
sc_core::sc_in<bool> clk;
sc_core::sc_in<bool> we;
sc_core::sc_in<unsigned long long int> address;
sc_core::sc_in<sc_uint<24>> wdata;
sc_core::sc_out<sc_uint<24>> rdata;

// Constructor for memory
SC_CTOR(memory)
{
this->mem = new int[SIZE];

SC_METHOD(run);
sensitive << clk.pos();
}

void run()
{
if (clk.read())
{
const unsigned long long int ADDR = static_cast<unsigned long long int>(this->address.read());

if (we.read())
{
this->mem[ADDR] = this->wdata.read();
}

this->rdata.write(this->mem[ADDR]);
}
}
};
#endif // IPS_MEMORY_HPP
136 changes: 136 additions & 0 deletions modules/ams/include/seq_item_ams.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#ifndef IPS_SEQ_ITEM_AMS_HPP
#define IPS_SEQ_ITEM_AMS_HPP

#define int64 systemc_int64
#define uint64 systemc_uint64
#include <systemc.h>
#include <systemc-ams.h>
#undef int64
#undef uint64
#define int64 opencv_int64
#define uint64 opencv_uint64
#include <opencv2/opencv.hpp>
#undef int64
#undef uint64

// Image path
#define IPS_IMG_PATH_TB "../../tools/datagen/src/imgs/car_rgb_noisy_image.jpg"

/**
* @brief This class is used to generate the data for the AMS test
*
* @tparam N - the number of output bits of the digital pixel
* @tparam H_ACTIVE - output horizontal active video pixels
* @tparam H_FP - wait after the display period before the sync
* horizontal pulse
* @tparam H_SYNC_PULSE - assert HSYNC
* @tparam H_BP - wait after the sync horizontal pulse before starting
* the next display period
* @tparam V_ACTIVE - output vertical active video pixels
* @tparam V_FP - wait after the display period before the sync
* vertical pulse
* @tparam V_SYNC_PULSE - assert VSYNC
* @tparam V_BP - wait after the sync vertical pulse before starting
* the next display period
*/
template <
unsigned int N = 8,
unsigned int H_ACTIVE = 640,
unsigned int H_FP = 16,
unsigned int H_SYNC_PULSE = 96,
unsigned int H_BP = 48,
unsigned int V_ACTIVE = 480,
unsigned int V_FP = 10,
unsigned int V_SYNC_PULSE = 2,
unsigned int V_BP = 33
>
SC_MODULE(seq_item_ams)
{
protected:
cv::Mat tx_img;

public:
// Input clock
sc_core::sc_in<bool> clk;
// Counters
sc_core::sc_in<unsigned int> hcount;
sc_core::sc_in<unsigned int> vcount;
// Output pixel
sc_core::sc_out<sc_uint<N> > o_red;
sc_core::sc_out<sc_uint<N> > o_green;
sc_core::sc_out<sc_uint<N> > o_blue;

SC_CTOR(seq_item_ams)
{
// Read image
const std::string img_path = IPS_IMG_PATH_TB;

cv::Mat read_img = cv::imread(img_path, cv::IMREAD_COLOR);

// CV_8UC3 Type: 8-bit unsigned, 3 channels (e.g., for a color image)
read_img.convertTo(this->tx_img, CV_8UC3);

#ifdef IPS_DEBUG_EN
std::cout << "Loading image: " << img_path << std::endl;
#endif // IPS_DEBUG_EN

// Check if the image is loaded successfully
if (this->tx_img.empty())
{
std::cerr << "Error: Could not open or find the image!" << std::endl;
exit(EXIT_FAILURE);
}

#ifdef IPS_DEBUG_EN
std::cout << "TX image info: ";
std::cout << "rows = " << this->tx_img.rows;
std::cout << " cols = " << this->tx_img.cols;
std::cout << " channels = " << this->tx_img.channels() << std::endl;
#endif // IPS_DEBUG_EN

SC_METHOD(run);
sensitive << clk.pos();
}

void run()
{
if (this->clk.read())
{
const int IMG_ROW = static_cast<int>(this->vcount.read()) - (V_SYNC_PULSE + V_BP);
const int IMG_COL = static_cast<int>(this->hcount.read()) - (H_SYNC_PULSE + H_BP);

#ifdef IPS_DEBUG_EN
std::cout << "TX image: ";
std::cout << "row = " << IMG_ROW;
std::cout << " col = " << IMG_COL;
#endif // IPS_DEBUG_EN

if ((IMG_ROW < 0) || (IMG_COL < 0) || (IMG_ROW >= static_cast<int>(V_ACTIVE)) || (IMG_COL >= static_cast<int>(H_ACTIVE)))
{
this->o_red.write(0);
this->o_green.write(0);
this->o_blue.write(0);

#ifdef IPS_DEBUG_EN
std::cout << " dpixel = (0,0,0) " << std::endl;
#endif // IPS_DEBUG_EN
}
else
{
cv::Vec3b pixel = tx_img.at<cv::Vec3b>(IMG_ROW, IMG_COL, 0);

this->o_red.write(static_cast<sc_uint<8>>(pixel[0]));
this->o_green.write(static_cast<sc_uint<8>>(pixel[1]));
this->o_blue.write(static_cast<sc_uint<8>>(pixel[2]));

#ifdef IPS_DEBUG_EN
std::cout << " ipixel = (" << static_cast<int>(pixel[0]) << ","
<< static_cast<int>(pixel[1]) << "," << static_cast<int>(pixel[2])
<< ")" << std::endl;
#endif // IPS_DEBUG_EN
}
}
}
};

#endif // IPS_SEQ_ITEM_AMS_HPP
Loading