
axi4_lite_slave.sv
axi4_lite_if.sv
tb_top.sv
run.do
sy_transaction.sv
AXI4-Lite 버스를 타고 다니는 데이터 패킷(Address, Data, Control 등)을 정의한 클래스입니다. rand 변수들이 이곳에 선언되어 무작위 검증(CRV)의 기반이 됩니다.
sy_sequence.sv
sy_transaction 객체들을 생성하여 시퀀서(Sequencer)로 보내는 기본적인 트래픽 생성기입니다.
UVM 내장 함수
- start_item(req); (버스 사용 허가 요청)
시퀀서(Sequencer)에게 "나 드라이버한테 보낼 데이터가 생겼는데, 지금 버스(Driver) 써도 돼?
- finish_item(req); (데이터 전송 및 대기)
허락이 떨어지면 드라이버에게 실제로 데이터를 쏴줍니다.
그리고 드라이버가 핀 레벨 제어를 완전히 끝내고 "전송 완료(item_done)" 신호를 보내줄 때까지 또 기다려줍니다.
if (!req.randomize() with { trans_kind == WRITE; })
req.randomize() with { trans_kind == WRITE; }
트랜잭션 내부의 변수들(addr, data 등)에 무작위 값을 채워 넣으라는 명령입니다. 단, with {} 블록을 써서 "종류(trans_kind)는 무조건 WRITE로 고정해라"라는 강제 조건(Inline Constraint)을 달았습니다.
함수의 반환값 (성공=1, 실패=0)
if (! ... ) (안전장치): 앞에 느낌표(!)가 붙었으므로 조건이 뒤집힙니다. 즉, "만약 값 무작위 생성에 실패(0)했다면" 이 if 문 안으로 들어가게 됩니다.
여러 시나리오를 지휘하는 역할을 합니다.
sy_virtual_sequencer.sv
uvm_sequencer #(sy_transaction) axi_sqr;
오직 AXI 트랜잭션(sy_transaction) 규격의 패킷만 취급하는 전용 우체국(Sequencer)의 연락처를 axi_sqr라는 이름으로 만들겠다
sy_vseq_base.sv
sy_vseq_sweep.sv
sy_vseq_error.sv
start_item(tx, -1, axi_sqr)
start_item(보낼 물건, 우선순위, 목적지 우체국);
sy_vseq_rmw.sv
// .read(status, rdata, path, extension, parent)
regmodel.ctrl_reg.read(status, rdata, UVM_FRONTDOOR, null, this);
regmodel.ctrl_reg: regmodel 안에 있는 컨트롤 레지스터ctrl_reg 를 지칭합니다.
sy_agent.sv
sy_driver.sv
sy_monitor.sv
// Analysis Port
item_collected_port = new("item_collected_port", this);
// run phase
/ 1. 핀 데이터를 트랜잭션 객체에 옮겨 담기
tx.addr = vif.araddr;
// 2. 안테나를 통해 스코어보드로 던짐
item_collected_port.write(tx);
item_collected_port는 버스에서 수집한 신호들을 sy_transaction 객체로 포장한 뒤, Scoreboard 나 Coverage Collector 등 다른 컴포넌트들에게 Broadcast하기 위해 설치하는 전용 송신 안테나
다이어그램 우측의 SCOREBOARD와 COVERAGE COLLECTOR 블록입니다.
sy_scoreboard.sv
uvm_analysis_imp #(sy_transaction, sy_scoreboard) item_collected_export;
이전 대화에서 모니터(Monitor)가 데이터를 방송하기 위해 uvm_analysis_port라는 송신 안테나를 세운 것을 확인하셨을 것입니다.
Associative Array (연관배열)
logic [31:0] ref_memory [logic [31:0]];
앞부분 logic [31:0] : 가로 길이 (데이터의 크기)
의미: 이 메모리의 한 칸(방)에 들어가는 데이터의 크기가 32비트(4바이트)라는 뜻입니다.
질문자님이 말씀하신 "32비트고"에 해당하는 부분이며, 이는 메모리의 가로폭을 의미합니다.
뒷부분 [logic [31:0]] : 세로 길이 (주소의 개수)
의미: 이 메모리의 방 번호(Index/Address)를 매길 때 32비트짜리 숫자를 쓴다는 뜻입니다.
오해의 원인: 세로로 32개가 있는 것이 아닙니다. 32비트로 표현할 수 있는 숫자의 경우의 수는 $2^{32}$입니다. 즉, 세로로 최대 4,294,967,296개(약 43억 개)의 방을 가질 수 있다는 뜻입니다
만약 코드를 일반적인 하드웨어 배열 문법으로 짰다면 이렇게 됩니다.
logic [31:0] ref_memory [0:4294967295];
sy_subscriber.sv
다이어그램에는 생략되어 있지만 매우 중요한 고급 UVM 기능입니다.
sy_reg_block.sv
status_reg.configure(this, null);
.configure(...): UVM이 제공하는 함수로, 방금 갓 태어난 레지스터에게 "너의 부모(Parent)가 누구인지" 지정해 주는 역할을 합니다.
sy_reg_adapter.sv
sy_ral_sequence.sv
sy_env.sv
Agent, Scoreboard, Subscriber, Virtual Sequencer 등을 인스턴스화하고, 모니터와 스코어보드/서브스크라이버 간의 Analysis Port를 연결(Connect)하는 컨테이너입니다.
sy_test.sv
UVM 최상단 컴포넌트(UVM TEST)입니다. sy_env를 생성하고, 어떤 테스트 시나리오(Virtual Sequence)를 돌릴지 결정하여 실행합니다.
sy_uvm_pkg.sv
위의 모든 src/ 폴더 내의 SV 파일들을 올바른 순서로 include 하여 하나의 패키지로 묶어주는 파일입니다. 컴파일 에러를 방지합니다.
UVM에서 Sequencer는 특별한 추가 기능(예: 복잡한 중재(Arbitration) 로직이나 시퀀서 전용 변수)이 필요하지 않다면, 굳이 별도의 .sv 파일을 만들지 않는 것이 실무에서도 일반적인 관례입니다.
sy_agent.sv 파일 상단이나 sy_uvm_pkg.sv 내부에 다음과 같이 한 줄로 정의되어 있습니다
uvm_sequencer #(sy_transaction) sqr;
왜 별도의 파일을 만들지 않았나요?
기본 기능만 사용: 단순히 시퀀스(Sequence)에서 받은 아이템을 드라이버(Driver)로 전달하는 '큐(Queue)' 역할만 수행한다면, UVM이 이미 제공하는 uvm_sequencer를 그대로 가져다 쓰기만 하면 됩니다.

