"내 칩 서비스" MPW 2024-2차 칩이 28핀 SSOP 패키지로 배포 되었다. 디지털 회로의 경우 비록 28핀 밖에 않되는 칩이지만 테스트 하려면 테스트 벡터 제네레이터, 로직 아날라이져 같은 장비를 필요로 한다. 여러 클럭에 걸쳐 일련의 테스트 벡터를 주어 기능을 확인해야 하므로 입출력 신호 검사 장비는 프로그래머블 해야함은 물론이다. 비록 이런 장비를 갖췄더라도 장비 사용법은 쉽지 않다. 고가의 테스트 장비에 복잡한 사용법으로 인해 테스트 할 엄두가 나지 않는다면 직접 만들어 보자.
칩 테스트 장치는 기본적으로 SCE-MI 에 준하여 구성되었다.
SystemC 로 작성한 테스트 벤치를 통해 테스트 벡터 생성하고 출력을 검출한다. 동작 모드는 클럭 상세(Cycle Accurate)다. 아듀이노 메가보드를 활용하여 DUT(하드웨어)와 SystemC 테스트 벤치(소프트웨어) 사이의 모델 인터페이스 한다.
테스트 대상 칩은 아래와 같다.

Wires & Pin Header

Test Clips

SOP-28 (300mil) Test Socket

Oscilloscope & Multi-Tester




Arduino MEGA/Modeling Interface
회로도: https://content.arduino.cc/assets/MEGA2560_Rev3e_sch.pdf
디지털 핀: https://docs.arduino.cc/resources/pinouts/A000067-full-pinout.pdf

/*
Filenale: fir8_test.ino
FIR8 with SystemC Co-Emulation
Chip Test at Cycle Accurate Level
MyChip MPW 2024-2
*/
//----------------------// SOIC-28 Package
#define PIN_Xin_3 22 // 1
#define PIN_Xin_2 23 // 2
#define PIN_Xin_1 24 // 3
#define PIN_Xin_0 25 // 4
// VDD // 5
#define PIN_Yin_3 26 // 6
#define PIN_Yin_2 27 // 7
#define PIN_Yin_1 28 // 8
#define PIN_Yin_0 29 // 9
#define PIN_RDY_i 30 // 10
#define PIN_CLK_i 31 // 11
#define PIN_Cin_0 32 // 12
#define PIN_Cin_1 33 // 13
#define PIN_Cin_2 34 // 14
#define PIN_Cin_3 35 // 15
#define PIN_Cin_4 36 // 16
#define PIN_Cin_5 37 // 17
#define PIN_Cin_6 38 // 18
#define PIN_VLD_o 39 // 19
#define PIN_Yout_0 40 // 20
#define PIN_Yout_1 41 // 21
#define PIN_Yout_2 42 // 22
#define PIN_Yout_3 43 // 23
// VSS // 24
#define PIN_Xout_0 44 // 25
#define PIN_Xout_1 45 // 26
#define PIN_Xout_2 46 // 27
#define PIN_Xout_3 47 // 28
//-------------------------------------------------------------------
class Port_Xin {
uint8_t _val;
public:
Port_Xin(uint8_t val) // Constructor
{
// Set digital pins to output connecting DUT's INPUT
pinMode(PIN_Xin_3, OUTPUT);
pinMode(PIN_Xin_2, OUTPUT);
pinMode(PIN_Xin_1, OUTPUT);
pinMode(PIN_Xin_0, OUTPUT);
write(val);
}
uint8_t read()
{
return _val;
}
void write(uint8_t val)
{
digitalWrite(PIN_Xin_3, val & 0x08);
digitalWrite(PIN_Xin_2, val & 0x04);
digitalWrite(PIN_Xin_1, val & 0x02);
digitalWrite(PIN_Xin_0, val & 0x01);
_val = val;
}
};
//-------------------------------------------------------------------
class Port_Yin {
uint8_t _val;
public:
Port_Yin(uint8_t val)
{
// Set digital pins to output connecting DUT's INPUT
pinMode(PIN_Yin_3, OUTPUT);
pinMode(PIN_Yin_2, OUTPUT);
pinMode(PIN_Yin_1, OUTPUT);
pinMode(PIN_Yin_0, OUTPUT);
write(val);
}
uint8_t read()
{
return _val;
}
void write(uint8_t val)
{
digitalWrite(PIN_Yin_3, val & 0x08);
digitalWrite(PIN_Yin_2, val & 0x04);
digitalWrite(PIN_Yin_1, val & 0x02);
digitalWrite(PIN_Yin_0, val & 0x01);
_val = val;
}
};
//-------------------------------------------------------------------
class Port_Cin {
uint8_t _val;
public:
Port_Cin(uint8_t val)
{
// Set digital pins to output connecting DUT's INPUT
pinMode(PIN_Cin_6, OUTPUT);
pinMode(PIN_Cin_5, OUTPUT);
pinMode(PIN_Cin_4, OUTPUT);
pinMode(PIN_Cin_3, OUTPUT);
pinMode(PIN_Cin_2, OUTPUT);
pinMode(PIN_Cin_1, OUTPUT);
pinMode(PIN_Cin_0, OUTPUT);
write(val);
}
uint8_t read()
{
return _val;
}
void write(uint8_t val)
{
digitalWrite(PIN_Cin_6, val & 0x40);
digitalWrite(PIN_Cin_5, val & 0x20);
digitalWrite(PIN_Cin_4, val & 0x10);
digitalWrite(PIN_Cin_3, val & 0x08);
digitalWrite(PIN_Cin_2, val & 0x04);
digitalWrite(PIN_Cin_1, val & 0x02);
digitalWrite(PIN_Cin_0, val & 0x01);
_val = val;
}
};
//-------------------------------------------------------------------
class Port_RDY_i {
bool _val;
public:
Port_RDY_i(bool val)
{
// Set digital pins to output connecting DUT's INPUT
pinMode(PIN_RDY_i, OUTPUT);
write(val);
}
bool read()
{
return _val;
}
void write(bool val)
{
digitalWrite(PIN_RDY_i, val);
_val = val;
}
};
//-------------------------------------------------------------------
class Port_Xout {
uint8_t _val;
public:
Port_Xout(uint8_t val) // Constructor
{
// Set digital pins to input connecting DUT's OUTPUT
pinMode(PIN_Xout_3, INPUT);
pinMode(PIN_Xout_2, INPUT);
pinMode(PIN_Xout_1, INPUT);
pinMode(PIN_Xout_0, INPUT);
write(val);
}
uint8_t read()
{
_val = ((digitalRead(PIN_Xout_3)? 0x08:0x00) |
(digitalRead(PIN_Xout_2)? 0x04:0x00) |
(digitalRead(PIN_Xout_1)? 0x02:0x00) |
(digitalRead(PIN_Xout_0)? 0x01:0x00));
return _val;
}
void write(uint8_t val)
{
_val = val;
}
};
//-------------------------------------------------------------------
class Port_Yout {
uint8_t _val;
public:
Port_Yout(uint8_t val) // Constructor
{
// Set digital pins to input connecting DUT's OUTPUT
pinMode(PIN_Yout_3, INPUT);
pinMode(PIN_Yout_2, INPUT);
pinMode(PIN_Yout_1, INPUT);
pinMode(PIN_Yout_0, INPUT);
write(val);
}
uint8_t read()
{
_val = ((digitalRead(PIN_Yout_3)? 0x08:0x00) |
(digitalRead(PIN_Yout_2)? 0x04:0x00) |
(digitalRead(PIN_Yout_1)? 0x02:0x00) |
(digitalRead(PIN_Yout_0)? 0x01:0x00));
return _val;
}
void write(uint8_t val)
{
_val = val;
}
};
//-------------------------------------------------------------------
class Port_VLD_o {
bool _val;
public:
Port_VLD_o(bool val) // Constructor
{
// Set digital pins to input connecting DUT's OUTPUT
pinMode(PIN_VLD_o, INPUT);
write(val);
}
bool read()
{
_val = digitalRead(PIN_VLD_o);
return _val;
}
void write(uint8_t val)
{
_val = val;
}
};
//-------------------------------------------------------------------
class Port_CLK {
bool _val;
public:
Port_CLK(bool val)
{
pinMode(PIN_CLK_i, OUTPUT);
write(val);
}
void write(bool val)
{
digitalWrite(PIN_CLK_i, val);
_val = val;
}
bool read()
{
return _val;
}
void posedge()
{
digitalWrite(PIN_CLK_i, false);
digitalWrite(PIN_CLK_i, true);
_val = true;
}
void negedge()
{
digitalWrite(PIN_CLK_i, true);
digitalWrite(PIN_CLK_i, false);
_val = false;
}
bool cycle()
{
if (_val)
{
negedge();
posedge();
}
else
{
posedge();
negedge();
}
return _val;
}
};
//-------------------------------------------------------------------
void establishContact()
{
while (Serial.available() <= 0)
{
Serial.print('A'); // send a capital A
delay(300);
if (Serial.read()==(int)'A')
break;
}
}
//-------------------------------------------------------------------
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect.
}
establishContact(); // send a byte to establish contact until receiver responds
// Monitoring LED
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
}
#define N_RX 3 // [0]={Xin[7:4]|Yin[3:0]}
// [1]={-|Cin[6:0]};
// [2]={-[7:2]|Clk|RDY};
#define N_TX 2 // [0]={Xout[7:4]|Yout[3:0]}
// [1]={-[7:1]|VLD[0]}
uint8_t rxBuf[N_RX], txBuf[N_TX];
// Instantiate DUT Ports
Port_Xin Xin(0x00);
Port_Yin Yin(0x00);
Port_Cin Cin(0x00);
Port_Xout Xout(0);
Port_Yout Yout(0);
Port_RDY_i RDY_i(false);
Port_VLD_o VLD_o(false);
Port_CLK CLK(false);
void RxPacket()
{
int rxByte;
while(true)
{
if (Serial.available() >= N_RX)
{
for(int i=0; i<N_RX; i++)
{
rxByte = Serial.read();
rxBuf[i] = (uint8_t)rxByte;
}
//rxBuf[0]={Xin[7:4]|Yin[3:0]}
Xin.write((rxBuf[0] & 0xF0) >> 4);
Yin.write((rxBuf[0] & 0x0F));
//rxBuf[1]={-|Cin[6:0]};
Cin.write((rxBuf[1] & 0x7F));
//rxBuf[2]={-[7:2]|Clk|RDY};
RDY_i.write((rxBuf[2] & 0x01));
CLK.write((rxBuf[2] & 0x02));
return;
}
}
}
void TxPacket()
{
int txByte;
while(1)
{
if (Serial.availableForWrite() >= N_TX)
{
// [0]={Xout[7:4]|Yout[3:0]}
txBuf[0] = (((uint8_t)Xout.read() << 4) | ((uint8_t)Yout.read() & 0x0F));
// [1]={-[7:1]|VLD[0]}
txBuf[1] = ((uint8_t)VLD_o.read() & 0x01);
for(int i=0; i<N_TX; i++)
{
txByte = (int)txBuf[i];
Serial.write(txByte);
}
return;
}
}
}
uint8_t counter;
void loop()
{
counter += 1;
digitalWrite(LED_BUILTIN, (counter & 0x10)? HIGH:LOW);
RxPacket();
TxPacket();
}
SystemC Testbench
1. DUT Wrapper
/**********************************************************************
Filename: sc_fir_pe.h
Purpose : Test wrapper
Chip Test of FIR PE (MyChip 2024-2)
Author : goodkook@gmail.com
History : Jan. 2025, First release
***********************************************************************/
#ifndef _SC_FIR_PE_H_
#define _SC_FIR_PE_H_
#include <systemc.h>
// Includes for accessing Arduino via serial port
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
SC_MODULE(sc_fir_pe)
{
sc_in<bool> clk;
sc_in<bool> Rdy;
sc_out<bool> Vld;
sc_in<sc_uint<8> > Cin;
sc_in<sc_uint<4> > Xin;
sc_out<sc_uint<4> > Xout;
sc_in<sc_uint<4> > Yin;
sc_out<sc_uint<4> > Yout;
#define N_TX 3
#define N_RX 2
void transact(void)
{
uint8_t x, y, txPacket[N_TX], rxPacket[N_RX];
txPacket[0] = ((uint8_t)Xin.read()<<4) | ((uint8_t)Yin.read() & 0x0F);
txPacket[1] = ((uint8_t)(Cin.read()) & 0x7F);
txPacket[2] = (((uint8_t)Rdy.read())? 0x01:0x00) | (((uint8_t)clk.read())? 0x02:0x00);
// Send to Emulator
for (int i=0; i<N_TX; i++)
{
x = txPacket[i];
while(write(fd, &x, 1)<=0) usleep(1);
}
// Receive from Emulator
for (int i=0; i<N_RX; i++)
{
while(read(fd, &y, 1)<=0) usleep(1);
rxPacket[i] = y;
}
Xout.write((sc_uint<4>)(rxPacket[0]>>4));
Yout.write((sc_uint<4>)(rxPacket[0] & 0x0F));
Vld.write(rxPacket[1]? true:false);
#ifdef LA_FIFO
x = txPacket[2] & 0x02; // clk
x |= txPacket[2] & 0x01; // Rdy
x |= rxPacket[1]? 0x04:0x00; // Vld
x |= (rxPacket[0] & 0x01)<<4; // Yout0
x |= (rxPacket[0] & 0x02)<<4; // Yout1
x |= (rxPacket[0] & 0x04)<<4; // Yout2
x |= (rxPacket[0] & 0x08)<<4; // Yout3
if((nWrite = write(la_fifo, &x, 1)) < 1)
fprintf(stderr,"la_fifo: write error\n");
else
fflush(0);
#endif
}
void pe_thread(void)
{
while(true)
{
wait(clk.posedge_event());
transact();
wait(clk.negedge_event());
transact();
}
}
// Arduino Serial IF
int fd; // Serial port file descriptor
struct termios options; // Serial port setting
#ifdef LA_FIFO
int la_fifo, nWrite;
#endif
SC_CTOR(sc_fir_pe):
clk("clk"),
Cin("Cin"), Xin("Xin"), Xout("Xout"),
Yin("Yin"), Yout("Yout")
{
SC_THREAD(pe_thread);
sensitive << clk;
// Arduino DUT
//fd = open("/dev/ttyACM0", O_RDWR | O_NDELAY | O_NOCTTY);
fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY);
if (fd < 0)
{
perror("Error opening serial port");
return;
}
// Set up serial port
options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
// Apply the settings
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
// Establish Contact
int len = 0;
char rx;
while(!len)
len = read(fd, &rx, 1);
if (rx=='A')
write(fd, &rx, 1);
printf("Connection established...\n");
#ifdef LA_FIFO
la_fifo = open("la_fifo", O_WRONLY);
if(la_fifo<0)
fprintf(stderr,"la_fifo: open error\n");
#endif
}
~sc_fir_pe(void)
{
}
};
#endif
2. Testbench
/**********************************************************************
Filename: sc_fir_pe_tb.h
Purpose : Testbench
Chip Test of FIR PE (MyChip 2024-2)
Author : goodkook@gmail.com
History : Jan. 2025, First release
***********************************************************************/
#ifndef _SC_FIR_PE_TB_H_
#define _SC_FIR_PE_TB_H_
#include <systemc.h>
#include "sc_fir_pe.h"
SC_MODULE(sc_fir_pe_tb)
{
sc_clock clk;
sc_signal<sc_uint<8> > Cin;
sc_signal<sc_uint<4> > Xin;
sc_signal<sc_uint<4> > Xout;
sc_signal<sc_uint<4> > Yin;
sc_signal<sc_uint<4> > Yout;
sc_signal<bool> Vld;
sc_signal<bool> Rdy;
sc_fir_pe* u_sc_fir_pe;
uint16_t Test_Cin[5] = {0, 0, 0, 0, 0};
uint16_t Test_Xin[5] = {0, 0, 0, 0, 0};
uint16_t Test_Yin[5] = {0, 0, 0, 0, 0};
uint8_t Test_Xout = 0;
uint16_t Test_Yout = 0;
// Test utilities
void Test_Gen()
{
Cin.write(0x00);
Xin.write(0x00);
Yin.write(0x00);
Rdy.write(false);
// INIT
for (int i=0; i<10; i++)
wait(clk.posedge_event());
wait(clk.posedge_event());
Rdy.write(true);
wait(clk.posedge_event());
Rdy.write(false);
for (int i=0; i<10; i++)
wait(clk.posedge_event());
Cin.write(Test_Cin[0]);
Xin.write(0x00);
Yin.write(0x00);
Rdy.write(false);
while(true)
{
Cin.write(Test_Cin[0] & 0x007F); // Cin: 7-Bits
wait(clk.posedge_event());
Rdy.write(true);
wait(clk.posedge_event());
Rdy.write(false);
Xin.write(Test_Xin[0] & 0x000F); // Xin: 4-Bits
Yin.write(Test_Yin[0] & 0x000F); // Yin: 4-Bits
wait(clk.posedge_event());
Xin.write(Test_Xin[0] >> 4);
Yin.write((Test_Yin[0] >> 4) & 0x000F); // Yin: 4-Bits
wait(clk.posedge_event());
Yin.write((Test_Yin[0] >> 8) & 0x000F); // Yin: 4-Bits
wait(clk.posedge_event());
Yin.write((Test_Yin[0] >> 12) & 0x000F); // Yin: 4-Bits
wait(clk.posedge_event());
//printf("Cin = %04d Xin = %04d Yin = %06d ---> ", Test_Cin[0], Test_Xin[0], Test_Yin[0]);
Test_Xin[4] = Test_Xin[3]; Test_Xin[3] = Test_Xin[2]; Test_Xin[2] = Test_Xin[1]; Test_Xin[1] = Test_Xin[0];
Test_Yin[4] = Test_Yin[3]; Test_Yin[3] = Test_Yin[2]; Test_Yin[2] = Test_Yin[1]; Test_Yin[1] = Test_Yin[0];
Test_Cin[4] = Test_Cin[3]; Test_Cin[3] = Test_Cin[2]; Test_Cin[2] = Test_Cin[1]; Test_Cin[1] = Test_Cin[0];
#if defined(TEST_MULTIPLIER_C)
Test_Cin[0]++;
if (Test_Cin[0]>127)
{
Test_Cin[0] = 0;
Test_Xin[0]++;
if (Test_Xin[0]>255)
sc_stop();
}
#elif defined(TEST_MULTIPLIER_X)
Test_Xin[0]++;
if (Test_Xin[0]>255)
{
Test_Xin[0] = 0;
Test_Cin[0]++;
if (Test_Cin[0]>127)
sc_stop();
}
#elif defined(TEST_ADDER_X)
Test_Cin[0] = 1;
Test_Xin[0]++;
if (Test_Xin[0]>255)
{
Test_Xin[0] = 0;
Test_Yin[0]++;
if (Test_Yin[0]>1000)
sc_stop();
}
#elif defined(TEST_ADDER_Y)
Test_Cin[0] = 1;
Test_Yin[0]++;
if (Test_Yin[0]>255)
{
Test_Yin[0] = 0;
Test_Xin[0]++;
if (Test_Xin[0]>255)
sc_stop();
}
#elif defined(TEST_ADDER_R)
Test_Cin[0] = 1;
Test_Xin[0] = (uint16_t)rand() & 0x00FF; // Xin: unsigned 8-bit
Test_Yin[0] = (uint16_t)rand() & 0xFFFF; // Yin: unsigned 16-bit
#else // RAND (default)
Test_Cin[0] = (uint16_t)rand() & 0x007F; // Cin: unsigned 7-bit
Test_Xin[0] = (uint16_t)rand() & 0x00FF; // Xin: unsigned 8-bit
Test_Yin[0] = (uint16_t)rand() & 0xFFFF; // Yin: unsigned 16-bit
#endif
}
}
void Test_Mon()
{
uint16_t Yout_Expected = 0;
while(true)
{
wait(clk.posedge_event());
if (Vld.read())
{
wait(clk.posedge_event());
wait(clk.posedge_event());
Test_Xout = (uint8_t)Xout.read();
Test_Yout = (uint16_t)Yout.read();
wait(clk.posedge_event());
Test_Xout |= (uint8_t)Xout.read() << 4;
Test_Yout |= (uint16_t)Yout.read() << 4;
wait(clk.posedge_event());
Test_Yout |= (uint16_t)Yout.read() << 8;
wait(clk.posedge_event());
Test_Yout |= (uint16_t)Yout.read() << 12;
printf("[Cin=%03d] * [Xin=%03d] + [Yin=%05d] ---> ",
#if defined(TEST_ADDER_X) || defined(TEST_ADDER_Y) || defined(TEST_ADDER_R) || defined(RAND)
Test_Cin[3], Test_Xin[3], Test_Yin[3]);
Yout_Expected = (Test_Cin[3]*Test_Xin[3]+Test_Yin[3]);
#else
Test_Cin[2], Test_Xin[2], Test_Yin[2]);
Yout_Expected = (Test_Cin[2]*Test_Xin[2]+Test_Yin[2]);
#endif
printf("Xout = %03d Yout = %05d", Test_Xout, Test_Yout);
if (Test_Yout!=Yout_Expected)
printf(":ERROR, Expected Yout = %05d\n", Yout_Expected);
else
printf("\n");
}
}
}
#ifdef VCD_TRACE_YES
sc_trace_file* fp; // VCD file
#endif
SC_CTOR(sc_fir_pe_tb):
clk("clk", 100, SC_NS, 0.5, 0.0, SC_NS, false),
Vld("Vld"),
Rdy("Rdy"),
Xin("Xin"),
Xout("Xout"),
Yin("Yin"),
Yout("Yout")
{
SC_THREAD(Test_Gen);
sensitive << clk;
SC_THREAD(Test_Mon);
sensitive << clk;
// Instaltiate FIR8
u_sc_fir_pe = new sc_fir_pe("u_sc_fir_pe");
u_sc_fir_pe->clk(clk);
u_sc_fir_pe->Cin(Cin);
u_sc_fir_pe->Xin(Xin);
u_sc_fir_pe->Xout(Xout);
u_sc_fir_pe->Yin(Yin);
u_sc_fir_pe->Yout(Yout);
u_sc_fir_pe->Rdy(Rdy);
u_sc_fir_pe->Vld(Vld);
#if VCD_TRACE_YES
// WAVE
fp = sc_create_vcd_trace_file("sc_fir_pe_tb");
sc_trace(fp, clk, "clk");
sc_trace(fp, Cin, "Cin");
sc_trace(fp, Xin, "Xin");
sc_trace(fp, Xout, "Xout");
sc_trace(fp, Yin, "Yin");
sc_trace(fp, Yout, "Yout");
sc_trace(fp, Rdy, "Rdy");
sc_trace(fp, Vld, "Vld");
#endif
}
~sc_fir_pe_tb(void)
{
}
};
#endif
3. Main
/********************************************************************
Filename: sc_main.cpp
Purpose : Chip Test of FIR PE (MyChip 2024-2)
Author : goodkook@gmail.com
History : Jan. 2025, First release
********************************************************************/
#include "sc_fir_pe_tb.h"
int sc_main(int argc, char** argv)
{
sc_fir_pe_tb u_sc_fir_pe_tb("u_sc_fir_pe_tb");
//sc_start(990, SC_US);
sc_start();
return 0;
}
4. Python Logic Analyzer
#
# Real-Time Logic Analyzer
#
#
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
HEIGHT = 3
def generate_wave(frame, tick, data,
Signal, Mask, PosY, line_Signal) -> None:
for i in np.arange(0, 80, 2):
if (not(data[int(i/2)] & Mask)) and (not(data[int(i/2)+1] & Mask)):# Zero
Signal[i] = PosY
Signal[i+1] = PosY
elif (not(data[int(i/2)] & Mask)) and (data[int(i/2)+1] & Mask):# Rising edge
Signal[i] = PosY
Signal[i+1] = PosY+HEIGHT
elif (data[int(i/2)] & Mask) and (not(data[int(i/2)+1] & Mask)):# Falling edge
Signal[i] = PosY+HEIGHT
Signal[i+1] = PosY
else: # One
Signal[i] = PosY+HEIGHT
Signal[i+1] = PosY+HEIGHT
Signal[80] = Signal[79]
line_Signal.set_xdata(tick[:frame])
line_Signal.set_ydata(Signal[:frame])
#--------------------------------------------------------------------
def update(frame, fp_fifo, data, tick,
line_Clk, line_Rdy, line_Vld,
line_Yout0, line_Yout1, line_Yout2, line_Yout3,
Clk, Rdy, Vld, Yout0, Yout1, Yout2, Yout3) -> None:
for i in range(0, 40):
data[i] = data[i+1]
data[40] = int.from_bytes(fp_fifo.read(1), "big")
generate_wave(frame, tick, data, Yout0, 0x10, 0, line_Yout0)
generate_wave(frame, tick, data, Yout1, 0x20, 5, line_Yout1)
generate_wave(frame, tick, data, Yout2, 0x40, 10, line_Yout2)
generate_wave(frame, tick, data, Yout3, 0x80, 15, line_Yout3)
generate_wave(frame, tick, data, Vld, 0x01, 20, line_Vld)
generate_wave(frame, tick, data, Rdy, 0x04, 25, line_Rdy)
generate_wave(frame, tick, data, Clk, 0x02, 30, line_Clk)
#--------------------------------------------------------------------
def run():
data = [0] * 41
tick = [0] * 81
Clk = [0] * 81
Rdy = [0] * 81
Vld = [0] * 81
Yout0 = [0] * 81
Yout1 = [0] * 81
Yout2 = [0] * 81
Yout3 = [0] * 81
fp_fifo = open("./la_fifo", "rb")
for i in range(0, 40):
data[i] = int.from_bytes(fp_fifo.read(1), "big")
fig, ax = plt.subplots()
line_Clk = ax.plot(tick[0], Clk[0], label="Clk")[0]
line_Rdy = ax.plot(tick[0], Rdy[0], label="Rdy")[0]
line_Vld = ax.plot(tick[0], Vld[0], label="Vld")[0]
line_Yout0 = ax.plot(tick[0], Yout0[0], label="Yout[0]")[0]
line_Yout1 = ax.plot(tick[0], Yout1[0], label="Yout[1]")[0]
line_Yout2 = ax.plot(tick[0], Yout2[0], label="Yout[2]")[0]
line_Yout3 = ax.plot(tick[0], Yout3[0], label="Yout[3]")[0]
ax.set(xlim=[0, 800], ylim=[-1, 35])
ax.legend(loc='upper left', fancybox=True, shadow=True)
for i in np.arange(0, 80, 2):
tick[i] = tick[i+1] = i * 10
tick[80] = tick[79]
ani = animation.FuncAnimation(
fig=fig,
func =update,
fargs= (fp_fifo, data, tick,
line_Clk, line_Rdy, line_Vld,
line_Yout0, line_Yout1,
line_Yout2, line_Yout3,
Clk, Rdy, Vld,
Yout0, Yout1, Yout2, Yout3),
interval=10, cache_frame_data=False)
plt.show()
#--------------------------------------------------------------------
run()
5. Makefile
# SystemC Environments -----------------------------------------
export SYSTEMC = /usr/local/systemc-3.0.0
export SYSTEMC_HOME = $(SYSTEMC)
export SYSTEMC_INCLUDE = $(SYSTEMC_HOME)/include
export SYSTEMC_LIBDIR = $(SYSTEMC_HOME)/lib-linux64
export LD_LIBRARY_PATH :=$(LD_LIBRARY_PATH):$(SYSTEMC_LIBDIR)
export CXX = clang++
export CXXFLAGS = -std=c++17
# SystemC testbench Reuse --------------------------------------
SC_SRCS = ./sc_main.cpp
SC_HDRS = ./sc_fir_pe.h \
./sc_fir_pe_tb.h
SC_TARGET = sc_fir_pe_tb
# Conditional building option
ifeq ($(VCD_TRACE),YES)
VCD_TRACE = VCD_TRACE_YES
else
VCD_TRACE = VCD_TRACE_NO
endif
ifeq ($(TEST_MODE), MULTIPLIER_C)
TEST_MODE = TEST_MULTIPLIER_C
else ifeq ($(TEST_MODE), MULTIPLIER_X)
TEST_MODE = TEST_MULTIPLIER_X
else ifeq ($(TEST_MODE), ADDER_X)
TEST_MODE = TEST_ADDER_X
else ifeq ($(TEST_MODE), ADDER_Y)
TEST_MODE = TEST_ADDER_Y
else
TEST_MODE = TEST_ADDER_R
endif
# Build Rules --------------------------------------------------
all :
@echo
@echo 'Makefile for Chip Test of "FIR_PE/MyChip MPW 2024-2"'
@echo 'Usage:'
@echo ' Build with Options,'
@echo ' TEST_MODE=<...> VCD_TRACE=<...> make build'
@echo ' TEST_MODE: MULTIPLIER_C, MULTIPLIER_X, ADDER_R, ADDER_X, ADDER_Y, RAND'
@echo ' VCD_TRACE: YES or NO'
@echo
@echo ' Run test,'
@echo ' make run'
@echo
@echo ' View VCD at run-time,'
@echo ' TEST_MODE=<...> make run_vcd'
@echo
@echo ' make clean'
@echo
build: $(SC_TARGET)
$(SC_TARGET): $(SC_SRCS) $(SC_HDRS)
$(CXX) $(CXXFLAGS) -I$(SYSTEMC_INCLUDE) -L$(SYSTEMC_LIBDIR) \
-D$(TEST_MODE) -D$(VCD_TRACE) -DLA_FIFO \
-lsystemc -o$(SC_TARGET) $(SC_SRCS)
run: $(SC_TARGET)
rm -f la_fifo
mkfifo la_fifo
python3 la_fifo.py &
./$(SC_TARGET)
run_vcd:
$(CXX) $(CXXFLAGS) -I$(SYSTEMC_INCLUDE) -L$(SYSTEMC_LIBDIR) \
-D$(TEST_MODE) -DVCD_TRACE_YES \
-lsystemc -o$(SC_TARGET) $(SC_SRCS)
rm -f sc_fir_pe_tb.vcd
mkfifo sc_fir_pe_tb.vcd
./$(SC_TARGET) &
shmidcat sc_fir_pe_tb.vcd | gtkwave -v -I sc_fir_pe_tb.sav
clean :
rm -f $(SC_TARGET)
rm -f sc_fir_pe_tb.vcd
테스트 실행
% make
Makefile for Chip Test of "FIR_PE/MyChip MPW 2024-2"
Usage:
Build with Options,
TEST_MODE=<...> VCD_TRACE=<...> make build
TEST_MODE: MULTIPLIER_C, MULTIPLIER_X, ADDER_R, ADDER_X, ADDER_Y, RAND
VCD_TRACE: YES or NO
Run test,
make run
View VCD at run-time,
TEST_MODE=<...> make run_vcd
make clean
% TEST_MODE=ADDER_R VCD_TRACE=NO make build
% make run





-----------------------
[이전] [2] 아듀이노 보드 에뮬레이터
[다음] [4] PC 사운드 카드 오실로 스코프
[참고]
1. "내 칩 제작 서비스" 2025년 1차 MPW 대비 오픈-소스 도구 설치 [바로가기]
2. ETRI 0.5um CMOS DK 예제: counter8/16, 디지털 회로 칩 테스트 방법 [바로가기]