이 백서에서는 IP 코어를 사용하는 방법을 설명합니다. Moku 클라우드 컴파일여기에는 일반적인 신호 처리 기능을 위한 8개의 사전 컴파일된 IP 코어와 맞춤형 AMD Vivado IP 코어 통합이 포함됩니다. 각 코어는 Moku 하드웨어를 사용한 사용 사례 및 테스트 설정과 함께 설명됩니다. 또한 이 문서는 사용자가 맞춤형 IP를 업로드하는 방법도 안내합니다.
개요
Moku Cloud Compile은 Moku 기기에서 사용할 수 있는 강력한 도구입니다. Moku FPGA 기반 테스트 및 측정 기기를 사용하면 사용자 정의 VHDL 및 Verilog 코드를 하드웨어에 배포할 수 있습니다. Moku Cloud Compile을 사용하면 기존 기기에 사용자 정의 설계를 통합하여 기기 기능을 확장하고 사용자 정의할 수 있으며, Moku 고유의 Instrument-on-Chip 아키텍처를 통해 새로운 기능을 구현할 수 있습니다. Moku Cloud Compile은 모든 Moku 기기와 호환되는 산술, 필터링, 파형 생성 및 상관 분석에 최적화된 8개의 사전 컴파일된 IP 코어를 제공합니다. 이러한 코어는 바로 인스턴스화하여 일반적인 디지털 신호 처리 작업을 간소화할 수 있습니다. 또한 사용자는 AMD Vivado에서 생성한 자체 IP 코어를 업로드하여 가져올 수도 있습니다. .xci 이 파일들을 통해 사용자 정의 하드웨어 블록을 Moku Cloud Compile 디자인에 원활하게 통합할 수 있습니다. 이 문서에서는 각 IP 코어의 입/출력 포트, 기능 및 사용 예시를 설명하고, 사용자 정의 디자인을 구축하고 테스트하는 방법에 대한 지침을 제공합니다. 다중 장비 모드이러한 기능을 모두 갖춘 Moku Cloud Compile은 신속한 프로토타입 제작과 고급 신호 처리 애플리케이션 모두에 적합한 더욱 강력한 플랫폼이 됩니다.
8개의 사전 컴파일된 IP 코어
이 섹션에서는 표 1에 나열된 XNUMX개의 사전 컴파일된 IP 코어에 대해 설명하고, 각 코어의 입출력 포트 사양과 기능을 자세히 설명합니다. 각 코어에 대한 사용 사례도 제공됩니다. Moku Cloud Compile 백엔드에 기본적으로 통합되어 있어, 이러한 IP 코어는 사용자 설계 내에서 직접 인스턴스화할 수 있으므로 개발 프로세스가 간소화되고 구현 오버헤드가 줄어듭니다.
표 1: 미리 컴파일된 XNUMX개의 IP 코어의 이름과 설명.
| 그렇지 않습니다. | IP 코어 이름 | 기술설명 |
| 1 | 더하기 빼기_16 | 동적으로 재구성 가능한 덧셈기/뺄셈기 모듈. |
| 2 | CIC_Dec_3Ordx8 | 8의 데시메이션 인자와 3의 필터 차수를 갖춘 Cascaded Integrator-Comb(CIC) 데시메이터입니다. |
| 3 | 코르딕_번역_16 | 16비트 실수 및 허수 입력을 진폭 및 위상 출력으로 변환하는 변환기입니다. |
| 4 | 카운터_32 | 동기식 클리어 기능을 갖춘 업/다운 카운팅을 지원하는 32비트 카운터입니다. |
| 5 | SineGen_48 | 48비트 주파수 단계 분해능을 갖춘 사인 및 코사인 파형 생성기입니다. |
| 6 | FIR_필터_7계수 | 고정 계수를 갖는 풀 레이트 FIR 저역 통과 필터. |
| 7 | FFT_1024 | 선택 가능한 전방 또는 역방향 변환 기능을 갖춘 1,024포인트 고속 푸리에 변환(FFT) 블록입니다. |
| 8 | FFT_65536 | 선택 가능한 전방 또는 역방향 변환과 구성 가능한 출력 스케일링을 갖춘 65,536포인트 고속 푸리에 변환(FFT) 블록입니다. |
1. 더하기 빼기_16
AddSubtract_16 모듈은 두 개의 부호 있는 16비트 입력에 대해 덧셈 또는 뺄셈을 수행할 수 있는 동적으로 구성 가능한 산술 연산 장치를 구현합니다. 이 모듈의 동작은 다음 논리에 의해 제어됩니다.
\(S =left{ begin{array}{rl} A + B text{(add: HIGH)} A – B text{(add: LOW)} end{array} right.\)AddSubtract_16 코어의 입력 및 출력 포트는 표 2에 자세히 설명되어 있습니다. 두 입력 버스(A 및 B)와 출력(S)은 모두 부호 있는 16비트 정수(int16)로 처리됩니다. 산술 연산은 add 신호로 제어되며, ce(클록 활성화) 신호는 모듈의 클록을 활성화 또는 비활성화합니다. ce 신호가 HIGH로 유지되면 모듈은 지속적으로 활성화됩니다.
표 2: AddSubtract_16 모듈에 대한 포트 정의, 입력 및 출력 신호 인터페이스를 자세히 설명합니다.
| 이름 | 방향 | 기술설명 |
| 아[15:0] | 입력 | A 버스를 입력하세요. |
| 비[15:0] | 입력 | 입력 B 버스. |
| clk | 입력 | 클록 신호, 상승 에지. |
| 더하다 | 입력 | AddSubtract_16 함수가 수행하는 연산을 제어합니다. (높음 = 덧셈, 낮음 = 뺄셈) |
| ce | 입력 | 액티브 하이 클럭 활성화. 상시 하이로 설정. |
| S[15:0] | 산출 | 출력 버스. |
코드 1은 Control0의 0번째 비트(최하위 비트, LSB)를 사용하여 모듈과 제어를 인스턴스화하는 방법을 보여주는 VHDL 예제를 제공합니다. 다중 계측기 모드 구성은 그림 1에 나와 있습니다. 그림 2와 3에 표시된 테스트 결과는 Moku 하드웨어를 사용하여 다양한 신호 조건에서 뺄셈과 덧셈이 올바르게 동작함을 보여줍니다.
코드 1: VHDL 예제는 AddSubtract_16 모듈의 인스턴스화를 보여줍니다. 여기서 OutputA는 Control0 레지스터의 LSB 상태에 따라 InputA + InputB 또는 InputA – InputB의 결과를 나타냅니다.
LIBRARY ieee;
ARCHITECTURE Behavioral OF CustomWrapper IS
SIGNAL s_temp : STD_LOGIC_VECTOR(15 DOWNTO 0);
BEGIN
AddSubtract : AddSubtract_16
PORT MAP(
A => STD_LOGIC_VECTOR(InputA),
B => STD_LOGIC_VECTOR(InputB),
clk => clk,
-- use Control0's 0th bit to control the operation
add => Control0(0),
-- constant high clock enable
ce => '1',
S => s_temp
);
OutputA <= signed(s_temp);
END ARCHITECTURE;

그림 1: 다중 계측 모드를 사용한 AddSubtract_16 테스트 구성. 이 설정에서 Moku Cloud Compile의 InputA와 InputB는 Moku 오실로스코프의 출력에서 내부적으로 라우팅되고, Moku Cloud Compile에서 처리된 출력은 오실로스코프로 피드백됩니다. 그림 2에서 보는 바와 같이, Moku 오실로스코프에 내장된 2채널 파형 발생기는 5kHz, 500mV 사인파와 90% 대칭의 100Hz, 5Vpp 램프 신호를 생성하도록 구성되어 있습니다. Control0의 LSB가 0으로 설정되면 Moku Cloud Compile은 감산 모드로 작동합니다. 관찰되는 출력은 다음과 같습니다. 모쿠 오실로스코프 예상된 감산기 동작을 확인합니다. 이후 그림 3에서 Control0의 LSB를 1로 설정하여 Moku Cloud Compile이 덧셈을 수행하도록 구성합니다. 결과 출력은 예상된 덧셈기 기능을 확인합니다.

그림 2: Moku Cloud Compile은 두 개의 입력 신호(500mVpp, 5kHz 사인파와 5Vpp, 100Hz 램프파)를 사용하여 뺄셈 결과를 출력합니다. Control0(0)을 0으로 설정하면 시스템은 뺄셈 모드로 작동하도록 구성됩니다.

그림 3: 500mVpp, 5kHz 사인파와 5Vpp, 100Hz 램프파에 대한 Moku 클라우드 컴파일 출력. Control0(0)이 1로 설정되면 시스템은 덧셈 모드로 구성됩니다. AddSubtract_16 모듈에는 캐리 아웃 메커니즘이 포함되어 있지 않으므로 산술 연산 중에 오버플로가 발생할 수 있다는 점에 유의해야 합니다. 특히 입력 A + 입력 B의 합이 부호 있는 16비트 범위 \([-2^{15}, 2^{15}]\)를 초과하면 오버플로로 인해 출력에 부호 반전이 발생할 수 있습니다. 잠재적인 오버플로를 감지하는 일반적인 방법은 피연산자와 결과의 최상위 비트(MSB)를 모니터링하는 것입니다. 입력의 부호가 반대이면 오버플로가 발생하지 않습니다. 그러나 두 입력의 부호가 같고 출력의 부호가 다르면 일반적으로 오버플로 상태를 나타냅니다. 본 논문에서는 해당 문제를 인지하고 있지만, 오버플로 감지 및 완화 기법에 대한 자세한 논의는 본 논문의 범위를 벗어납니다. 입력 소스는 5Vpp 사인파와 5V DC 신호로 구성됩니다. 이론적으로 이 조합은 2.5V에서 7.5V 사이의 출력 파형을 생성해야 합니다. 그러나 Moku:Go 하드웨어는 ±5V 입력/출력 범위(10Vpp)로 제한됩니다. 결과적으로 출력에서 이 범위를 벗어나는 부분은 오버플로로 인해 부호가 반전됩니다. 이러한 동작은 그림 4에서 확인할 수 있는데, 5V와 7.5V 사이에 있어야 할 파형 부분이 -2.5V와 -5V 사이에 나타나도록 왜곡되어 있습니다.

그림 4: 5Vpp, 1kHz 사인파와 5V DC 오프셋을 더하면 신호가 Moku:Go 장치의 ±5V 입력 범위를 초과하므로 관찰 가능한 오버플로가 발생합니다. Control0(0)을 1로 설정하면 시스템은 가산 모드로 작동하며, 출력의 부호 반전은 오버플로 발생을 확인합니다.
2. CIC_Dec_3Ordx8
CIC_Dec_3Ordx8 모듈은 고정된 데시메이션 비율 8을 갖는 3차 캐스케이드 적분기-콤(CIC) 데시메이션 필터를 구현합니다. CIC 필터는 높은 샘플링 속도를 낮춰야 하는 멀티레이트 시스템에서 널리 사용됩니다. 이 아키텍처는 가산기, 감산기 및 지연에만 의존하므로 디지털 수신기 및 록인 증폭기와 같은 하드웨어 효율적인 다운샘플링 애플리케이션에 이상적입니다. 모듈의 입력 및 출력 포트는 표 3에 요약되어 있으며, 지연 시간 및 필터 차수와 같은 구현 세부 정보는 표 4에 제공됩니다. 이 모듈은 16비트 부호 있는 입력 샘플을 받아들이고 25비트 부호 있는 출력 샘플을 생성합니다. 입력 인터페이스는 입력 및 출력 채널 모두에 대한 핸드셰이크 신호(tvalid, tready)를 제공합니다. 필터는 유효한 입력이 수신되고 코어가 준비된 경우에만 출력을 업데이트합니다.
표 3: CIC_Dec_3Ordx8 IP 코어에 대한 포트 설명.
| 이름 | 방향 | 기술설명 |
| aclk | 입력 | 클록 신호, 상승 에지. |
| s_축_데이터_t데이터 [15:0] | 입력 | 데이터 입력 채널의 TDATA입니다. 처리되지 않은 샘플 데이터를 전달합니다. |
| s_axis_data_tvalid | 입력 | 데이터 입력 채널의 TVALID입니다. 외부 블록에서 데이터를 제공할 수 있음을 알리는 데 사용됩니다. |
| s_축_데이터_트레디 | 산출 | TREADY는 데이터 입력 채널을 나타냅니다. CIC 데시메이터가 데이터를 수신할 준비가 되었음을 알리는 데 사용됩니다. |
| m_축_데이터_t데이터 [24:0] | 산출 | 데이터 출력 채널(TDATA)입니다. 처리된 샘플 데이터를 전달합니다. |
| m_axis_data_tvalid | 산출 | 데이터 출력 채널의 TVALID입니다. CIC 데시메이터가 샘플 데이터를 제공할 수 있음을 알리기 위해 사용합니다. |
표 4: CIC_Dec_3Ordx8 IP 코어의 구성 매개변수.
| 구성 요소 이름 | CIC_Dec_3Ordx8 |
| 필터 유형 | 데시 메이션 |
| 단계 수 | 3 |
| 차등 지연 | 1 |
| 지원되는 속도 | 8 |
| 입력 샘플 주파수(MSa/s) | 31.25 |
| 클록 주파수(MHz) | 31.25 |
| 입력 데이터 너비 | 16 |
| 출력 데이터 너비 | 25 |
| 숨어 있음 | 15 |
제공된 VHDL 예제(코드 2 참조)에서 입력 데이터는 코어가 준비된 상태(s_axis_data_tready가 높음)일 때만 기록되고, 출력은 유효한 데이터가 있는 경우(m_axis_data_tvalid가 높음)에만 캡처됩니다. 출력은 입력 동적 범위와의 일관성을 유지하기 위해 최상위 16비트로 잘리는 방식으로 스케일링됩니다. 중요한 점은 유효 신호가 반드시 활성화되어야 하며, 이 신호가 높을 때만 출력을 업데이트해야 한다는 것입니다. 그렇지 않으면 출력이 연속적인 스트림이 아닌 펄스형 또는 간헐적인 동작을 보일 수 있습니다. 이는 CIC_Dec_3Ordx8이 데시메이션 팩터에 따라 8클록 사이클마다 하나의 유효 출력 샘플을 생성하기 때문에 발생합니다.
코드 2: 8배 데시메이션 계수를 갖는 CIC 데시메이터의 인스턴스화를 보여주는 VHDL 예제입니다. OutputA 신호는 InputA 신호의 다운샘플링된 버전을 나타냅니다.
LIBRARY ieee;
ARCHITECTURE Behavioral OF CustomWrapper IS
SIGNAL s_axis_data_tready : STD_LOGIC;
SIGNAL s_axis_data_tdata : STD_LOGIC_VECTOR(15 DOWNTO 0);
SIGNAL m_axis_data_tvalid : STD_LOGIC;
SIGNAL m_axis_data_tdata : STD_LOGIC_VECTOR(31 DOWNTO 0);
BEGIN
Decimator : CIC_Dec_3Ordx8
PORT MAP(
aclk => clk,
s_axis_data_tdata => s_axis_data_tdata,
s_axis_data_tvalid => '1', -- always output
s_axis_data_tready => s_axis_data_tready,
m_axis_data_tdata => m_axis_data_tdata,
m_axis_data_tvalid => m_axis_data_tvalid
);
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
-- update input data when CIC is ready
IF s_axis_data_tready THEN
s_axis_data_tdata <= STD_LOGIC_VECTOR(InputA);
ELSE
s_axis_data_tdata <= (OTHERS => '0');
END IF;
-- update Output only when data is valid
IF m_axis_data_tvalid THEN
-- Scale data correctly
OutputA <= signed(m_axis_data_tdata(24 DOWNTO 9));
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
다중 계측기 모드 테스트 설정은 다음을 사용합니다. Moku 주파수 응답 분석기 필터의 주파수 응답을 평가하는 방법은 그림 5에 나와 있습니다. CIC 필터의 주파수 응답은 대역 외 신호의 감쇠를 특성화하고 데시메이션 중 앨리어싱 잡음을 억제하는 효과를 나타내므로 특히 중요합니다. 그림 6과 그림 7의 측정 결과는 데시메이션 및 보간 아티팩트로 인한 예상 불일치를 고려하여 이론적 예측과 잘 일치합니다.

그림 5: Moku 주파수 응답 분석기를 사용하여 Moku 클라우드 컴파일 출력을 분석하는 다중 계측기 모드 테스트 구성입니다.

그림 6: Moku 주파수 응답 분석기를 사용하여 얻은 CIC_Dec_3Ordx8 IP 코어의 주파수 응답.

그림 7: CIC_Dec_3Ordx8의 시뮬레이션 및 구현된 응답 비교.
3. 코르딕_트랜슬레이트_16
CORDIC 코어는 삼각 함수를 계산하고, 더 일반적으로는 쌍곡선 및 제곱근 연산을 포함하는 방정식을 푸는 데 사용되는 반복적인 방법인 CORDIC(Coordinate Rotation Digital Computer) 알고리즘을 구현합니다. 입력 및 출력 포트에 대한 설명은 표 5에 나와 있습니다. 이 Cordic_Translate_16 코어는 입력 신호를 데카르트 표현(실수 및 허수 성분)에서 해당 극형(진폭 및 위상)으로 변환합니다. 이 모듈의 총 계산 지연 시간은 20클럭 사이클입니다.
표 5: Cordic_Translate_16 IP 코어의 포트 정의.
| 이름 | 방향 | 기술설명 |
| aclk | 입력 | 시계. 활성 상승 에지. |
| s_축_데카르트_t유효 | 입력 | 채널 S_AXIS_CARTESIAN에 대한 핸드셰이크 신호입니다. |
| s_축_직교_t데이터 [31:0] | 입력 | 기능 구성에 따라 이 포트는 하나 또는 두 개의 하위 필드를 가집니다. X_IN과 Y_IN은 각각 [15:0]과 [31:16]입니다. 이들은 직교 좌표계 피연산자입니다. 각 하위 필드는 16비트 폭을 가지며, X_IN과 Y_IN 모두 14개의 소수 비트와 2개의 정수 비트로 구성됩니다. |
| m_축_dout_tvalid | 산출 | 출력 채널에 대한 핸드셰이크 신호. |
| m_축_도트_t데이터 [31:0] | 산출 | 기능 구성에 따라 이 포트는 다음과 같은 하위 필드를 포함합니다. AMPLITUDE_OUT, PHASE_OUT. AMPLITUDE_OUT은 [15:0]이고 PHASE_OUT은 [31:16]입니다. 각 하위 필드는 16비트입니다. AMPLITUDE_OUT은 소수점 이하 14비트와 정수 2비트로 구성됩니다. PHASE_OUT은 소수점 이하 13비트와 정수 3비트로 구성되며 단위는 라디안입니다. |
Cordic_Translate_16 IP 코어는 신호의 허수(InputA)와 실수(InputB) 성분을 해당 진폭(OutputA)과 위상 각도(OutputB)로 변환하는 코드 3을 사용하여 인스턴스화할 수 있습니다.
코드 3: Cordic_Translate_16 IP 코어의 인스턴스화를 보여주는 VHDL 구현 예제입니다.
LIBRARY ieee;
ARCHITECTURE Behavioral OF CustomWrapper IS
SIGNAL m_axis_dout_tvalid : STD_LOGIC;
SIGNAL tdata_temp : signed(31 DOWNTO 0);
BEGIN
Cordic : Cordic_Translate_16
PORT MAP(
aclk => clk,
-- input is always valid
s_axis_cartesian_tvalid => '1',
-- InputA : imaginary part
-- InputB : real part
s_axis_cartesian_tdata => STD_LOGIC_VECTOR(InputA & InputB),
m_axis_dout_tvalid => m_axis_dout_tvalid,
m_axis_dout_tdata => tdata_temp
);
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF m_axis_dout_tvalid THEN
OutputA <= signed(tdata_temp(15 DOWNTO 0));
OutputB <= signed(tdata_temp(31 DOWNTO 16));
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
인스턴스화된 Cordic_Translate_16은 그림 8에 표시된 다중 계측 모드 설정을 사용하여 테스트됩니다. Moku Cloud Compile InputA(허수)와 InputB(실수)는 Moku 오실로스코프 출력에서 Moku Cloud Compile로 내부적으로 전달되어 해당 진폭 및 위상 출력을 계산합니다. 그런 다음 이러한 Moku Cloud Compile 출력은 시각화 및 분석을 위해 다시 오실로스코프로 전달됩니다. 결과는 그림 9에 나와 있습니다. 파란색 파형은 3.9288V의 최대값에 도달하며, 이는 약 3.1415라디안에 해당합니다. 위상 출력은 13비트 소수점으로 표현되므로 해상도는 2^13 LSB/rad입니다. 디지털 값을 물리적 단위로 변환하려면 Moku Cloud Compile의 디지털 해상도를 확인해야 하며, 이는 찾을 수 있습니다. 여기에서 확인하세요Moku:Go에서 6550.4 LSB/V의 디지털 해상도가 주어졌을 때 라디안 값은 다음과 같이 계산됩니다.
\(frac{text{3.9288 V} times text{6550.4 LSBs/V}}{2^{13} text{LSBs/rad}}=text{3.1415 rad}\)또한 Cordic_Translate_16에서 수행된 20번의 반복 동안 도입된 스케일링 효과의 누적으로 인해 진폭 출력의 크기가 약 1.1644배 증가합니다.

그림 8: Cordic_Translate_16 IP 코어 테스트를 위한 다중 계측기 모드 테스트 설정.

그림 9: 두 개의 출력 채널은 100° 위상 편이를 통해 5Vpp의 90Hz 사인파로 구성되어 연속 회전하는 복소 벡터를 에뮬레이션합니다. 입력 A(빨간색 선)는 진폭을, 입력 B(파란색 선)는 위상을 나타냅니다. 예상대로 진폭은 일정하게 유지되고 위상은 시간에 따라 2𝜋 라디안마다 선형적으로 증가합니다.
4. 카운터_32
Counter_32 IP 코어는 룩업 테이블(LUT)과 단일 DSP 슬라이스를 활용한 카운터 구현을 제공합니다. 입력 및 출력 포트 기능은 표 6에 설명되어 있습니다. 32비트 출력 폭을 갖는 업/다운 카운팅 모드를 지원합니다. 카운터는 매 클럭 사이클마다 XNUMX씩 증가하며, SCLR 신호를 하이(High)로 설정하여 동기적으로 클리어할 수 있습니다.
표 6: Counter_32의 포트 정의.
| 이름 | 방향 | 기술설명 |
| CLK | 입력 | 상승 에지 클록 신호. |
| SCLR | 입력 | 동기식 클리어: 높게 구동될 때 출력을 낮은 상태로 강제합니다. |
| UP | 입력 | 업/다운 카운터의 카운트 방향을 제어합니다. 값이 높으면 카운트를 올리고, 값이 낮으면 카운트를 내립니다. |
| 큐 [31:0] | 산출 | 카운터 출력. 32비트 폭. |
코드 4의 예제는 두 개의 Counter_32 함수를 구현합니다. 하나는 양방향 카운팅으로 삼각파를 생성하도록 구성되고, 다른 하나는 단방향 카운팅으로 톱니파를 생성하도록 구성됩니다. 설계가 16 미만의 범위에서 작동하므로 카운터의 최하위 65,536비트만 출력에 연결됩니다.
코드 4: 삼각파와 톱니파에 대한 두 개의 Counter_32를 인스턴스화하는 VHDL 예제입니다.
LIBRARY ieee;
ARCHITECTURE Behavioural OF CustomWrapper IS
SIGNAL sclr_triangular : STD_LOGIC;
SIGNAL sclr_sawtooth : STD_LOGIC;
SIGNAL up_triangular : STD_LOGIC;
SIGNAL up_sawtooth : STD_LOGIC;
SIGNAL q_triangular : STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL q_sawtooth : STD_LOGIC_VECTOR(31 DOWNTO 0);
BEGIN
-- Triangular wave
Triangular : Counter_32
PORT MAP(
clk => clk,
-- synchronous clear
sclr => sclr_triangular,
up => up_triangular,
q => q_triangular
);
OutputA <= signed(q_triangular(15 DOWNTO 0));
-- Triangular counter configuration
PROCESS (clk) IS
BEGIN
IF rising_edge(clk) THEN
-- reset
IF Control0(0) = '1' THEN
sclr_triangular <= '1';
up_triangular <= '1';
ELSE
-- don't clear
sclr_triangular <= '0';
-- Control1: counter limit
IF q_triangular = Control1 THEN
-- count down
up_triangular <= '0';
ELSIF q_triangular = x"00000000" THEN
-- count up
up_triangular <= '1';
ELSE
-- hold
up_triangular <= up_triangular; END IF; END IF; END IF; END PROCESS; Sawtooth : Counter_32 PORT MAP( clk => clk,
sclr => sclr_sawtooth, -- synchronous clear
up => up_sawtooth,
q => q_sawtooth
);
OutputB <= signed(q_sawtooth(15 DOWNTO 0));
-- Sawtooth counter configuration
PROCESS (clk) IS
BEGIN
IF rising_edge(clk) THEN
-- reset
IF Control0(0) = '1' THEN
sclr_sawtooth <= '1';
up_sawtooth <= '1';
ELSE
-- always count up
up_sawtooth <= '1';
-- Control2 : counter limit
IF q_sawtooth = Control2 THEN
-- clear
sclr_sawtooth <= '1';
ELSE
-- continue counting
sclr_sawtooth <= '0';
END IF;
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
그림 10은 다중 계측 모드 구성을 보여줍니다. Moku 오실로스코프를 사용하여 두 개의 Counter_32 모듈에서 생성된 파형을 시각화했습니다. 두 카운터 모두 Control1과 Control2를 통해 6,550의 제어 값으로 구성되었으며, Moku:Go의 디지털 해상도인 6550.4 LSB/V를 기준으로 약 1V의 피크 출력을 생성합니다. Control0의 LSB는 리셋 신호 역할을 하며, 작동 전에 하이로 설정했다가 로우로 되돌려야 합니다. 예상대로 톱니파형은 삼각파형보다 주파수가 두 배 높습니다. 톱니파형은 상향 카운팅만 하는 반면, 삼각파형은 상향과 하향 카운팅 주기를 번갈아 수행하기 때문입니다. 테스트 결과는 그림 11에 나와 있습니다. 빨간색 파형은 상향과 하향 카운팅이 번갈아 발생하는 삼각파형을 나타냅니다. 파란색 파형은 연속적으로 증가하다가 설정된 한계값인 6,550에 도달하면 리셋되는 톱니파형을 나타냅니다.

그림 10: Counter_32 테스트를 위한 다중 계측기 모드 구성.

그림 11: Moku Cloud 컴파일 제어 레지스터 구성 및 두 개의 Counter_32 모듈의 해당 출력.
5. SineGen_48
SineGen_48 IP 코어는 고해상도, 저왜곡 사인파를 생성합니다. 입력 및 출력 포트는 표 7에 자세히 나와 있습니다. 48비트 주파수 스텝 입력을 받아 32비트 출력 포트를 통해 16비트 사인파와 코사인파 출력을 모두 생성합니다. 이 모듈은 위상 고정 루프(PLL) 및 동시 진폭 주파수 변조(AM 및 FM)를 포함한 다양한 고급 응용 분야에 적합한 사인파 발생기 서브블록 역할을 합니다. SineGen_48 IP 코어는 48비트 주파수 스텝 입력을 필요로 하지만 Moku Cloud Compile의 제어 레지스터는 32비트로 제한되어 있으므로, 전체 48비트 입력을 구성하기 위해 두 개의 레지스터를 결합해야 합니다. 예를 들어, 코드 5에서는 Control2의 최하위 16비트를 Control1의 32비트와 연결하여 완전한 주파수 제어 워드를 구성합니다. 생성된 출력은 사인파와 코사인파에 해당하는 두 개의 16비트 구성 요소로 나뉘어 각각 OutputA와 OutputB로 출력됩니다. 또한, 내부 위상 카운터의 최상위 16비트는 OutputC로 출력됩니다.
코드 5: SineGen_48의 VHDL 인스턴스화 예제.
LIBRARY ieee;
ARCHITECTURE Behavioural OF CustomWrapper IS
SIGNAL m_axis_data_tvalid : STD_LOGIC;
SIGNAL m_axis_phase_tvalid : STD_LOGIC;
SIGNAL sine_temp : STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL m_axis_phase_tdata : STD_LOGIC_VECTOR(47 DOWNTO 0);
BEGIN
SineCosineGen : SineGen_48
PORT MAP(
aclk => clk,
-- Use the 0th bit of Control0 to reset this module
aresetn => NOT Control0(0),
-- input signal is always available
s_axis_config_tvalid => '1',
-- 48-bit frequency step
s_axis_config_tdata => Control2(15 DOWNTO 0) & Control1,
m_axis_data_tvalid => m_axis_data_tvalid,
m_axis_data_tdata => sine_temp,
m_axis_phase_tvalid => m_axis_phase_tvalid,
m_axis_phase_tdata => m_axis_phase_tdata -- 48-bit phase counter output
);
-- only output data when data is valid
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF m_axis_data_tvalid THEN
-- 32-bit, the most significant 16 bits are sine
-- and the least significant 16 bits are cosine
OutputA <= signed(sine_temp(15 DOWNTO 0));
OutputB <= signed(sine_temp(31 DOWNTO 16));
END IF;
IF m_axis_phase_tvalid THEN
OutputC <= signed(m_axis_phase_tdata(47 DOWNTO 32));
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
SineGen_48 IP 코어 테스트를 위한 다중 계측 모드 구성은 그림 12에 나와 있습니다. 주파수 스텝은 Control1을 2,374,548,092로, Control2를 6으로 설정하여 3.125kHz로 설정됩니다. 전체 48비트 주파수 제어 워드는 다음과 같이 계산됩니다.
\(주파수 단계} = text{제어 2} × 2^{32} + text{제어 1} = 2,814,749,767\)그리고 주파수는 Hz 단위로 다음과 같이 계산할 수 있습니다.
\(text{주파수} = frac{text{클럭 속도}}{2^{48}}×[text{컨트롤 2} × 2^{32} + text{컨트롤 1}]\)Moku:Go의 클럭 속도가 31.25MHz이므로 출력 주파수는 3.125kHz가 됩니다.

그림 12는 SineGen_48 IP 코어 테스트를 위한 다중 계측 모드 구성을 보여줍니다. 그림 13은 SineGen_48 IP 코어의 출력을 나타내며, 채널 A(빨간색)는 코사인 파형을, 채널 B(파란색)는 사인 파형을 나타냅니다. 두 신호 간의 위상차는 예상대로 90°입니다. 또한, 그림 14는 Moku Cloud Compile의 OutputC로 연결된 위상 카운터의 동작을 보여줍니다. 출력은 지속적으로 증가하는 램프 형태를 보여주며, 이는 위상 신호가 생성된 코사인 파형과 동일한 주파수로 진행함을 확인시켜 줍니다.

그림 13: Moku 오실로스코프를 사용하여 시각화한 사인 및 코사인 파형. 채널 A(빨간색)는 코사인 신호를, 채널 B(파란색)는 사인 신호를 표시합니다. 주파수 단계는 Control1을 2,374,548,092로, Control2를 6으로 설정하여 구성했습니다.

그림 14: Moku 오실로스코프 입력은 Moku 클라우드 컴파일의 OutputA와 OutputC에 연결됩니다. 파란색 선은 위상 카운터 출력의 최상위 16비트를 나타냅니다.
6. FIR_필터_7계수
FIR_Filter_7coef IP 코어는 고정 계수를 사용하여 최대 클럭 속도로 작동하므로, 다중 계측 모드 설정에서 추가 계측기 없이 Moku 클라우드 컴파일 디자인에 저역 통과 필터를 통합해야 하는 사용자에게 리소스 효율적인 솔루션을 제공합니다. 필터 계수는 표 8에, 포트 정의는 표 9에 나와 있습니다. 조정 가능한 계수가 필요한 애플리케이션의 경우, 사용자는 다음을 사용할 수 있습니다. Moku FIR 필터 빌더 또는 다음 지침에 따라 사용자 지정 FIR 필터 IP 코어를 다시 컴파일합니다. 맞춤형 IP 코어 이 논문의 섹션.
표 8: FIR_Filter_7coef에 사용된 계수.

표 9: FIR_Filter_7coef의 포트 정의.
| 이름 | 방향 | 기술설명 |
| aclk | 입력 | 라이징 에지 클록. |
| s_axis_data_tvalid | 입력 | 입력 데이터 채널에 유효하지 않습니다. 외부 블록에서 데이터를 전송할 수 있음을 나타내기 위해 어서트됩니다. |
| s_축_데이터_트레디 | 산출 | 입력 데이터 채널에 대한 트레디. 코어가 데이터를 수신할 준비가 되었음을 나타내기 위해 코어에 의해 어설션됨. |
| s_축_데이터_t데이터 [15:0] | 입력 | 입력 데이터 채널에 대한 tdata입니다. 필터링할 데이터 스트림을 전달합니다. 내부 구조는 tdata 구조체를 참조하세요. |
| m_axis_data_tvalid | 산출 | 출력 데이터 채널에 유효하지 않습니다. 코어에서 데이터를 전송할 수 있음을 나타내기 위해 어설션됩니다. |
| m_축_데이터_t데이터 [23:0] | 산출 | 출력 데이터 채널의 tdata입니다. 이는 필터링된 데이터 스트림입니다. 내부 구조는 tdata 구조체를 참조하세요. |
FIR_Filter_7coef IP 코어의 VHDL 인스턴스는 코드 6에 제공됩니다. 이 예제에서는 필터가 연속적인 입력 데이터를 처리하고 연속적인 출력 스트림을 생성하도록 설계되었기 때문에 핸드셰이크 신호가 생략되었습니다. 적절한 출력 스케일링을 보장하기 위해 필터 출력의 최상위 16비트는 OutputA로 라우팅됩니다. 이 애플리케이션 노트는 듀얼 박스카 평균기의 구현을 살펴보고, 4개의 싱글 박스카 평균기 그룹으로 구성된 핵심 구조를 설명합니다.
코드 6: FIR_Filter_7coef IP 코어를 인스턴스화하는 VHDL 예제.
LIBRARY ieee;
ARCHITECTURE Behavioural OF CustomWrapper IS
SIGNAL FIR_out_temp : STD_LOGIC_VECTOR(23 DOWNTO 0);
BEGIN
FIR_Filter : FIR_Filter_7coef
PORT MAP(
aclk => clk,
-- input data is always valid
s_axis_data_tvalid => '1',
-- FIR filter ready to accept data
s_axis_data_tready => OPEN,
s_axis_data_tdata => InputA,
-- FIR filtered data is available to be transferred
m_axis_data_tvalid => OPEN,
m_axis_data_tdata => FIR_out_temp
);
OutputA <= signed(FIR_out_temp(23 DOWNTO 8));
END ARCHITECTURE;
FIR_Filter_7coef 다중 계측기 모드 테스트 설정은 그림 15에 나와 있습니다. Moku 주파수 응답 분석기로 측정한 필터 응답은 그림 16에 나와 있습니다. 시뮬레이션된 응답과 측정된 응답을 비교한 내용은 그림 17에 나와 있습니다.

그림 15: FIR_Filter_7coef IP 코어의 다중 계측 모드 구성.

그림 16: Moku 주파수 응답 분석기를 사용하여 얻은 주파수 응답.

그림 17: 주어진 FIR 계수를 기반으로 한 시뮬레이션 응답과 측정된 주파수 응답의 비교.
7. FFT_1024
고속 푸리에 변환(FFT) IP 코어는 이산 푸리에 변환(DFT)을 계산하는 효율적인 기법인 쿨리-튜키 알고리즘을 구현합니다. 이 알고리즘은 대규모 필터링, 교차 상관, 그리고 거친 주파수 분석과 같은 응용 분야에 매우 적합합니다. 표 10은 FFT_1024의 입력 및 출력 정의를 제공합니다. 이 섹션에서는 FFT 코어 구현 예를 보여줍니다.
표 10: FFT_1024 IP 코어의 포트 정의.
| 이름 | 방향 | 기술설명 |
| aclk | 입력 | 라이징 에지 클록. |
| 아레셋 | 입력 | 액티브-로우 동기 클리어(선택 사항, 항상 aclken보다 우선). 최소 2사이클의 액티브 펄스가 필요합니다. |
| s_axis_config_tdata[7:0] | 입력 | 구성 채널용 tdata입니다. CP_LEN, FWD/INV, NFFT 및 SCALE_SCH와 같은 구성 정보를 포함합니다. 최하위 비트(0번째 비트)만 FWD/INV(정방향 또는 역방향 FFT)를 제어하는 데 사용됩니다. 나머지 비트는 비어 있습니다. |
| s_axis_config_tvalid | 입력 | 구성 채널에 유효합니다. 외부 블록에서 데이터를 제공할 수 있음을 알리기 위해 어설션됩니다. |
| s_axis_config_tready | 산출 | 구성 채널에 대한 트레디입니다. 코어가 구성 데이터를 수신할 준비가 되었음을 알리기 위해 어서트됩니다. |
| s_축_데이터_t데이터[31:0] | 입력 | 데이터 입력 채널의 tdata입니다. 처리되지 않은 샘플 데이터를 전달합니다. 실수부는 [15:0]이고 허수부는 [31:16]입니다. |
| s_axis_data_tvalid | 입력 | 데이터 입력 채널에 유효합니다. 외부 블록에서 데이터를 제공할 수 있음을 알리는 데 사용됩니다. 항상 높게 설정할 수 있습니다. |
| s_축_데이터_트레디 | 산출 | 데이터 입력 채널을 위한 트레디. 코어가 데이터를 수신할 준비가 되었음을 알리는 데 사용됩니다. |
| s_축_데이터_최종 | 입력 | 데이터 입력 채널의 tlast입니다. 프레임의 마지막 샘플에서 외부 블록에 의해 어설션됩니다. 이 값은 event_tlast_unexpected 및 event_tlast_missing 이벤트를 생성하는 경우를 제외하고는 코어에서 사용되지 않습니다. |
| m_축_데이터_t데이터[63:0] | 산출 | 데이터 출력 채널의 tdata입니다. 처리된 샘플 데이터를 전달하며, 실수부는 [58:32]이고 허수부는 [26:0]입니다. 신호는 모두 27비트 부호화(소수점 15비트 포함)입니다. |
| m_axis_data_tuser[15:0] | 산출 | 데이터 출력 채널의 tuser입니다. 샘플별 정보의 인덱스를 전달합니다. |
| m_axis_data_tvalid | 산출 | 데이터 출력 채널에 유효합니다. 코어에서 샘플 데이터를 제공할 수 있음을 알리기 위해 사용됩니다. |
| m_축_데이터_트레디 | 입력 | 데이터 출력 채널에 대한 트레디. 외부 슬레이브가 데이터를 수신할 준비가 되었음을 알리기 위해 어서트됩니다. |
| m_축_데이터_최종 | 산출 | 데이터 출력 채널의 마지막 값입니다. 프레임의 마지막 샘플에서 코어에 의해 어설션됩니다. |
| 이벤트 프레임 시작됨 | 산출 | 코어가 새로운 프레임을 처리하기 시작할 때 발생합니다. |
| 이벤트_마지막_예상치 못한 | 산출 | 프레임의 마지막이 아닌 데이터 샘플에서 s_axis_data_tlast가 높음을 코어가 확인할 때 발생합니다. |
| 이벤트 마지막 누락 | 산출 | 프레임의 마지막 데이터 샘플에서 s_axis_data_tlast가 낮을 때 어설션됩니다. |
| 이벤트_상태_채널_중단 | 산출 | 코어가 상태 채널에 데이터를 쓰려고 시도하지만 쓸 수 없는 경우 발생합니다. |
| 채널 중단 이벤트 데이터 | 산출 | 코어가 데이터 입력 채널에서 데이터를 요청했지만 아무것도 사용할 수 없는 경우 발생합니다. |
| 이벤트_데이터_아웃_채널_중단 | 산출 | 코어가 데이터 출력 채널에 데이터를 쓰려고 하지만 쓸 수 없는 경우 발생합니다. |
FFT_1024 IP 코어의 VHDL 인스턴스는 코드 7에 제공됩니다. 입력 신호는 순수 실수이므로 s_axis_data_tdata의 최하위 16비트만 InputA에 연결되고, FFT 출력의 실수 및 허수 성분의 최상위 16비트는 각각 Cordic_Translate_16 모듈의 입력에 연결되어 해당 진폭과 위상을 계산합니다. 이 예제에서는 s_axis_config_tdata의 최하위 비트를 높게 설정하여 FFT를 순방향 푸리에 변환으로 구성합니다. 이벤트 신호는 이 예제에서 사용되지 않으므로 의도적으로 연결하지 않습니다. 각 FFT 프레임의 끝은 m_axis_data_tlast 신호로 표시되며, 이 신호가 발생하면 FFT 코어는 다음 처리 주기를 준비하기 위해 재설정됩니다. Cordic_Translate_16의 20주기 처리 지연 시간을 고려하여 FFT 출력 인덱스(m_axis_data_tuser)는 그에 따라 지연됩니다. 결과적으로 얻어진 진폭, 위상 및 주파수 빈 인덱스는 각각 OutputA, OutputB 및 OutputC로 출력됩니다.
코드 7: FFT_1024 IP 코어와 Cordic_Translate_16 모듈의 인스턴스화를 보여주는 VHDL 예제로, FFT 출력을 해당 진폭 및 위상 값으로 변환하는 데 사용됩니다.
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ARCHITECTURE Behavioural OF CustomWrapper IS
TYPE array_tuser IS ARRAY (0 TO 19) OF signed(15 DOWNTO 0);
SIGNAL aresetn, aresetn_dly : STD_LOGIC;
SIGNAL s_axis_data_tdata : STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL s_axis_data_tready : STD_LOGIC;
SIGNAL m_axis_data_tlast : STD_LOGIC;
SIGNAL m_axis_data_tvalid, m_axis_data_tvalid_dly : STD_LOGIC;
SIGNAL m_axis_data_tuser : signed(15 DOWNTO 0);
SIGNAL m_axis_data_tuser_dly : array_tuser;
SIGNAL m_axis_dout_tvalid : STD_LOGIC;
SIGNAL tdata_temp : signed(31 DOWNTO 0);
SIGNAL im, real : STD_LOGIC_VECTOR(26 DOWNTO 0);
SIGNAL fftdata_temp : STD_LOGIC_VECTOR(63 DOWNTO 0);
BEGIN
FFT_DUT : FFT_1024
PORT MAP(
aclk => clk,
aresetn => (NOT reset) AND aresetn AND aresetn_dly,
-- Forward FFT with the LSB configured as 1
s_axis_config_tdata => x"01",
-- Config data is always valid
s_axis_config_tvalid => '1',
-- Leave config ready signal open
-- config data is constant
s_axis_config_tready => OPEN,
-- Input only has real values
s_axis_data_tdata => s_axis_data_tdata,
-- Input data is always valid
s_axis_data_tvalid => '1',
-- Data ready logic
s_axis_data_tready => s_axis_data_tready,
-- Continuous data stream
-- don't have last sample
s_axis_data_tlast => '0',
-- Transformed data
m_axis_data_tdata => fftdata_temp,
-- FFT frequency index
m_axis_data_tuser => m_axis_data_tuser,
-- output is valid
m_axis_data_tvalid => m_axis_data_tvalid,
-- Slave device is always ready to accept output
m_axis_data_tready => '1',
-- last sample of the frame
m_axis_data_tlast => m_axis_data_tlast,
-- don't care events
event_frame_started => OPEN,
event_tlast_unexpected => OPEN,
event_tlast_missing => OPEN,
event_status_channel_halt => OPEN,
event_data_in_channel_halt => OPEN,
event_data_out_channel_halt => OPEN
);
-- only output data when data is valid
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF s_axis_data_tready THEN
s_axis_data_tdata <= x"0000" & STD_LOGIC_VECTOR(InputA);
END IF;
IF m_axis_data_tvalid THEN
im <= fftdata_temp(58 DOWNTO 32);
real <= fftdata_temp(26 DOWNTO 0);
END IF;
m_axis_data_tuser_dly <= m_axis_data_tuser & m_axis_data_tuser_dly(0 TO 18);
END IF;
END PROCESS;
-- reset process
-- reset fft when the tlast is high
PROCESS (clk)
BEGIN
IF rising_edge(Clk) THEN
aresetn_dly <= aresetn;
IF m_axis_data_tlast THEN
aresetn <= '0';
ELSE
aresetn <= '1'; END IF; END IF; END PROCESS; Cordic : Cordic_Translate_16 PORT MAP( aclk => clk,
s_axis_cartesian_tvalid => m_axis_data_tvalid,
s_axis_cartesian_tdata => STD_LOGIC_VECTOR(im(26 DOWNTO 11) & real(26 DOWNTO 11)),
m_axis_dout_tvalid => m_axis_dout_tvalid,
m_axis_dout_tdata => tdata_temp
);
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF m_axis_dout_tvalid THEN
OutputA <= signed(tdata_temp(15 DOWNTO 0));
OutputB <= signed(tdata_temp(31 DOWNTO 16));
OutputC <= signed(m_axis_data_tuser_dly(19));
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
다중 계측 모드 테스트 구성 및 해당 출력 신호는 그림 18과 그림 19에 나와 있습니다. 그림 18은 FFT_1024 및 Cordic_Translate_16 IP 코어의 진폭 출력 측정 설정을 보여주고, 그림 19는 위상 출력을 캡처하기 위한 구성을 보여줍니다. 그림 18의 진폭 스펙트럼에는 양의 주파수 영역에 하나, 음의 주파수 영역에 다른 하나, 두 개의 피크가 나타납니다. 양의 주파수 피크와 관련된 인덱스는 인덱스 램프 시작 시점을 기준으로 한 타임스탬프에 해당합니다. Moku:Go 클럭이 31.25MHz이고 인덱스 램프의 총 시간 간격이 32.684마이크로초임을 고려하면, 예상 주파수는 다음과 같이 계산됩니다.

\(주파수} = frac{text{10.531 } μ text{s}}{text{32.684 } μ text{s}} × text{31.25 MHz} = text{10.0689 MHz}\) 1024포인트 FFT는 약 0.03 MHz의 해상도 대역폭을 제공한다는 점에 유의해야 합니다. 따라서 이 구현은 대략적인 주파수 추정에만 적합합니다. 보다 정확한 분석을 위해서는 다른 방법을 사용하는 것이 좋습니다. 모쿠 위상계그림 19는 위상 출력을 빨간색으로 표시합니다. FFT 분석 윈도우가 획득 주기 동안 가변적이기 때문에 위상이 불안정하게 나타납니다. 이 예시는 기능 시연을 위한 것이지만, 윈도우 함수 및 슈퍼헤테로다인 블록과 같은 필수 구성 요소가 부족하므로 완전한 스펙트럼 분석기는 아닙니다.

그림 18: FFT_1024 IP 코어에 대한 다중 계측기 모드 테스트 구성 및 진폭 출력 결과. 10MHz 사인파가 Moku 클라우드 컴파일의 입력 A에 입력되고 FFT_1024 모듈에서 처리됩니다. 채널 A(빨간색)에 표시되는 결과 진폭 스펙트럼은 입력 신호의 양(+) 및 음(-) 주파수 성분에 해당하는 두 개의 피크를 나타냅니다.

그림 19: FFT_1024 IP 코어의 다중 계측기 모드 테스트 구성 및 위상 응답. 관찰된 위상 응답은 입력 신호에 대한 FFT 분석 윈도우의 무작위 시간 오프셋으로 인해 불안정해 보입니다.
8. FFT_65536
FFT_65536은 FFT_1024의 변형으로, 동일한 IP 코어 컴파일러를 사용하여 생성되었지만 더 많은 FFT 포인트로 구성됩니다. 두 코어는 동일한 기본 구조를 공유하지만, FFT_65536은 증가된 포인트 수를 수용하기 위해 고유한 구성 매개변수와 출력 데이터 형식을 갖습니다. 자세한 포트 사양 및 업데이트된 신호 연결은 표 11에 제공되며, 변경 사항은 강조 표시되어 있습니다. 하드웨어 리소스 제한으로 인해 FFT_65536 IP 코어는 Moku:Go 또는 Moku:Lab에서 지원되지 않으며 Moku:Pro에 배포해야 합니다.
표 11: FFT_65536 IP 코어의 포트 정의. FFT_1024와 다른 매개변수는 굵게 표시되어 있습니다.
| 이름 | 방향 | 기술설명 |
| aclk | 입력 | 라이징 에지 클록. |
| 아레셋 | 입력 | 액티브-로우 동기 클리어(선택 사항, 항상 aclken보다 우선). 최소 2사이클의 액티브 펄스가 필요합니다. |
| s_axis_config_tdata[39:0] | 입력 | 구성 채널의 tdata입니다. 0번째 비트는 순방향 또는 역방향 FFT를 제어합니다. [32:1]은 출력 스케일입니다. 다른 비트는 비어 있습니다. |
| s_axis_config_tvalid | 입력 | 구성 채널에 유효합니다. |
| s_axis_config_tready | 산출 | 구성 채널에 대한 tracey입니다. |
| s_축_데이터_t데이터[31:0] | 입력 | 데이터 입력 채널의 tdata입니다. 처리되지 않은 샘플 데이터(실수[15:0] 및 허수[31:16])를 전달합니다. |
| s_axis_data_tvalid | 입력 | 데이터 입력 채널에 유효합니다. 상수 높음으로 설정하세요. |
| s_축_데이터_트레디 | 산출 | 데이터 입력 채널을 위한 트레디. 코어가 데이터를 수신할 준비가 되었음을 알리는 데 사용됩니다. |
| s_축_데이터_최종 | 입력 | 데이터 입력 채널의 마지막. 프레임의 마지막 샘플에서 외부 마스터에 의해 어설션됩니다. |
| m_축_데이터_t데이터[31:0] | 산출 | 데이터 출력 채널의 tdata입니다. 처리된 샘플 데이터(실수[15:0] 및 허수[31:16])를 전달합니다. 신호 형식은 16비트 부호화 방식이며, 15비트의 소수점 이하 자릿수를 가집니다. |
| m_axis_data_tuser[15:0] | 산출 | 데이터 출력 채널의 tuser입니다. 샘플별 정보의 인덱스를 전달합니다. |
| m_axis_data_tvalid | 산출 | 데이터 출력 채널에 유효합니다. 코어에서 샘플 데이터를 제공할 수 있음을 알리기 위해 사용됩니다. |
| m_축_데이터_트레디 | 입력 | 데이터 출력 채널에 대한 트레디. 외부 블록이 데이터를 수신할 준비가 되었음을 알리기 위해 어서트됩니다. |
| m_축_데이터_최종 | 산출 | 데이터 출력 채널의 마지막 값입니다. 프레임의 마지막 샘플에서 코어에 의해 어설션됩니다. |
| 이벤트 프레임 시작됨 | 산출 | 코어가 새로운 프레임을 처리하기 시작할 때 발생합니다. |
| 이벤트_마지막_예상치 못한 | 산출 | 프레임의 마지막이 아닌 데이터 샘플에서 s_axis_data_tlast가 높음을 코어가 확인할 때 발생합니다. |
| 이벤트 마지막 누락 | 산출 | 프레임의 마지막 데이터 샘플에서 s_axis_data_tlast가 낮을 때 어설션됩니다. |
| 이벤트_상태_채널_중단 | 산출 | 코어가 상태 채널에 데이터를 쓰려고 시도하지만 쓸 수 없는 경우 발생합니다. |
| 채널 중단 이벤트 데이터 | 산출 | 코어가 데이터 입력 채널에서 데이터를 요청했지만 아무것도 사용할 수 없는 경우 발생합니다. |
| 이벤트_데이터_아웃_채널_중단 | 산출 | 코어가 데이터 출력 채널에 데이터를 쓰려고 하지만 쓸 수 없는 경우 발생합니다. |
FFT_65536과 Cordic_Translate_16 하나를 인스턴스화하는 VHDL 예제는 코드 8에 나와 있습니다. Moku Cloud 컴파일 출력에는 InputA의 진폭 및 위상 스펙트럼과 주파수 인덱스가 포함됩니다. 또한, Control0은 스케일 매개변수를 설정하는 데 사용되고, Control1의 최하위 비트(LSB)는 FFT 방향을 결정합니다.
코드 8: 하나의 FFT_65536과 하나의 Cordic_Translate_16 모듈의 인스턴스화를 보여주는 VHDL 예제입니다.
LIBRARY ieee;
ARCHITECTURE Behavioural OF CustomWrapper IS
TYPE array_tuser IS ARRAY (0 TO 19) OF signed(15 DOWNTO 0);
SIGNAL aresetn, aresetn_dly : STD_LOGIC;
SIGNAL s_axis_data_tdata : STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL s_axis_data_tready : STD_LOGIC;
SIGNAL m_axis_data_tlast : STD_LOGIC;
SIGNAL m_axis_data_tvalid, m_axis_data_tvalid_dly : STD_LOGIC;
SIGNAL count_out, m_axis_data_tuser : signed(15 DOWNTO 0);
SIGNAL m_axis_data_tuser_dly : array_tuser;
SIGNAL fftdata_temp : signed(31 DOWNTO 0);
SIGNAL real, im : signed(15 DOWNTO 0);
SIGNAL m_axis_dout_tvalid : STD_LOGIC;
SIGNAL tdata_temp : signed(31 DOWNTO 0);
BEGIN
FFT_DUT : FFT_65536
PORT MAP(
aclk => clk,
-- aresetn => (not Reset) and FFT_reset and FFT_reset_dly,
aresetn => (NOT reset) AND aresetn AND aresetn_dly,
-- Control FFT direction with LSB of Control1
-- and scale of the FFT output with Control0
s_axis_config_tdata => "0000000" & Control0(31 DOWNTO 0) & Control1(0),
-- Config data is always valid
s_axis_config_tvalid => '1',
-- Leave config ready signal open
-- config data is constant
s_axis_config_tready => OPEN,
-- Input only has real values
s_axis_data_tdata => s_axis_data_tdata,
-- Input data is always valid
s_axis_data_tvalid => '1',
-- Data ready logic
s_axis_data_tready => s_axis_data_tready,
-- Continuous data stream
-- don't have last sample
s_axis_data_tlast => '0',
-- Transformed data
m_axis_data_tdata => fftdata_temp,
-- FFT frequency index
m_axis_data_tuser => m_axis_data_tuser,
-- output is valid
m_axis_data_tvalid => m_axis_data_tvalid,
-- Slave device is always ready to accept output
m_axis_data_tready => '1',
-- last sample of the frame
m_axis_data_tlast => m_axis_data_tlast,
-- don't care events
event_frame_started => OPEN,
event_tlast_unexpected => OPEN,
event_tlast_missing => OPEN,
event_status_channel_halt => OPEN,
event_data_in_channel_halt => OPEN,
event_data_out_channel_halt => OPEN
);
-- only output data when data is valid
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF s_axis_data_tready THEN
s_axis_data_tdata <= x"0000" & STD_LOGIC_VECTOR(InputA);
END IF;
IF m_axis_data_tvalid THEN
-- real part
real <= fftdata_temp(15 DOWNTO 0);
-- imaginary part
im <= fftdata_temp(31 DOWNTO 16);
END IF;
-- delay 20 clk cycles
m_axis_data_tuser_dly <= m_axis_data_tuser & m_axis_data_tuser_dly(0 TO 18);
END IF;
END PROCESS;
-- reset process
-- reset fft when the tlast is high
PROCESS (clk)
BEGIN
IF rising_edge(Clk) THEN
aresetn_dly <= aresetn;
IF m_axis_data_tlast THEN
aresetn <= '0';
ELSE
aresetn <= '1'; END IF; END IF; END PROCESS; Cordic : Cordic_Translate_16 PORT MAP( aclk => clk,
s_axis_cartesian_tvalid => m_axis_data_tvalid,
s_axis_cartesian_tdata => STD_LOGIC_VECTOR(im & real),
m_axis_dout_tvalid => m_axis_dout_tvalid,
m_axis_dout_tdata => tdata_temp
);
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF m_axis_dout_tvalid THEN
OutputA <= signed(tdata_temp(15 DOWNTO 0));
OutputB <= signed(tdata_temp(31 DOWNTO 16));
OutputC <= signed(m_axis_data_tuser_dly(19));
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
Moku:Pro 다중 계측기 모드 테스트 구성은 그림 20에 나와 있습니다. 테스트 대상 신호는 Moku 오실로스코프에 내장된 파형 발생기에서 생성되어 내부 디지털 신호 버스를 통해 Moku Cloud Compile 입력으로 다시 라우팅됩니다. Moku Cloud Compile은 세 개의 출력을 생성합니다. OutputA와 OutputB는 변환된 진폭과 위상을 나타내며, OutputC는 주파수 지수에 해당합니다. 이 출력들은 모니터링을 위해 오실로스코프의 입력에 연결됩니다.

그림 20: Moku:Pro FFT_65536 테스트, 다중 계측 모드 구성. FFT_65536의 출력 진폭 및 주파수 인덱스는 그림 21에 나와 있습니다. Control0은 신호 오버플로를 방지하기 위해 미세 조정되었고, Control1은 순방향 FFT를 수행하기 위해 1로 설정되었습니다. 65,536포인트 FFT에 부호 있는 16비트 표현을 사용했기 때문에 주파수 인덱스의 부호가 반전되는 것처럼 보이며, 이로 인해 오버플로가 발생합니다. 그러나 이 오버플로는 음수와 양수 주파수를 효과적으로 구분하므로 무해합니다. 진폭 채널은 80MHz 주파수 인덱스 근처에서 피크를 보이는데, 이는 Moku:Pro Moku Cloud Compile의 클럭 속도가 312.5MHz일 때 Moku Cloud Compile의 80MHz 입력 신호에 해당합니다.

\(주파수} = frac{53.86 μs}{104.95 μs} × frac{312.5 MHz}}{2} = 80.19 MHz\)

그림 21: 인스턴스화된 FFT_65536과 해당 진폭 스펙트럼 출력의 테스트 결과.
맞춤형 IP 코어
Moku Cloud Compile은 사용자가 Vivado에서 생성된 IP 코어의 구성을 정의하는 사용자 지정 .xci 파일을 업로드할 수 있도록 지원합니다. Moku Cloud Compile은 이러한 .xci 파일을 파싱하고, 해당 IP 코어를 백엔드에 로드하여 사용자 디자인 내에서 인스턴스화할 수 있도록 합니다. Moku Cloud Compile 백엔드와의 호환성을 보장하기 위해 .xci 파일은 Vivado 2022.2 버전을 사용하여 생성해야 합니다. Vivado 2022.2에서 지원하는 모든 IP 코어는 Moku Cloud Compile에서도 지원됩니다. Vivado 2022.2는 다음 링크에서 다운로드할 수 있습니다. AMD 공식 홈페이지다음 섹션에서는 이 과정을 설명하는 예를 제시합니다.
1. Vivado 프로젝트 생성:
프로젝트 생성 과정에서 올바른 하드웨어 플랫폼을 선택하는 것은 필수적입니다. 대상 FPGA 장치는 설정 과정에서 지정해야 합니다. 표 12는 지원되는 세 가지 하드웨어 플랫폼에 대한 FPGA 플랫폼 모델을 나열하고 있으며, 그림 22는 구성 예시를 보여줍니다.
표 12: Moku 플랫폼의 FPGA 모델 번호.
| 플랫폼 | FPGA 모델 |
| Moku:Go | xc7z020clg400-1 |
| Moku:Lab | xc7z020clg484-3 |
| Moku:Pro | xczu9egffvc900-2 |

그림 22: 프로젝트는 적절한 FPGA 플랫폼 설정을 사용하여 Vivado에서 생성해야 합니다. 이 예에서는 Moku:Go 플랫폼을 대상 장치로 선택했습니다.
2. IP 코어를 빌드하고 .xci 파일을 찾습니다.
그림 23에 설명된 단계에 따라 사용자 정의 IP 코어를 컴파일할 수 있습니다. 먼저 다음을 선택합니다. IP 카탈로그 인사말 프로젝트 매니저 왼쪽 패널(1단계)에서 원하는 IP 코어를 선택합니다. 그런 다음 오른쪽 패널(2단계)의 목록에서 원하는 IP 코어를 선택합니다. 구성 과정에서 클록 주파수가 필요할 수 있으며, 플랫폼별 클록 속도는 표 13에 나와 있습니다. IP 코어가 구성되면 지우면 좋을거같음 . SM 창(3단계). 생성된 .xci 파일의 위치는 다음에서 찾을 수 있습니다. 소스 파일 속성 패널(4단계).
표 13: 다양한 하드웨어 플랫폼에 따른 Moku Cloud Compile의 클록 속도.
| 플랫폼 | Moku 클라우드 컴파일 클럭 속도(MHz) |
| Moku:Go | 31.25 |
| Moku:Lab | 125 |
| Moku:Pro | 312.5 |

그림 23: IP 코어를 구성하는 프로세스.
3. .xci 파일을 Moku Cloud에 업로드하고 OUTPUTDIR을 컴파일하고 변경합니다.
IP 코어가 컴파일되면 .xci 파일을 업로드해야 합니다. Moku Cloud Compile 웹 인터페이스. Moku Cloud Compile 백엔드에서 성공적인 재컴파일을 보장하려면 출력 매개변수는 “../output”으로 설정해야 합니다. 이 과정의 예는 그림 24에 나와 있습니다.

그림 24: .xci 파일을 Moku 클라우드 컴파일에 업로드하고 OUTPUTDIR을 "../output"으로 설정하여 올바른 컴파일이 이루어지도록 합니다.
4. Moku Cloud에서 IP 코어 인스턴스화 및 디자인 컴파일 및 빌드
Moku Cloud Compile에서 사용자 지정 IP 코어를 인스턴스화하려면 포트 구성과 신호 연결을 이해하는 것이 필수적입니다. 그림 25는 인스턴스화 템플릿을 찾는 과정을 보여줍니다. 먼저 IP 소스를 선택한 다음, 인스턴스화 예시를 제공하는 .vho 및 .veo 파일을 찾습니다. .vho 파일은 VHDL용이고 .veo 파일은 Verilog용입니다.

그림 25: IP 코어 인스턴스화 템플릿 찾기. 다음으로, 그림 26은 템플릿을 사용하여 사용자 지정 IP 코어를 인스턴스화하는 과정을 보여줍니다. 이로써 설정이 완료되며, 이후 Moku Cloud Compile에서 사용자 지정 IP 코어를 컴파일하고 비트스트림을 생성할 수 있습니다.

그림 26: Moku Cloud에서 IP 코어를 인스턴스화하고 해당 신호를 CustomWrapper 모듈의 해당 포트에 컴파일하고 연결합니다.
Verilog 지원
Verilog는 VHDL과 마찬가지로 하드웨어 설명 언어이지만, 일반적으로 더 간결하고 하드웨어 모델링에 더 가깝습니다. 사용자가 일반적으로 CustomWrapper 엔티티의 동작 아키텍처만 정의하는 VHDL과 달리, Verilog에서는 전체 CustomWrapper 모듈의 선언과 구조적 정의가 모두 필요합니다. 여기에는 CustomWrapper 포트와 내부 로직을 명시적으로 지정하는 것이 포함됩니다. 이 섹션에서는 코드 9에 나와 있는 것처럼 Verilog를 사용하여 AddSubtract_16 IP 코어를 인스턴스화하는 예제를 제공합니다. Verilog는 하드웨어 설명 언어라는 점에 유의해야 합니다. 대소 문자를 구별하는따라서 합성이나 동작상의 오류를 피하기 위해서는 대문자를 정확하게 사용하고 일관된 명칭을 사용하는 것이 필수적입니다.
코드 9: AddSubtract_16 IP 코어에 대한 지원을 보여주는 Verilog 구현 예입니다.
module CustomWrapper (
input wire Clk,
input wire Reset,
input wire [31:0] Sync,
// 4 input ports
input wire signed [15:0] InputA,
input wire signed [15:0] InputB,
input wire signed [15:0] InputC,
input wire signed [15:0] InputD,
// external trigger input port
input wire ExtTrig,
// 4 output ports
output wire signed [15:0] OutputA,
output wire signed [15:0] OutputB,
output wire signed [15:0] OutputC,
output wire signed [15:0] OutputD,
// enable/disable interpolation
output wire OutputInterpA,
output wire OutputInterpB,
output wire OutputInterpC,
output wire OutputInterpD,
// 16 control registers
input wire [31:0] Control0,
input wire [31:0] Control1,
input wire [31:0] Control2,
input wire [31:0] Control3,
input wire [31:0] Control4,
input wire [31:0] Control5,
input wire [31:0] Control6,
input wire [31:0] Control7,
input wire [31:0] Control8,
input wire [31:0] Control9,
input wire [31:0] Control10,
input wire [31:0] Control11,
input wire [31:0] Control12,
input wire [31:0] Control13,
input wire [31:0] Control14,
input wire [31:0] Control15
);
AddSubtract_16 AddSubtract_DUT (
.A(InputA), // input wire [15 : 0] A
.B(InputB), // input wire [15 : 0] B
.CLK(Clk), // input wire CLK
.ADD(Control0[0]), // input wire ADD
.CE(1'b1), // input wire CE
.S(OutputA) // output wire [15 : 0] S
);
endmodule
예제 Verilog 코드를 Moku Cloud Compile에 업로드한 후 AddSubtract_16 모듈을 성공적으로 컴파일하고, 그림 27에서 볼 수 있듯이 해당 비트스트림이 생성됩니다.

그림 27: AddSubtract_16 모듈을 컴파일하고 Verilog 코드에서 비트스트림을 생성하기 위한 Moku Cloud 컴파일 인터페이스.
제품 개요
Moku Cloud Compile은 산술 연산, 필터링, 파형 생성, 스펙트럼 분석과 같은 신호 처리 작업을 위한 8개의 사전 컴파일된 IP 코어를 제공합니다. 각 코어는 위에서 설명한 바와 같이 상세한 포트 정의, VHDL 구현 예제, 그리고 Moku 하드웨어 플랫폼의 다중 계측 모드를 사용한 테스트 구성 정보를 제공합니다. 내장 코어 외에도 사용자는 Vivado 2022.2에서 생성된 .xci 파일을 가져와 사용자 지정 IP 코어를 업로드할 수 있습니다. Moku Cloud Compile은 Verilog와 VHDL을 모두 지원합니다. 이러한 기능들을 통해 Moku Cloud Compile은 FPGA 기반 디지털 신호 처리 솔루션을 신속하게 개발하고 배포할 수 있는 강력하고 유연한 플랫폼으로서의 기능을 향상시킵니다.



