샘플 주파수에서 클럭킹되는 FPGA에서 IIR 필터를 생성 할 수 있습니까?


9

이 질문은 매우 구체적인 기준을 가진 DSP 슬라이스가있는 FPGA에서 IIR 필터를 구현하는 것에 관한 것입니다.

이 방정식을 사용하여 정방향 탭이없고 역방향 탭이 하나만있는 필터를 작성한다고 가정 해 보겠습니다.

y[n]=y[n1]b1+x[n]

(이미지 참조)

Xilinx의 DSP48A1 슬라이스를 예로 들어 보면, 대부분의 하드 IP DSP 슬라이스는 비슷합니다.

클럭 당 1 개의 샘플로 아날로그 데이터를 수신한다고 가정 해 봅시다. 샘플 클럭에서 동기식으로 실행되는 IIR 필터를 설계하고 싶습니다.

문제는 최대 속도로 DSP 슬라이스를 실행하기 위해 동일한 사이클에 곱하고 추가 할 수 없다는 것입니다. 이러한 구성 요소 사이에 파이프 라인 레지스터가 있어야합니다.

따라서 매 클럭마다 새로운 샘플이 1 개 있으면 클럭 당 1 개의 출력을 생성해야합니다. 그러나이 디자인에서 새로운 출력을 생성하려면 이전 출력 2 클럭이 필요합니다.

확실한 해결책은 데이터를 이중 클럭 속도로 처리하거나 파이프 라인 레지스터를 비활성화하여 동일한주기에 곱하고 추가 할 수 있도록하는 것입니다.

불행히도, 완전히 파이프 라인 된 DSP 슬라이스의 최대 클럭 속도로 샘플링한다고해서 이러한 솔루션 중 어느 것도 가능하지 않습니다. 이것을 구축하는 다른 방법이 있습니까?

(DSP 슬라이스를 사용하여 샘플 속도의 절반으로 작동하는 IIR 필터를 설계 할 수있는 경우 보너스 포인트)

Xilinx Artix FPGA에서 1 GSPS ADC에 대한 보상 필터를 실행하는 것이 목표입니다. 그들의 DSP 슬라이스는 완전히 파이프 라인 될 때 ​​500MHz 이상을 실행할 수 있습니다. 클럭 당 1 샘플에 대한 솔루션이 있다면 클럭 당 2 샘플에 대한 솔루션을 스케일하고 싶습니다. 이것은 FIR 필터를 사용하면 매우 쉽습니다.

단일 피드백 IIR 필터 예


1
명확히하기 위해 파이프 라인 방법을 사용하여 클록 사이클 당 하나의 출력이없는 이유는 없습니다. 대기 시간을 두 개가 아닌 하나의 클럭 사이클로 최소화하려고합니까? 상황에 따라 b1에 정수를 사용하는 경우 x [n]을 포함하여 거대한 추가로 곱할 수 있습니다.
horta

오른쪽-클럭 당 하나의 입력이 있으므로 클럭 당 하나의 출력이 필요합니다. 대기 시간도 문제가되지 않습니다. DSP 슬라이스에는 2 개의 입력 가산기가 있으며 탭은 일반적으로 매우 큰 숫자이므로 1 클럭주기에서 b1 번을 추가 할 수 없습니다. 주된 한계는 출력을 1 클럭으로 피드백해야하지만 2 클럭을 생성하는 것입니다.
Marcus10110

1
파이프 라인의 작동 방식을 여전히 이해하고 있다고 생각합니다. 파이프 라인은 잠재적으로 대기 시간을 증가 시키지만 각 클록 사이클에서 각 입력에 대해 1 개의 출력을 얻을 수 있습니다. 결과는 이상적인 1 클럭이 아니라 2 클럭입니다. 입력은 x [0], x [1], x [2], x [3], x [4]와 같은 순서가되지만 출력은 같은 시간 간격 y [-2], y가됩니다. [-1], y [0], y [1], y [2]. 샘플이 손실되지 않습니다. 또한 FPGA를 사용하고 있기 때문에 DSP 파이프 라인이 설계 한 것보다 더 많은 작업을 수행하려면 fpga를 사용하여 워크로드를 병렬화하십시오.
horta

이 DSP는 사이클에서 융합 된 곱셈 누적을 수행 할 수 있습니다. DSP 슬라이스의 출력을 단일 사이클에서 피드백으로 자체 입력에 연결할 수 있는지는 확실하지 않습니다.
jbarlow

horta-일반적으로 파이프 라이닝에 대해서는 맞지만 문제는이 경우 탭 b1에 피드백이 있다는 것입니다. 즉 파이프 라인의 단계는 이전 값의 출력에 달려 있습니다. 이전 출력에서 ​​다음 출력을 생성하는 데 항상 2 개의 클럭이 필요한 경우 추가 한 대기 시간에 관계없이 클럭 당 1 개의 출력을 생성 할 수있는 방법이 없습니다. jbarlow-맞습니다. DSP 슬라이스에는 1 사이클 융합 옵션이 있습니다. 그러나이 경우에는 충분히 빨리 실행할 수 없습니다. M 레지스터를 추가하면 (데이터 시트 참조) 500MHz에 도달 할 수 있지만 동일한 클럭에 곱할 수 없습니다.
Marcus10110

답변:


3

아직 IIR 필터를 사용하지 않았지만 주어진 방정식 만 계산하면

y[n] = y[n-1]*b1 + x[n]

CPU주기마다 한 번씩 파이프 라이닝을 사용할 수 있습니다.

한 사이클에서는 곱셈을 수행하고 한 사이클에서는 각 입력 샘플에 대한 합산을 수행해야합니다. 즉, 주어진 샘플 속도로 클럭킹 할 때 FPGA가 한 번의 주기로 곱셈을 수행 할 수 있어야합니다! 그런 다음 현재 샘플의 곱셈과 마지막 샘플의 곱셈 결과의 합산 만 수행하면됩니다. 이것은 2주기의 일정한 처리 지연을 야기합니다.

좋아, 공식을보고 파이프 라인을 디자인 해 봅시다.

y[n] = y[n-1]*b1 + x[n]

파이프 라인 코드는 다음과 같습니다.

output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input

세 명령 모두 병렬로 실행되어야하므로 두 번째 라인의 "출력"은 마지막 클럭 사이클의 출력을 사용합니다!

Verilog에서 많은 작업을하지 않았으므로이 코드의 구문이 잘못되었을 가능성이 높습니다 (예 : 입력 / 출력 신호의 비트 폭 누락, 곱셈을위한 실행 구문). 그러나 아이디어를 얻어야합니다.

module IIRFilter( clk, reset, x, b, y );
  input clk, reset, x, b;
  output y;

  reg y, t, t2;
  wire clk, reset, x, b;

  always @ (posedge clk or posedge reset)
  if (reset) begin
    y <= 0;
    t <= 0;
    t2 <= 0;
  end else begin
    y <= t + t2;
    t <= mult(y, b);
    t2 <= x
  end

endmodule

추신 : 어쩌면 일부 숙련 된 Verilog 프로그래머가이 코드를 편집하고이 주석과 코드 위의 주석을 나중에 제거 할 수 있습니다. 감사!

PPS : 요인 "b1"이 고정 상수 인 경우 하나의 스칼라 입력 만 받고 "times b1"만 계산하는 특수 승수를 구현하여 설계를 최적화 할 수 있습니다.

"불행히도 이것은 실제로 y [n] = y [n-2] * b1 + x [n]과 같습니다. 이것은 추가 파이프 라인 단계 때문입니다." 이전 버전의 답변에 대한 의견으로

예, 실제로 다음 구 버전 (INCORRECT !!!)에 적합했습니다.

  always @ (posedge clk or posedge reset)
  if (reset) begin
    t <= 0;
  end else begin
    y <= t + x;
    t <= mult(y, b);
  end

두 번째 레지스터에서도 입력 값을 지연 시켜이 버그를 수정했습니다.

  always @ (posedge clk or posedge reset)
  if (reset) begin
    y <= 0;
    t <= 0;
    t2 <= 0;
  end else begin
    y <= t + t2;
    t <= mult(y, b);
    t2 <= x
  end

이번에 제대로 작동하는지 확인하기 위해 처음 몇주기에서 어떤 일이 발생하는지 봅시다. 이전 출력 값 (예 : y [-1] == ??)을 사용할 수 없으므로 처음 2주기는 다소 (정의 된) 가비지를 생성합니다. 레지스터 y는 0으로 초기화되며 이는 y [-1] == 0이라고 가정하는 것과 같습니다.

첫 번째 사이클 (n = 0) :

BEFORE: INPUT (x=x[0], b); REGISTERS (t=0, t2=0, y=0)

y <= t + t2;      == 0
t <= mult(y, b);  == y[-1] * b  = 0
t2 <= x           == x[0]

AFTERWARDS: REGISTERS (t=0, t2=x[0], y=0), OUTPUT: y[0]=0

두 번째주기 (n = 1) :

BEFORE: INPUT (x=x[1], b); REGISTERS (t=0, t2=x[0], y=y[0])

y <= t + t2;      ==     0  +  x[0]
t <= mult(y, b);  ==  y[0]  *  b
t2 <= x           ==  x[1]

AFTERWARDS: REGISTERS (t=y[0]*b, t2=x[1], y=x[0]), OUTPUT: y[1]=x[0]

세 번째주기 (n = 2) :

BEFORE: INPUT (x=x[2], b); REGISTERS (t=y[0]*b, t2=x[1], y=y[1])

y <= t + t2;      ==  y[0]*b +  x[1]
t <= mult(y, b);  ==  y[1]   *  b
t2 <= x           ==  x[2]

AFTERWARDS: REGISTERS (t=y[1]*b, t2=x[2], y=y[0]*b+x[1]), OUTPUT: y[2]=y[0]*b+x[1]

네 번째 사이클 (n = 3) :

BEFORE: INPUT (x=x[3], b); REGISTERS (t=y[1]*b, t2=x[2], y=y[2])

y <= t + t2;      ==  y[1]*b +  x[2]
t <= mult(y, b);  ==  y[2]   *  b
t2 <= x           ==  x[3]

AFTERWARDS: REGISTERS (t=y[2]*b, t2=x[3], y=y[1]*b+x[2]), OUTPUT: y[3]=y[1]*b+x[2]

cylce n = 2로 시작하면 다음과 같은 결과가 나타납니다.

y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]

어느 것이

y[n]=y[n-2]*b + x[n-1]
y[n]=y[n-1-l]*b1 + x[n-l],  where l = 1
y[n+l]=y[n-1]*b1 + x[n],  where l = 1

위에서 언급했듯이 l = 1주기의 추가 지연을 소개합니다. 이는 출력 y [n]이 지연 l = 1만큼 지연됨을 의미합니다. 즉, 출력 데이터는 동일하지만 하나의 "인덱스"만큼 지연됩니다. 보다 명확하게하기 위해 : 출력 데이터는 1 사이클 (일반) 클록 사이클이 필요하고 중간 스테이지에 대해 1 클록 (래그 l = 1)이 추가되므로 2 사이클로 지연됩니다.

다음은 데이터 흐름을 그래픽으로 보여주는 스케치입니다.

데이터 흐름 스케치

추신 : 내 코드를 자세히 살펴 주셔서 감사합니다. 그래서 나도 무언가를 배웠다! ;-)이 버전이 올바른지 또는 더 이상 문제가 있으면 알려주십시오.


잘 했어! 불행하게도, y [n] = y [n-2] * b + x [n-1]은 실제로는 기능적으로 y [n] = y [n-1] * b + x [n]과 대기 시간이 동일하지 않습니다. IIR 전달 함수의 형태는 실제로 다음과 같습니다 : y [n] = x [n] * b0 + x [n-1] * b1-y [n-1] * a1-y [n-2] * a2 등등. 양식은 b0과 a1을 0으로 설정하고 대신 b1과 a2를 사용합니다. 그러나이 변환은 실제로 매우 다른 필터를 생성합니다. 그러나 첫 번째 분모 (a1)를 0으로 설정하여 필터를 계산하는 방법이 있다면 두 솔루션 모두 완벽하게 작동합니다.
Marcus10110

"지연된 지연"문제를 올바르게 이해해야합니다. 예를 들어, "데이터 스트림 처리"필터는 y [n] = x [n-1]을 출력으로 생성하면 y [n] = x [n]이 올바르게 작동하므로 입력을 전달해야합니다. 출력은 1 사이클 만 지연됩니다 (예 : 출력 인덱스는 모든 입력 인덱스에 대해 고정 된 값으로 오프셋됩니다)! 이 예에서 이것은 함수가 y[n+l] = y[n-1] * b + x[n]지연에 대해 고정 된 값 ly[n] = y[n-1-l] * b + x[n-l]가지며 다시 쓸 수 있음을 의미 하며 l = 1의 경우 이것은입니다 y[n] = y[n-2] * b + x[n-1].
SDwarfs

보다 복잡한 IIR 필터의 경우 동일한 작업을 수행해야합니다 : y[n+l] = x[n] * b0 + x[n-1] * b1 - y[n-1] * a1 - y[n-2] * a2=> y[n] = x[n-l]*b0 + x[n-1-l] * b1 - y[n-1-l] * a1 - y[n-2-l]*a2. 세 번의 곱셈을 모두 병렬로 수행 할 수 있고 (1 단계 / 1주기) 제품을 함께 추가해야한다고 가정하면 2주기 (1주기 : 처음 두 개의 제품 결과 추가 / 서브, 1주기 : 추가 / 서브가 필요함) 이 두 개의 추가 / 하위 결과에 따라 두 번의 추가주기가 필요합니다. 그래서 l = (3-1) = 2주는 y[n]=x[n-2]*b0+x[n-1-2]*b1-y[n-1-2]*a1-y[n-2-2]*a2=>y[n]=x[n-2]*b0+x[n-3]*b1-y[n-3]*a1-y[n-4]*a2
SDwarfs

물론 이것이 작동하려면 FPGA가 4 개의 곱셈과 3 개의 덧셈 / 뺄셈과 병렬로 수행 할 수 있어야합니다. 즉, 4 개의 승수와 3 개의 가산기에 대한 리소스가 필요합니다.
SDwarfs

0

예, 샘플 주파수에서 클럭 할 수 있습니다.

이 문제에 대한 해결책은 원하는 출력 순서를 유지하면서 파이프 라인 레지스터를 삽입 할 수 있도록 원래 식을 조작하는 것입니다.

주어진 : y [n] = y [n-1] * b1 + x [n];

이것은 y [n] = y [n-2] * b1 * b1 + x [n-1] * b1 + x [n]으로 조작 할 수 있습니다.

이것이 동일한 순서인지 확인하기 위해 처음 x [0], x [1], x [2] 등에서 발생하는 것을 고려하십시오. 여기서 x [0] 이전의 모든 x, y 샘플은 0입니다.

원래 표현의 순서는 다음과 같습니다.

y = x[0],

x[1] +x[0]*b1,

x[2] +x[1]*b1 +x[0]*b1*b1,

x[3] +x[2]*b1 +x[1]*b1*b1 +x[0]*b1*b1*b1, ...

b1 <1이 필요하다는 것이 분명합니다. 그렇지 않으면 제한없이 커질 것입니다.

이제 조작 된 표현을 고려하십시오.

y = x[0],

x[0]*b1 +x[1],

x[0]*b1*b1 +x[1]*b1 +x[2],

x[0]*b1*b1*b1 +x[1]*b1*b1 +x[2]*b1 +x[3], ...

이것은 같은 순서입니다.

Xilinx 라이브러리 프리미티브의 하드웨어 솔루션은 캐스케이드로 두 개의 DSP48E가 필요합니다. 아래 포트 및 레지스터 이름은 UG193 v3.6의 그림 1-1을 참조하십시오. 첫 번째 기본 요소는 b1을 곱하고 나중에 한 클럭을 더하는 것입니다. 두 번째는 b1 * b1을 곱하고 나중에 한 시계를 더하는 것입니다. 이 로직에는 4 클럭 파이프 라인 대기 시간이 있습니다.

-DSP48E # 1

a_port1 : = b1; -상수 계수, 세트 AREG = 1

b_port1 : = x; -속성 BREG = 1 설정

c_port1 : = x; -CREG = 1로 설정

-DSP48E # 1의 내부

reg_a1 <= a_port1;

reg_b1 <= b_port1;

reg_c1 ​​<= c_port1;

reg_m1 <= reg_a1 * reg_b1;

reg_p1 <= reg_m1 + reg_c1; -첫 번째 DSP48E의 출력

-DSP48E # 1의 끝

-DSP48E # 2

a_port2 : = reg_p2; -속성 AREG = 0 설정

                -- this means the output of register reg_p2

                -- directly feeds back to the multiplier

b_port2 : = b1 * b1; -상수, BREG = 1 설정

c_port2 : = reg_p1; -CREG = 1로 설정

-DSP48E # 2의 내부

reg_b2 <= b_port2;

reg_c2 <= c_port2;

reg_m2 <= a_port2 * reg_b2;

reg_p2 <= reg_m2 + reg_c2;

-DSP48E # 2의 끝

reg_p1의 순서 :

x [0],

x [1] + x [0] * b1,

x [2] + x [1] * b1,

x [3] + x [2] * b1,

기타

reg_p2의 순서는 원하는 결과입니다. 두 번째 DSP48E 내부에서 레지스터 reg_m2는 다음과 같은 시퀀스를 갖습니다.

x [0] * b1 * b1,

x [1] * b1 * b1 + x [0] * b1 * b1 * b1,

x [2] * b1 * b1 + x [1] * b1 * b1 * b1 + x [0] * b1 * b1 * b1 * b1

이 결과에는 좋은 우아함이 있습니다. 분명히 DSP48E는 곱하기와 같은 클럭에 추가하지는 않지만 차이 방정식에 필요한 것입니다. 조작 된 차이 방정식을 통해 DSP48E의 M 및 P 레지스터를 허용하고 최대 속도로 클럭 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.