#include "ulpi_wrapper_tb.h"
|
#include "ulpi_wrapper_tb.h"
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// sc_main_tb
|
// sc_main_tb
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
static int attach_system_c(p_cb_data user_data)
|
static int attach_system_c(p_cb_data user_data)
|
{
|
{
|
ulpi_wrapper_tb * u_tb = new ulpi_wrapper_tb("ulpi_wrapper_tb");
|
ulpi_wrapper_tb * u_tb = new ulpi_wrapper_tb("ulpi_wrapper_tb");
|
|
|
// Initialize SystemC
|
// Initialize SystemC
|
sc_start(0, SC_NS);
|
sc_start(0, SC_NS);
|
|
|
// Start clock
|
// Start clock
|
u_tb->m_vpi_clk.start();
|
u_tb->m_vpi_clk.start();
|
}
|
}
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// _register
|
// _register
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
static void _register(void)
|
static void _register(void)
|
{
|
{
|
s_cb_data cb_data_s;
|
s_cb_data cb_data_s;
|
cb_data_s.user_data = NULL;
|
cb_data_s.user_data = NULL;
|
cb_data_s.reason = cbStartOfSimulation;
|
cb_data_s.reason = cbStartOfSimulation;
|
cb_data_s.cb_rtn = attach_system_c;
|
cb_data_s.cb_rtn = attach_system_c;
|
cb_data_s.time = NULL;
|
cb_data_s.time = NULL;
|
cb_data_s.value = NULL;
|
cb_data_s.value = NULL;
|
vpi_register_cb(&cb_data_s);
|
vpi_register_cb(&cb_data_s);
|
}
|
}
|
|
|
void (*vlog_startup_routines[])() =
|
void (*vlog_startup_routines[])() =
|
{
|
{
|
_register,
|
_register,
|
0
|
0
|
};
|
};
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// testbench
|
// testbench
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
void ulpi_wrapper_tb::testbench(void)
|
void ulpi_wrapper_tb::testbench(void)
|
{
|
{
|
sc_uint <8> last_wr = 0xFF;
|
sc_uint <8> last_wr = 0xFF;
|
|
|
ulpi_rst_i.write(true);
|
ulpi_rst_i.write(true);
|
wait(5);
|
wait(5);
|
ulpi_rst_i.write(false);
|
ulpi_rst_i.write(false);
|
wait(1);
|
wait(1);
|
|
|
m_reg.write(ULPI_REG_SCRATCH, last_wr);
|
|
|
|
int cycles = 0;
|
int cycles = 0;
|
while (true)
|
while (true)
|
{
|
{
|
// Random delay
|
// Random delay
|
int wait_len = rand() % 10;
|
int wait_len = rand() % 10;
|
if (wait_len)
|
if (wait_len)
|
wait(wait_len);
|
wait(wait_len);
|
|
|
// Random register write
|
|
if (rand() & 1)
|
|
{
|
|
last_wr = rand();
|
|
m_reg.write(ULPI_REG_SCRATCH, last_wr);
|
|
}
|
|
// Random register read
|
|
else
|
|
{
|
|
sc_assert(m_reg.read(ULPI_REG_SCRATCH) == last_wr);
|
|
}
|
|
|
|
if (!(rand() % 32))
|
if (!(rand() % 32))
|
{
|
{
|
if (rand() & 1)
|
if (rand() & 1)
|
utmi_opmode_i.write(rand());
|
utmi_opmode_i.write(rand());
|
else
|
else
|
utmi_dppulldown_i.write(rand() & 1);
|
utmi_dppulldown_i.write(rand() & 1);
|
}
|
}
|
|
|
if (cycles++ == 1000)
|
if (cycles++ == 1000)
|
m_dut.stopSimulation();
|
m_dut.stopSimulation();
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// phy_rx: PHY Rx Thread
|
// phy_rx: PHY Rx Thread
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
void ulpi_wrapper_tb::phy_rx(void)
|
void ulpi_wrapper_tb::phy_rx(void)
|
{
|
{
|
sc_uint <8> data;
|
sc_uint <8> data;
|
sc_uint <1> last;
|
sc_uint <1> last;
|
|
|
sc_uint <8> ulpi_data;
|
sc_uint <8> ulpi_data;
|
sc_uint <1> ulpi_last;
|
sc_uint <1> ulpi_last;
|
|
|
while (ulpi_rst_i.read())
|
while (ulpi_rst_i.read())
|
wait();
|
wait();
|
|
|
while (1)
|
while (1)
|
{
|
{
|
// Wait for data from ULPI interface
|
// Wait for data from ULPI interface
|
ulpi_last = m_ulpi.read(ulpi_data);
|
ulpi_last = m_ulpi.read(ulpi_data);
|
|
|
// Read actual data FIFO
|
// Read actual data FIFO
|
(last, data) = m_link_phy_queue.read();
|
(last, data) = m_link_phy_queue.read();
|
|
|
cout << hex << "EXPECT: DATA " << data << " LAST " << last << endl;
|
cout << hex << "EXPECT: DATA " << data << " LAST " << last << endl;
|
cout << hex << "GOT: DATA " << ulpi_data << " LAST " << ulpi_last << endl;
|
cout << hex << "GOT: DATA " << ulpi_data << " LAST " << ulpi_last << endl;
|
|
|
sc_assert(ulpi_data == data);
|
sc_assert(ulpi_data == data);
|
sc_assert(ulpi_last == last);
|
sc_assert(ulpi_last == last);
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// link_rx: Link Rx Thread
|
// link_rx: Link Rx Thread
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
void ulpi_wrapper_tb::link_rx(void)
|
void ulpi_wrapper_tb::link_rx(void)
|
{
|
{
|
sc_uint <8> data;
|
sc_uint <8> data;
|
sc_uint <1> last;
|
sc_uint <1> last;
|
|
|
sc_uint <8> ulpi_data;
|
sc_uint <8> ulpi_data;
|
sc_uint <1> ulpi_last;
|
sc_uint <1> ulpi_last;
|
|
|
while (ulpi_rst_i.read())
|
while (ulpi_rst_i.read())
|
wait();
|
wait();
|
|
|
while (1)
|
while (1)
|
{
|
{
|
// Wait for data from UTMI interface
|
// Wait for data from UTMI interface
|
ulpi_last = m_utmi.read(ulpi_data);
|
ulpi_last = m_utmi.read(ulpi_data);
|
|
|
// Read actual data FIFO
|
// Read actual data FIFO
|
(last, data) = m_phy_link_queue.read();
|
(last, data) = m_phy_link_queue.read();
|
|
|
cout << hex << "EXPECT: DATA " << data << " LAST " << last << endl;
|
cout << hex << "EXPECT: DATA " << data << " LAST " << last << endl;
|
cout << hex << "GOT: DATA " << ulpi_data << " LAST " << ulpi_last << endl;
|
cout << hex << "GOT: DATA " << ulpi_data << " LAST " << ulpi_last << endl;
|
|
|
sc_assert(ulpi_data == data);
|
sc_assert(ulpi_data == data);
|
sc_assert(ulpi_last == last);
|
sc_assert(ulpi_last == last);
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// phy_tx: PHY Tx Thread
|
// phy_tx: PHY Tx Thread
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
void ulpi_wrapper_tb::phy_tx(void)
|
void ulpi_wrapper_tb::phy_tx(void)
|
{
|
{
|
while (ulpi_rst_i.read())
|
while (ulpi_rst_i.read())
|
wait();
|
wait();
|
|
|
while (1)
|
while (1)
|
{
|
{
|
wait(10 + (rand() % 16));
|
wait(10 + (rand() % 16));
|
|
|
m_mutex.lock();
|
m_mutex.lock();
|
|
|
int len = 1 + (rand() % 8);
|
int len = 1 + (rand() % 8);
|
while (len--)
|
while (len--)
|
{
|
{
|
sc_uint <8> data = rand();
|
sc_uint <8> data = rand();
|
sc_uint <1> last = (len == 0);
|
sc_uint <1> last = (len == 0);
|
|
|
cout << hex << "QUEUE (RX): DATA " << data << " LAST " << last << endl;
|
cout << hex << "QUEUE (RX): DATA " << data << " LAST " << last << endl;
|
m_phy_link_queue.write((last, data));
|
m_phy_link_queue.write((last, data));
|
m_ulpi.write(data, last);
|
m_ulpi.write(data, last);
|
}
|
}
|
|
|
do
|
do
|
{
|
{
|
wait(1);
|
wait(1);
|
}
|
}
|
while (m_phy_link_queue.num_available());
|
while (m_phy_link_queue.num_available());
|
|
|
m_mutex.unlock();
|
m_mutex.unlock();
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// link_tx: Link Tx Thread
|
// link_tx: Link Tx Thread
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
void ulpi_wrapper_tb::link_tx(void)
|
void ulpi_wrapper_tb::link_tx(void)
|
{
|
{
|
while (ulpi_rst_i.read())
|
while (ulpi_rst_i.read())
|
wait();
|
wait();
|
|
|
while (1)
|
while (1)
|
{
|
{
|
wait(10 + (rand() % 16));
|
wait(10 + (rand() % 16));
|
|
|
m_mutex.lock();
|
m_mutex.lock();
|
|
|
int len = 1 + (rand() % 8);
|
int len = 1 + (rand() % 8);
|
bool first = true;
|
bool first = true;
|
while (len--)
|
while (len--)
|
{
|
{
|
sc_uint <8> data = rand();
|
sc_uint <8> data = rand();
|
sc_uint <1> last = (len == 0);
|
sc_uint <1> last = (len == 0);
|
|
|
// First byte is PID
|
// First byte is PID
|
if (first)
|
if (first)
|
data.range(7,4) = ~data.range(3,0);
|
data.range(7,4) = ~data.range(3,0);
|
|
|
first = false;
|
first = false;
|
|
|
cout << hex << "QUEUE (TX): DATA " << data << " LAST " << last << endl;
|
cout << hex << "QUEUE (TX): DATA " << data << " LAST " << last << endl;
|
m_link_phy_queue.write((last, data));
|
m_link_phy_queue.write((last, data));
|
m_utmi.write(data, last);
|
m_utmi.write(data, last);
|
}
|
}
|
|
|
// Wait until transfer completed
|
// Wait until transfer completed
|
do
|
do
|
{
|
{
|
wait();
|
wait();
|
}
|
}
|
while (m_link_phy_queue.num_available());
|
while (m_link_phy_queue.num_available());
|
|
|
m_mutex.unlock();
|
m_mutex.unlock();
|
}
|
}
|
}
|
}
|
|
|