지노랩 /JinoLab

[UVM] 3.5.1 기본적인 시퀀서와 드라이버의 상호작용 본문

UVM(Universal Verification Methodology)/3. 재사용 가능한 검증 컴포넌트 개발(Developing Reusabl

[UVM] 3.5.1 기본적인 시퀀서와 드라이버의 상호작용

지노랩/JinoLab 2025. 3. 12. 13:27

3.5.1 기본적인 시퀀서와 드라이버의 상호작용

3.5.1.1 개요

  • 드라이버(Driver)와 시퀀서(Sequencer)는 트랜잭션 레벨 모델링(TLM)을 통해 데이터를 주고받음.
  • 드라이버는 시퀀서에서 트랜잭션을 받아(DUT로 보내기 위해) 실행한 후, 완료 여부를 시퀀서에 알림.
  • 주요 메서드인 get_next_item()과 item_done()을 통해 이 작업이 수행됨.

3.5.1.2 드라이버의 주요 동작

  1. get_next_item(req);
    • 시퀀서에서 트랜잭션을 요청하는 메서드.
    • 시퀀서에서 트랜잭션이 준비될 때까지 블로킹(blocking) 상태로 대기.
    • 트랜잭션이 준비되면, 이를 받아서 처리할 수 있도록 반환.
  2. 트랜잭션을 DUT로 전송
    • 시퀀서에서 받은 트랜잭션을 실제 DUT에 맞게 변환하여 입력.
    • 해당 트랜잭션이 올바르게 실행되도록 인터페이스 신호를 제어.
  3. item_done();
    • 트랜잭션이 완료되었음을 시퀀서에 알리는 메서드.
    • 다음 트랜잭션 요청을 처리할 준비가 되었음을 시퀀서에 전달.

3.5.1.3 기본 루프 형태

UVM 드라이버의 run_phase() 내에서 반복적으로 수행되는 동작의 기본 구조는 다음과 같다.

forever begin
    get_next_item(req);   // 시퀀서에서 트랜잭션을 요청하여 가져옴
    // 프로토콜을 따르는 방식으로 트랜잭션 실행 (DUT에 전달)
    item_done();          // 트랜잭션이 끝났음을 알림
end

3.5.1.4 실행 흐름 예제

아래 예제는 simple_driver에서 시퀀서와의 상호작용을 구현한 코드이다.

class simple_driver extends uvm_driver #(simple_item);

    `uvm_component_utils(simple_driver)

    function new (string name = "simple_driver", uvm_component parent);
        super.new(name, parent);
    endfunction : new

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        if (!uvm_config_db#(virtual dut_if)::get(this, "", "vif", vif))
            `uvm_fatal("NOVIF", {"Virtual interface must be set for: ", get_full_name(), ".vif"});
    endfunction : build_phase

    virtual task run_phase(uvm_phase phase);
        forever begin
            simple_item req;
            seq_item_port.get_next_item(req);  // 트랜잭션 요청 (블로킹)
            drive_item(req);                   // DUT에 데이터 전달
            seq_item_port.item_done();         // 트랜잭션 완료 알림
        end
    endtask : run_phase

    task drive_item(simple_item item);
        // DUT의 프로토콜을 따르는 방식으로 데이터 전송
        vif.addr <= item.addr;
        vif.data <= item.data;
        #10;
        vif.write_enable <= 1;
        #10;
        vif.write_enable <= 0;
    endtask : drive_item

endclass : simple_driver

3.5.1.5 코드 설명

  • seq_item_port.get_next_item(req);
    • 시퀀서에서 새로운 트랜잭션을 요청하여 가져옴.
    • 트랜잭션이 생성될 때까지 블로킹됨.
  • drive_item(req);
    • 시퀀서에서 받은 데이터를 drive_item() 메서드를 통해 DUT에 전달.
  • seq_item_port.item_done();
    • 현재 트랜잭션이 완료되었음을 시퀀서에 알림.

3.5.1.6 get_next_item()의 블로킹 동작

  • get_next_item()은 트랜잭션이 생성될 때까지 블로킹되므로 시퀀서에서 트랜잭션이 제공될 때까지 실행이 멈춘다.
  • 즉, 시퀀서에서 새로운 트랜잭션을 생성하지 않으면 드라이버는 대기 상태로 남아 있음.

✅ 3.5.1 요약

  • get_next_item()은 시퀀서에서 트랜잭션을 요청하는 블로킹 메서드.
  • item_done()은 트랜잭션 처리가 완료되었음을 시퀀서에 알리는 메서드.
  • 드라이버는 forever 루프를 통해 트랜잭션을 계속 가져와 실행.
  • 시퀀서가 트랜잭션을 제공할 때까지 get_next_item()은 대기 상태로 유지됨.

 

 

 


 

본 내용은
accellera에서 공개한
Universal Verification Methodology
(UVM) 1.2 User's Guide
를 바탕으로 작성된 글입니다.