Продолжение этого поста, где был написан модуль вычисления значений синуса и косинуса в заданном угле методом CORDIC.
Сегодняшней задачей будет сравнить получившиеся выходные значения квадратур с идеальными значениями синуса и косинуса, рассчитанными в заданных точках. Я буду приводить данные только для канала Re_out, потому что результаты будут одинаковыми для обоих каналов. Я хочу получить значения Re_out в текстовый файл. Для этого перепишем test bench:
Exported from Notepad++
Создадим два файла, куда запишется один период квадратур. Начнем писать спустя 15 тактов, потому что на этот такт появится первое правильное значение. До этого симулятор покажет на выходе что-то вроде 'XXX', в реальном железе будет скорее всего '0'. Так мы получили текстовый файл с результатами работы модуля cordic_phase.
Для построения графиков я буду пользоваться программой FreeMat, которая является легковесной кроссплатформенной альтернативой матлабу и октаву.
Во-первых загрузим текстовый файл из test bench во FreeMat.
load('re.txt')
Во-вторых посчитаем косинус в тех же точках, что и в test bench:
for n = 1:1:16384
my_re(n) = fix(32767*cos(360*(n-1)*pi/(180*16384)));
end
Видно, что ошибка симметричная и достигает почти 70 в "плохих" углах. Это график абсолютной погрешности. На самом деле видно, что ошибка растет в областях, где косинус проходит 0. Я уже писал, что ошибка там будет расти из-за операции сдвига, вместо деления, когда отрицательное число всегда при сдвиге остается отрицательным.
С относительно погрешностью как-то сложнее. Если построить график для 10000 точек:
for n = 1:1:10000
delta(n) = double(abs(my_re(n)-re(n))/ abs(my_re(n)));
end
Сегодняшней задачей будет сравнить получившиеся выходные значения квадратур с идеальными значениями синуса и косинуса, рассчитанными в заданных точках. Я буду приводить данные только для канала Re_out, потому что результаты будут одинаковыми для обоих каналов. Я хочу получить значения Re_out в текстовый файл. Для этого перепишем test bench:
module cordic_tb;
reg clk;
reg signed [ 14 : 0 ] arg;
wire signed [ 15 : 0 ] Re_out;
wire signed [ 15 : 0 ] Im_out;
localparam N = 12;
cordic_phase u0
(
.clk(clk),
.arg(arg),
.Re_out(Re_out),
.Im_out(Im_out)
);
integer re;
integer im;
initial begin
clk = 0;
arg = 0;
re = $fopen("re.txt", "w");
im = $fopen("im.txt", "w");
while(arg != 16383) begin
arg = arg + 1;
if(arg > N+3)
begin
$fwrite(re, "%d\n", Re_out);
$fwrite(im, "%d\n", Im_out);
end
@(posedge clk);
end
$finish;
$fclose(re);
$fclose(im);
end
always
#10 clk = !clk;
endmodule
Создадим два файла, куда запишется один период квадратур. Начнем писать спустя 15 тактов, потому что на этот такт появится первое правильное значение. До этого симулятор покажет на выходе что-то вроде 'XXX', в реальном железе будет скорее всего '0'. Так мы получили текстовый файл с результатами работы модуля cordic_phase.
Для построения графиков я буду пользоваться программой FreeMat, которая является легковесной кроссплатформенной альтернативой матлабу и октаву.
Во-первых загрузим текстовый файл из test bench во FreeMat.
load('re.txt')
Во-вторых посчитаем косинус в тех же точках, что и в test bench:
for n = 1:1:16384
my_re(n) = fix(32767*cos(360*(n-1)*pi/(180*16384)));
end
Построим оба графика в одной сетке:
plot(my_re)
hold on;
plot(re)
Графики накладываются, но если приблизить масштаб увидим:
Зеленый - CORDIC Verilog
Синий - FreeMat
Видно, что в каких-то точках графики соприкасаются, но потом расходятся. Это недостаток самого метода - мы не можем представить все углы непрерывно потому, что у нас дискретный и конечный (всего 12) набор углов.
Теперь посмотрим на абсолютную ошибку между двумя графиками:
for n = 1:1:16384
delta(n) = my_re(n)-re(n);
end
Тут будут проблемы из-за того, что длина re не 16384, потому что из начала 15 отсчетов выкинули, а в конце не добавили. Так что будем верить результатам в первых 99/100 графика.
С относительно погрешностью как-то сложнее. Если построить график для 10000 точек:
for n = 1:1:10000
delta(n) = double(abs(my_re(n)-re(n))/ abs(my_re(n)));
end
Адский скачок в точка с абсциссой 4097, равный 24. Это точка - угол 90 градусов, где должен был быть ноль. Природа этой проблемы заключается в том, что точное значение угла достигается на 11 шаге, а в 12 вносится искажение. В точках 1..3000 максимальная относительная погрешность составляет 0,24%, В точках 1..4000 - 2,63%. В точках 4000..4090 - 23,89%. Видно, чем ближе к нулю, тем хуже. Апофеоз всего этого действа 124%.
Комментариев нет:
Отправить комментарий