필터는 말 그대로 특정 주파수를 거르거나 통과시키는 역할을 한다.
디지털로 구현할 수 있는 필터는 크게 FIR와 IIR 필터로 나뉜다.
아날로그로 구현하는 필터들 (RLC회로)들은 피드백을 가지고 있으며, 임펄스응답은 무한의 길이를 갖는다. 이러한 피드백구조를 갖는 디지털필터를 IIR필터라고 하는데, 이 필터는 차수가 낮기 때문에 회로가 단순해지고 딜레이가 적지만, 위상측면에서 비선형성을 가진다는 것이 단점이다.
오디오, 이미지, 생체정보와 같은 현재 데이터의 보존이 중요한 경우 선형위상을 갖는 FIR필터를 사용하는게 이상적이다.

요약하자면(FIR)
1. 유한한 시간안에 결과가 도출됨
2. 피드백 없음
3. 차수가 깊어질 수도 있음(정확도와 트레이드오프)
4. 항상 안정적
5. 계산량 아주많음
FIR필터가 선형위상을 가지기 위해서 필수적인 조건은 계수의 대칭성이다.
이 계수값을 구하기 위해서 매트랩 filter designer를 사용하여 계수값을 도출하자.

fs = 1khz
뇌파의 주파수를 고려하여 차단주파수를 60hz로 설정.
; FIR filter coefficients generated from MATLAB
radix=10;
coefdata=
17,-11,-19,-32,-50,
-72,-97,-124,-151,-175,
-194,-206,-207,-197,-174,
-137,-87,-28,39,108,
174,231,273,296,293,
263,205,120,13,-110,
-240,-366,-476,-559,-601,
-594,-528,-399,-206,49,
358,711,1092,1485,1870,
2229,2543,2794,2969,3060,
3060,2969,2794,2543,2229,
1870,1485,1092,711,358,
49,-206,-399,-528,-594,
-601,-559,-476,-366,-240,
-110,13,120,205,263,
293,296,273,231,174,
108,39,-28,-87,-137,
-174,-197,-207,-206,-194,
-175,-151,-124,-97,-72,
-50,-32,-19,-11,17;
최종적으로 값이 대칭인 계수값을 가져왔음. (차단주파수 60hz)
C언어 검증
c언어로 먼저 FIR필터를 구현해 보았다.
가중치가 저장되어있는 coef data배열은 고정되어있는 상태로 input 을 슬라이딩하는 방식으로 계산하였다.
이렇게 계산될 경우 곱연산이 누적되어서 절대적인 값이 커지므로 정규화 과정도 넣게 되었다.
#include <stdio.h>
#include <stdlib.h> // for exit()
// 전역 변수로 계수 배열 선언
int coefdata[]={
17,-11,-19,-32,-50,
-72,-97,-124,-151,-175,
-194,-206,-207,-197,-174,
-137,-87,-28,39,108,
174,231,273,296,293,
263,205,120,13,-110,
-240,-366,-476,-559,-601,
-594,-528,-399,-206,49,
358,711,1092,1485,1870,
2229,2543,2794,2969,3060,
3060,2969,2794,2543,2229,
1870,1485,1092,711,358,
49,-206,-399,-528,-594,
-601,-559,-476,-366,-240,
-110,13,120,205,263,
293,296,273,231,174,
108,39,-28,-87,-137,
-174,-197,-207,-206,-194,
-175,-151,-124,-97,-72,
-50,-32,-19,-11,17}; //총 100개의 계수 -> 100차수
double sum_of_coefficients = 0.0;
float filter(float in){
static float x[100];
for(int i = 99; i > 0; i--){ // x[99] = x[98], ..., x[1] = x[0]
x[i] = x[i-1];
}
x[0] = in; // 새로운 입력 값을 x[0]에 저장
double out_raw = 0.0; // 합산 결과가 커질 수 있으므로 double 사용
for(int i = 0; i < 100; i++){ // coefdata가 100개이므로 0부터 99까지 반복
out_raw += (double)x[i] * coefdata[i];
}
// 정규화 적용
float out_scaled;
if (sum_of_coefficients != 0.0) { // 0으로 나누는 것을 방지
out_scaled = (float)(out_raw / sum_of_coefficients);
} else {
out_scaled = 0.0; // 계수 합이 0이면 출력을 0으로 처리
}
return out_scaled;
}
int main(){
for (int i = 0; i < 100; i++) {
sum_of_coefficients += coefdata[i];
}
FILE *inf, *outf;
inf = fopen("filter_in.txt", "r");
outf = fopen("filter_out.txt", "w");
float in;
while(fscanf(inf, "%f", &in) == 1){ // fscanf의 반환 값 확인
float out;
out=filter(in);
fprintf(outf, "%f\n", out);
}
fclose(inf);
fclose(outf);
return 0;
}
테스트 결과를 보자.

matlab에 의해 설계된 필터값은 1khz로 샘플링된 데이터를 차단주파수 60hz로 필터링해내는 것이다.
input 파일로 200hz의 노이즈가 섞인 신호를 입력하게 되었고(파란색 신호) 다음과 같이 노이즈가 섞인 입력값이 주황색으로 필터링되었음을 확인할 수 있었다.

앞서 설명한것과 같이 FIR필터는 선형위상을 가지고 있기 때문에 필터의 계수에 비례하는 딜레이가 존재한다. 따라서 시간도메인에서 보면 딜레이가 생겼음을 확인할 수 있다.
VERILOG 구현
1. 고정소수점 연산
2. ADDER TREE
'프로젝트 > 뇌파측정 프로젝트' 카테고리의 다른 글
| AXI 연동 후 검증 (0) | 2025.07.18 |
|---|---|
| FFT(05.20) (1) | 2025.07.18 |
| FFT (03.25) (1) | 2025.07.18 |