# 디지털 및 아날로그 회로의 공동 시뮬레이션: Icarus Verilog과 NGSpice 브리지의 두 가지 접근 방식
현대 전자 시스템은 디지털과 아날로그 구성 요소의 통합을 요구하며, 혼합 신호 시뮬레이션이 매우 중요합니다. 이 도전을 해결하기 위해 Icarus Verilog과 NGSpice 간 브리지를 구현하면서 두 가지 아키텍처를 개발했습니다. 각 아키텍처는 근본적인 한계를 지니고 있지만, SAR ADC부터 시그마-델타 변조기까지 실제 문제를 해결할 수 있게 해줍니다.
혼합 신호 시뮬레이션의 기본: 이벤트 vs. 연속성
디지털 회로는 이벤트로 모델링됩니다. 시뮬레이터는 신호 변화(클럭 에지, 플립플롭 토글) 시에만 활성화됩니다. Icarus Verilog과 다른 디지털 시뮬레이터가 바로 이렇게 작동합니다—이벤트 사이에서는 시스템이 "잠들어" 있어 높은 성능을 보장합니다. 아날로그 회로는 연속 모델링이 필요합니다. SPICE 엔진(NGSpice, Spectre)은 시간을 작은 단계로 나누어 각 구간마다 미분 방정식을 풉니다. 이 방법은 정확하지만 자원이 많이 들며, 특히 날카로운 에지나 피드백 루프에서 그렇습니다.
공동 시뮬레이션의 핵심 도전 과제는 이 근본적으로 다른 패러다임을 조화시키는 것입니다. 디지털 시뮬레이터는 이산 이벤트를 다루고, 아날로그 시뮬레이터는 부드러운 시간 흐름이 필요합니다. SAR ADC(아날로그 비교기가 디지털 로직과 상호작용하는 경우)에서 딜레마가 생깁니다: 엔진 간 데이터 전달 시 중요한 이벤트를 잃지 않고 어떻게 처리할까?
브리지 아키텍처: 공통 원리
두 구현 모두 동일한 핵심 기술을 사용합니다:
- Icarus와 상호작용을 위한 VPI (Verilog Procedural Interface)
- 동적 라이브러리 libngspice.so
- 세마포어를 사용한 스트리밍 메커니즘
- 별도의 NGSpice 실행 스레드
중심 요소는 클럭 신호 에지에서 호출되는 시스템 태스크 $spice_sync()입니다. 이는 전체 교환 주기를 수행합니다: alter 명령으로 디지털 값을 SPICE에 전달하고, 아날로그 전압을 쿼리하며, Verilog의 실수형 변수에 업데이트합니다. 이를 통해 GTKWave에서 디지털 신호와 동일한 타임라인에 아날로그 신호를 표시할 수 있습니다.
always @(posedge clk_fast) begin
$spice_sync();
if (tb.Vcmp > vref_th) begin
// Reaction to event
...
end
end
expose_analog_N 메커니즘은 아날로그 변수를 자동 동기화하여 디지털 로직에서 접근 가능하게 합니다. 브리지 양쪽의 래퍼 객체가 에지와 지연을 처리합니다.
전통적 접근법: 동기 폴링
이 구현에서는 Verilog이 매 $spice_sync() 호출마다 교환을 시작합니다. 시뮬레이터는 현재 시간을 기록하고 세마포어에서 블록하며, 제어를 NGSpice에 넘깁니다. NGSpice는 그 시점까지 시뮬레이션한 후 데이터를 반환합니다.
장점:
- 완전한 결정성
- 예측 가능한 성능
- 간단한 구현(약 2000줄 코드)
치명적 한계:
- 클럭 에지 사이 아날로그 이벤트 완전 무시. 예를 들어 비교기가 5.2 ns에 전환되는데 다음 클럭이 10.0 ns라면, 디지털 로직은 4.8 ns 동안 변화를 감지하지 못해 SAR ADC나 DC-DC 컨버터의 피드백 루프가 불가능합니다.
- 강제 오버샘플링: 빠른 이벤트를 포착하려면 클럭 주파수를 인위적으로 높여야 합니다(예: 500 MHz), 성능 저하를 초래합니다.
이 접근법은 아날로그 이벤트가 클럭 에지와 맞물리거나 동기화를 위한 고주파 클럭이 있는 작업에만 적합합니다.
대안적 접근법: 선행 분석
전통적 방법의 한계를 극복하기 위해 선행 메커니즘을 구현했습니다. NGSpice는 설정된 간격만큼 "선행 실행" 허가를 받고, 구성 가능한 센서를 통해 아날로그 이벤트를 추적합니다. mixed_bridge.cfg의 예시 규칙:
analog_event_0 = threshold outp rising 1.2 | time_var=tb.analog_event_time id_var=tb.analog_event_id
조건이 트리거되면 SPICE가 일시정지하고 cbAfterDelay 콜백을 통해 Verilog에 이벤트를 시작합니다.
장점:
- 비동기 아날로그 이벤트 감지 가능
- 구성 가능한 유연성(임계값, 지속 시간, 에너지 조건)
- 낮은 클럭 빈도에서도 부하 감소
근본적 단점:
- SPICE 스텝 사이 이산 시간 적분으로 인한 이벤트 누락
- 인과성 위반:
alter명령(디지털 신호 변화)은 다음 시뮬레이션 단계에서만 적용되어 DAC에 치명적 - 분석 창당 하나의 이벤트 제한
- 선행 간격 길이 선택 휴리스틱으로 인한 비결정성
- 구현 복잡성(3500+줄 코드 + 구성 파서)
주요 차이점 비교
아키텍처 간 주요 트레이드오프는 다섯 가지 측면에서 나타납니다:
- 이벤트 감지: 전통적 방법은 클럭 사이 이벤트를 완전히 놓치고, 대안은 부분적으로 포착하지만 누락 위험이 있음
- 인과성: 전통적 접근에서 DAC→아날로그 연결이 정확; 대안에서는 타이밍 불일치 가능
- 성능: 동기 방법은 안정적 속도; 선행은 짧은 간격에서 극적으로 느려짐
- 결정성: 전통적 구현만 재현 가능한 결과를 보장
- 통합 복잡성: 대안은 휴리스틱 미세 조정과 회로 타이밍 분석 필요
주요 교훈
- 완벽한 해결책 없음: 모델링 패러다임의 근본 차이로 두 아키텍처 모두 내재적 한계 존재
- 작업에 따라 선택: 희귀 펄스의 시그마-델타 변조기에는 대안 적합; 엄격한 타이밍의 SAR ADC에는 오버샘플링 전통적 방법 적합
- 실제 적용성: 아날로그 환경에서 디지털 로직 검증과 펄스 카운팅에 이미 사용 중
- 시각화: GTKWave와 gnuplot에서 통합 타임라인 신호 표시 지원
- 전망: 이벤트 큐 통합과
cbNextSimTime사용으로 한계 완화 가능
실제 구현 및 사용 예시
시그마-델타 변조기에 브리지를 사용하는 경우를 생각해 보세요. 아날로그 부분이 짧은 펄스를 생성하고 디지털 카운터가 이를 세야 합니다. 전통적 접근에서는 펄스 지속 시간을 초과하는 주파수에서 $spice_sync()를 호출합니다. 예시 Verilog 코드:
module DSMCounter(
input i_clk,
input i_rst,
input i_Qbar,
output reg[31:0] o_cntQbar,
output reg o_ready
);
parameter CNT_CLK = 22;
reg [31:0] cnt;
reg [31:0] cntQbar;
always @(posedge i_clk) begin
if(i_rst) begin
cnt <= 0;
cntQbar <= 0;
o_cntQbar <= 0;
o_ready <= 0;
end else begin
o_ready <= 0;
if(i_Qbar == 1) begin
cntQbar <= cntQbar + 1;
end
if(cnt == CNT_CLK-1) begin
o_cntQbar <= cntQbar;
o_ready <= 1;
cnt <= 0;
cntQbar <= 0;
end else begin
cnt <= cnt + 1;
end
end
end
endmodule
대안 구현에서는 analog_event를 통한 펄스 감지 규칙으로 동기 주파수를 낮출 수 있습니다. 하지만 누락을 피하기 위해 선행 매개변수를 세심하게 조정해야 합니다.
실행을 위해 공유 NGSpice 빌드(--with-ngshared)가 필요합니다. 브리지 구성은 mixed_bridge.cfg를 통해 설정하며, 동기 지점과 이벤트 감지 규칙을 정의합니다. 두 구현 모두 오픈 소스지만 특정 작업에 대한 테스트가 필요합니다.
미래 방향으로는 단일 플래그 대신 이벤트 큐 구현, 브리지 구성에 maxstep 통합, 정확한 시간 제어를 위한 cbNextSimTime 사용이 포함됩니다. 완전한 해결책을 위해 NGSpice에 이벤트 API 추가가 필요합니다.
— Editorial Team
아직 댓글이 없습니다.