아직 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 사이클로 지연됩니다.
다음은 데이터 흐름을 그래픽으로 보여주는 스케치입니다.
추신 : 내 코드를 자세히 살펴 주셔서 감사합니다. 그래서 나도 무언가를 배웠다! ;-)이 버전이 올바른지 또는 더 이상 문제가 있으면 알려주십시오.