ฉันได้ออกแบบตัวกรอง Butterworth โลว์พาสง่าย ๆ โดยใช้ Matlab ข้อมูลโค้ดต่อไปนี้แสดงให้เห็นถึงสิ่งที่ฉันได้ทำไปแล้ว
fs = 2.1e6;
flow = 44 * 1000;
fNorm = flow / (fs / 2);
[b,a] = butter(10, fNorm, 'low');
ใน [b, a] ถูกจัดเก็บค่าสัมประสิทธิ์ตัวกรอง ฉันต้องการได้รับ [b, a] เป็นจำนวนเต็มเพื่อให้ฉันสามารถใช้เครื่องสร้างรหัสHDL ออนไลน์เพื่อสร้างรหัสใน Verilog
ค่า Matlab [b, a] ดูเหมือนจะเล็กเกินไปที่จะใช้กับเครื่องสร้างรหัสออนไลน์ (สคริปต์ Perl ฝั่งเซิร์ฟเวอร์ปฏิเสธที่จะสร้างรหัสด้วยค่าสัมประสิทธิ์) และฉันสงสัยว่ามันจะเป็นไปได้ที่จะได้รับ [b, a] ในรูปแบบที่สามารถใช้เป็นอินพุตที่เหมาะสม
สัมประสิทธิ์ที่ฉันได้รับใน Matlab คือ:
1.0000
-9.1585
37.7780
-92.4225
148.5066
-163.7596
125.5009
-66.0030
22.7969
-4.6694
0.4307
สัมประสิทธิ์ b ที่ฉันได้ใน Matlab คือ:
1.0167e-012
1.0167e-011
4.5752e-011
1.2201e-010
2.1351e-010
2.5621e-010
2.1351e-010
1.2201e-010
4.5752e-011
1.0167e-011
1.0167e-012
เมื่อใช้ตัวสร้างออนไลน์ฉันต้องการออกแบบตัวกรองที่มีบิตด์วิดท์ 12 บิตและตัวกรอง I หรือ II ฉันไม่รู้ว่า "เศษส่วน" มีความหมายอย่างไรที่ลิงค์ด้านบน
เรียกใช้ตัวสร้างโค้ด (http://www.spiral.net/hardware/filter.html) ด้วยค่าสัมประสิทธิ์ [b, a] ข้างต้นด้วยเศษบิตที่ตั้งไว้ที่ 20 และบิตที่ 12 ฉันได้รับข้อผิดพลาดในการทำงานต่อไปนี้ :
Integer A constants: 1048576 -9603383 39613104 -96912015 155720456 -171714386 131597231 -69209161 23904282 -4896220 451621
Integer B constants: 0 0 0 0 0 0 0 0 0 0 0
Error: constants wider than 26 bits are not allowed, offending constant = -69209161, effective bitwidth = 7 mantissa + 20 fractional = 27 total.
An error has occurred - please revise the input parameters.
ฉันจะเปลี่ยนการออกแบบเพื่อไม่ให้เกิดข้อผิดพลาดนี้ได้อย่างไร
UPDATE: การใช้ Matlab เพื่อสร้างตัวกรอง Butterworth ลำดับที่ 6 ฉันได้รับค่าสัมประสิทธิ์ดังต่อไปนี้:
สำหรับ:
1.0000
-5.4914
12.5848
-15.4051
10.6225
-3.9118
0.6010
สำหรับ b:
0.0064e-005
0.0382e-005
0.0954e-005
0.1272e-005
0.0954e-005
0.0382e-005
0.0064e-005
ใช้ตัวสร้างรหัสออนไลน์ (http://www.spiral.net/hardware/filter.html) ตอนนี้ฉันได้รับข้อผิดพลาดดังต่อไปนี้ (ที่มีเศษส่วนเป็น 8 และบิตที่ 20):
./iirGen.pl -A 256 '-1405' '3221' '-3943' '2719' '-1001' '153' -B '0' '0' '0' '0' '0' '0' '0' -moduleName acm_filter -fractionalBits 8 -bitWidth 20 -inData inData -inReg -outReg -outData outData -clk clk -reset reset -reset_edge negedge -filterForm 1 -debug -outFile ../outputs/filter_1330617505.v 2>&1
At least 1 non-zero-valued constant is required. Please check the inputs and try again.
บางที b-coefficients นั้นเล็กเกินไปหรือบางทีตัวสร้างโค้ด (http://www.spiral.net/hardware/filter.html) ต้องการ [b, a] ในรูปแบบอื่นหรือไม่?
UPDATE:
บางทีสิ่งที่ฉันต้องทำคือปรับสเกลสัมประสิทธิ์ [b, a] ด้วยจำนวนของเศษส่วนเศษส่วนเพื่อให้ได้สัมประสิทธิ์เป็นจำนวนเต็ม
a .* 2^12
b .* 2^12
อย่างไรก็ตามฉันยังคิดว่าสัมประสิทธิ์ b มีขนาดเล็กมาก ฉันทำอะไรผิดที่นี่
บางทีตัวกรองประเภทอื่น (หรือวิธีการออกแบบตัวกรอง) จะเหมาะสมกว่าหรือไม่ ใครช่วยแนะนำได้บ้าง
อัพเดท: ตามคำแนะนำของ Jason R และ Christopher Felton ในความคิดเห็นด้านล่างตัวกรองสัญญาณขอความช่วยเหลือจะเหมาะสมกว่า ตอนนี้ฉันได้เขียนโค้ด Matlab เพื่อรับตัวกรองสัญญาณขอความช่วยเหลือ
fs = 2.1e6;
flow = 44 * 1000;
fNorm = flow / (fs / 2);
[A,B,C,D] = butter(10, fNorm, 'low');
[sos,g] = ss2sos(A,B,C,D);
เมทริกซ์ SOS ที่ฉันได้รับคือ:
1.0000 3.4724 3.1253 1.0000 -1.7551 0.7705
1.0000 2.5057 1.9919 1.0000 -1.7751 0.7906
1.0000 1.6873 1.0267 1.0000 -1.8143 0.8301
1.0000 1.2550 0.5137 1.0000 -1.8712 0.8875
1.0000 1.0795 0.3046 1.0000 -1.9428 0.9598
เป็นไปได้ไหมที่จะใช้เครื่องมือสร้างรหัส Verilog (http://www.spiral.net/hardware/filter.html) เพื่อใช้ตัวกรองสัญญาณขอความช่วยเหลือ SOS นี้หรือฉันควรเขียน Verilog ด้วยมือหรือไม่ มีการอ้างอิงที่ดีอยู่หรือไม่?
ฉันสงสัยว่าตัวกรอง FIR จะดีกว่าที่จะใช้ในสถานการณ์นี้หรือไม่
MOREOVER:ตัวกรอง IIR แบบเรียกซ้ำสามารถใช้งานได้โดยใช้เลขจำนวนเต็มโดยแสดงค่าสัมประสิทธิ์เป็นเศษส่วน (ดูสมุดประมวลผลสัญญาณ DSP ที่ยอดเยี่ยมของ Smith สำหรับรายละเอียดเพิ่มเติม: http://www.dspguide.com/ch19/5.htm )
โปรแกรม Matlab ต่อไปนี้แปลงค่าสัมประสิทธิ์บัตเตอร์เวิร์ ธ เป็นส่วนที่เป็นเศษส่วนโดยใช้ฟังก์ชัน Matlab rat () จากนั้นตามที่กล่าวไว้ในความคิดเห็นส่วนลำดับที่สองสามารถใช้ในการใช้ตัวกรองเป็นตัวเลข (http://en.wikipedia.org/wiki/Digital_biquad_filter)
% variables
% variables
fs = 2.1e6; % sampling frequency
flow = 44 * 1000; % lowpass filter
% pre-calculations
fNorm = flow / (fs / 2); % normalized freq for lowpass filter
% uncomment this to look at the coefficients in fvtool
% compute [b,a] coefficients
% [b,a] = butter(7, fNorm, 'low');
% fvtool(b,a)
% compute SOS coefficients (7th order filter)
[z,p,k] = butter(7, fNorm, 'low');
% NOTE that we might have to scale things to make sure
% that everything works out well (see zp2sos help for 'up' and 'inf' options)
sos = zp2sos(z,p,k, 'up', 'inf');
[n,d] = rat(sos);
sos_check = n ./ d; % this should be the same as SOS matrix
% by here, n is the numerator and d is the denominator coefficients
% as an example, write the the coefficients into a C code header file
% for prototyping the implementation
% write the numerator and denominator matices into a file
[rownum, colnum] = size(n); % d should be the same
sections = rownum; % the number of sections is the same as the number of rows
fid = fopen('IIR_coeff.h', 'w');
fprintf(fid, '#ifndef IIR_COEFF_H\n');
fprintf(fid, '#define IIR_COEFF_H\n\n\n');
for i = 1:rownum
for j = 1:colnum
if(j <= 3) % b coefficients
bn = ['b' num2str(j-1) num2str(i) 'n' ' = ' num2str(n(i,j))];
bd = ['b' num2str(j-1) num2str(i) 'd' ' = ' num2str(d(i,j))];
fprintf(fid, 'const int32_t %s;\n', bn);
fprintf(fid, 'const int32_t %s;\n', bd);
end
if(j >= 5) % a coefficients
if(j == 5)
colstr = '1';
end
if(j == 6)
colstr = '2';
end
an = ['a' colstr num2str(i) 'n' ' = ' num2str(n(i,j))];
ad = ['a' colstr num2str(i) 'd' ' = ' num2str(d(i,j))];
fprintf(fid, 'const int32_t %s;\n', an);
fprintf(fid, 'const int32_t %s;\n', ad);
end
end
end
% write the end of the file
fprintf(fid, '\n\n\n#endif');
fclose(fid);