ฉันยังไม่ได้ทำงานกับตัวกรอง IIR แต่ถ้าคุณต้องการคำนวณสมการที่กำหนด
y[n] = y[n-1]*b1 + x[n]
หนึ่งครั้งต่อรอบ CPU คุณสามารถใช้ pipelining
ในรอบเดียวคุณทำการคูณและในรอบเดียวคุณต้องทำการสรุปสำหรับแต่ละตัวอย่างอินพุต นั่นหมายความว่า 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
PS: บางทีโปรแกรมเมอร์ Verilog ที่มีประสบการณ์บางคนสามารถแก้ไขรหัสนี้และลบความคิดเห็นนี้และความคิดเห็นด้านบนรหัสหลังจากนั้น ขอบคุณ!
PPS: ในกรณีที่ปัจจัย "b1" ของคุณเป็นค่าคงที่คงที่คุณอาจสามารถปรับการออกแบบให้เหมาะสมโดยใช้ตัวคูณพิเศษที่รับอินพุตสเกลาร์เดียวเท่านั้นและคำนวณ "คูณ 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
เพื่อให้แน่ใจว่าการทำงานอย่างถูกต้องในครั้งนี้ลองมาดูว่าเกิดอะไรขึ้นในสองสามรอบแรก โปรดทราบว่า 2 รอบแรกจะสร้างขยะมากขึ้นหรือน้อยลงเนื่องจากไม่มีค่าเอาต์พุตก่อนหน้า (เช่น y [-1] == ??) register 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] ล่าช้าโดย lag l = 1 นั่นหมายความว่าข้อมูลที่ส่งออกจะเทียบเท่า แต่ล่าช้าโดย "ดัชนี" หนึ่งรายการ เพื่อให้ชัดเจนยิ่งขึ้น: ข้อมูลขาออกล่าช้าเป็น 2 รอบเนื่องจากจำเป็นต้องใช้วงจรนาฬิกาหนึ่ง (ปกติ) และ 1 นาฬิกาเพิ่มเติม (lag l = 1) จะถูกเพิ่มสำหรับรอบกลาง
นี่คือภาพร่างที่แสดงภาพกราฟิกว่าข้อมูลไหลอย่างไร:
PS: ขอบคุณที่มองรหัสของฉันอย่างใกล้ชิด ดังนั้นฉันจึงเรียนรู้บางอย่างเช่นกัน! ;-) แจ้งให้เราทราบหากรุ่นนี้ถูกต้องหรือหากคุณเห็นปัญหาเพิ่มเติม