Halfback 0 Posted November 11, 2021 (edited) · Report post Всем доброго времени суток! Реализовал полифазный децимирующий фильтр на 70 точек (на выходе каждая 10-я точка относительно входа), в моделсиме показывает всё как надо, в железе на столе тоже работает, но квартус валит слэки по Setup (Slow 1200mV 0C и +85С, по Fast - слэков нет). Причем в sdc когда ставлю 80МГц - слэков нет, на 100МГц еже есть. Буду очень признателен если поможете найти плохое место в коде. Может есть возможность что-то поправить/улучшить? Скрытый текст module PoliPhaseFilter_70 ( input clk, input signed [15:0] datain, input nreset, output signed [15:0] dataout, output clkDec // выходной клок синхр. данных ); localparam BANK_NUM = 10; localparam VALUE_NUM = 7; //регистры с входными данные reg signed [15:0] BANK_D0[BANK_NUM-1:0]; reg signed [15:0] BANK_D1[BANK_NUM-1:0]; reg signed [15:0] BANK_D2[BANK_NUM-1:0]; reg signed [15:0] BANK_D3[BANK_NUM-1:0]; reg signed [15:0] BANK_D4[BANK_NUM-1:0]; reg signed [15:0] BANK_D5[BANK_NUM-1:0]; reg signed [15:0] BANK_D6[BANK_NUM-1:0]; reg signed [15:0] BANK_C [BANK_NUM-1:0][VALUE_NUM-1:0]; //коэффициенты полифазного фильтра reg signed [31+3+4:0] RESSUMM = 0; // промежуточная сумма reg signed [31+3+4:0] RESSUMM_out = 0; // итоговая сумма -> на выход фильтра reg rclkDec = 0; integer i; reg [3:0] step=0; // 10 шагов //результаты перемножений значений данных на коэфф фильтра wire signed [15:0] mult0_1, mult0_2, mult1_1, mult1_2, mult2_1, mult2_2, mult3_1, mult3_2, mult4_1,mult4_2,mult5_1,mult5_2,mult6_1,mult6_2; //сумма результатов перемножений wire signed [31+3:0] resmult1; assign resmult1 = mult0_1*mult0_2 + mult1_1*mult1_2 + mult2_1*mult2_2 + mult3_1*mult3_2 + mult4_1*mult4_2 + mult5_1*mult5_2 + mult6_1*mult6_2; initial begin //обнуление всех регистров, формирование коэффициентов for(i = 0; i < BANK_NUM; i=i+1) begin BANK_D0[i]<=0; BANK_D1[i]<=0; BANK_D2[i]<=0; BANK_D3[i]<=0; BANK_D4[i]<=0; BANK_D5[i]<=0; BANK_D6[i]<=0; end RESSUMM <= 0; RESSUMM_out <= 0; BANK_C[0][0]= -16'd293; BANK_C[0][1]= -16'd1513;BANK_C[0][2] = 16'd3442; BANK_C[0][3] = 16'd16735;BANK_C[0][4] = 16'd15664;BANK_C[0][5] = 16'd2358; BANK_C[0][6] = -16'd1445; BANK_C[1][0]= -16'd278; BANK_C[1][1]= -16'd1518;BANK_C[1][2] = 16'd4646; BANK_C[1][3] = 16'd17631;BANK_C[1][4] = 16'd14446;BANK_C[1][5] = 16'd1407; BANK_C[1][6] = -16'd1331; BANK_C[2][0]= -16'd396; BANK_C[2][1]= -16'd1446;BANK_C[2][2] = 16'd5952; BANK_C[2][3] = 16'd18326;BANK_C[2][4] = 16'd13114;BANK_C[2][5] = 16'd596; BANK_C[2][6] = -16'd1185; BANK_C[3][0]= -16'd534; BANK_C[3][1]= -16'd1279;BANK_C[3][2] = 16'd7340; BANK_C[3][3] = 16'd18800;BANK_C[3][4] = 16'd11702;BANK_C[3][5] = -16'd74; BANK_C[3][6] = -16'd1022; BANK_C[4][0]= -16'd688; BANK_C[4][1]= -16'd1003;BANK_C[4][2] = 16'd8781; BANK_C[4][3] = 16'd19041;BANK_C[4][4] = 16'd10247;BANK_C[4][5] = -16'd604; BANK_C[4][6] = -16'd854; BANK_C[5][0]= -16'd854; BANK_C[5][1]= -16'd604; BANK_C[5][2] = 16'd10247;BANK_C[5][3] = 16'd19041;BANK_C[5][4] = 16'd8781; BANK_C[5][5] = -16'd1003;BANK_C[5][6] = -16'd688; BANK_C[6][0]= -16'd1022;BANK_C[6][1]= -16'd74; BANK_C[6][2] = 16'd11702;BANK_C[6][3] = 16'd18800;BANK_C[6][4] = 16'd7340; BANK_C[6][5] = -16'd1279;BANK_C[6][6] = -16'd534; BANK_C[7][0]= -16'd1185;BANK_C[7][1]= 16'd596; BANK_C[7][2] = 16'd13114;BANK_C[7][3] = 16'd18326;BANK_C[7][4] = 16'd5952; BANK_C[7][5] = -16'd1446;BANK_C[7][6] = -16'd396; BANK_C[8][0]= -16'd1331;BANK_C[8][1]= 16'd1407; BANK_C[8][2] = 16'd14446;BANK_C[8][3] = 16'd17631;BANK_C[8][4] = 16'd4646; BANK_C[8][5] = -16'd1518;BANK_C[8][6] = -16'd278; BANK_C[9][0]= -16'd1445;BANK_C[9][1]= 16'd2358; BANK_C[9][2] = 16'd15664;BANK_C[9][3] = 16'd16735;BANK_C[9][4] = 16'd3442; BANK_C[9][5] = -16'd1513;BANK_C[9][6] = -16'd293; end //initial always @ (posedge clk) begin if(nreset==1'b0) begin RESSUMM <= 0; RESSUMM_out <= 0; step <= 0; for(i = 0; i < BANK_NUM; i=i+1) begin BANK_D0[i]<=0; BANK_D1[i]<=0; BANK_D2[i]<=0; BANK_D3[i]<=0; BANK_D4[i]<=0; BANK_D5[i]<=0; BANK_D6[i]<=0; end end else begin //формирование строба для чтения выходного регистра if(step==0) rclkDec <= 1; if(step==5) rclkDec <= 0; BANK_D0[step] <= datain; // // сдвигаем данные BANK_D6[step]<=BANK_D5[step];BANK_D5[step]<=BANK_D4[step];BANK_D4[step]<=BANK_D3[step]; BANK_D3[step]<=BANK_D2[step];BANK_D2[step]<=BANK_D1[step];BANK_D1[step]<=BANK_D0[step]; case (step) 0,1,2,3,4,5,6,7,8: begin step <= step + 4'd1; RESSUMM <= RESSUMM + resmult1; end 9: begin step <= 4'd0; RESSUMM_out <= RESSUMM + resmult1;// формируем выход RESSUMM <= 0; end endcase end //else if end //always assign clkDec = rclkDec; assign mult0_1 = BANK_D0[step]; assign mult0_2 = BANK_C[step][6]; assign mult1_1 = BANK_D1[step]; assign mult1_2 = BANK_C[step][5]; assign mult2_1 = BANK_D2[step]; assign mult2_2 = BANK_C[step][4]; assign mult3_1 = BANK_D3[step]; assign mult3_2 = BANK_C[step][3]; assign mult4_1 = BANK_D4[step]; assign mult4_2 = BANK_C[step][2]; assign mult5_1 = BANK_D5[step]; assign mult5_2 = BANK_C[step][1]; assign mult6_1 = BANK_D6[step]; assign mult6_2 = BANK_C[step][0]; assign dataout = RESSUMM_out[33:18]; // обрезаем выходной регистр сверху и снизу для получения нужных 16 бит endmodule Edited November 11, 2021 by Halfback Quote Ответить с цитированием Share this post Link to post Share on other sites
des00 0 Posted November 11, 2021 · Report post assign resmult1 = mult0_1*mult0_2 + mult1_1*mult1_2 + mult2_1*mult2_2 + mult3_1*mult3_2 + mult4_1*mult4_2 + mult5_1*mult5_2 + mult6_1*mult6_2; assign mult0_1 = BANK_D0[step] как минимум после этого, удивительно что это еще на 80МГц работает ЗЫ. Скачайте учебник по ЦОС от альтеры, там в разделе фильтров много крайне полезной информации 43 minutes ago, Halfback said: Может есть возможность что-то поправить/улучшить? что-то мне подсказывает что BANK_D у вас будет реализован на регистрах, если с памятью проблем нет, то я бы переделал все на блочную память) Quote Ответить с цитированием Share this post Link to post Share on other sites
Maverick_ 10 Posted November 11, 2021 · Report post в дополнение к des00 обратите внимание еще на Quote Ответить с цитированием Share this post Link to post Share on other sites
Halfback 0 Posted November 12, 2021 (edited) · Report post 11.11.2021 в 09:55, des00 сказал: ЗЫ. Скачайте учебник по ЦОС от альтеры, там в разделе фильтров много крайне полезной информации Не поделитесь ссылкой или как в гугле поискать? Пока в поисковике вижу только Altera DSP Builder, но как я понимаю это не то что мне нужно... 10 часов назад, Maverick_ сказал: обратите внимание еще на обратил. У меня для Cyclone III (Quartus 13.0.1) нет такого примера, но есть вот такой темплейт для DSP Features/Sum of Four Multipliers (Stratix V, Arria-V, Cyclone-V and later device families) Мне не совсем понятно чем эта реализация отличается от моей. Если разница есть то ткните пожалуйста. Скрытый текст // Quartus II Verilog Template // Sum of four multipliers // For use with the Stratix V, Arria-V, Cyclone-V and later device families module sum_of_4(a1, b1, a2, b2, a3, b3, a4, b4, p); //This template is applicable to sum-of-4 18x18 mode on Stratix-V parameter a_width = 18; parameter b_width = 18; input [a_width-1:0] a1; input [b_width-1:0] b1; input [a_width-1:0] a2; input [b_width-1:0] b2; input [a_width-1:0] a3; input [b_width-1:0] b3; input [a_width-1:0] a4; input [b_width-1:0] b4; output [a_width+b_width+1:0] p; wire signed [a_width-1:0] a1; wire signed [b_width-1:0] b1; wire signed [a_width-1:0] a2; wire signed [b_width-1:0] b2; wire signed [a_width-1:0] a3; wire signed [b_width-1:0] b3; wire signed [a_width-1:0] a4; wire signed [b_width-1:0] b4; wire signed [a_width+b_width+1:0] p; //Static add/sub is supported assign p = a1 * b1 + a2 * b2 - a3 * b3 + a4 * b4; endmodule есть еще вот такой темплейт Sums of Multipliers (я так понял для плис помедленнее). Я таким образом тоже реализовывал - умножение с суммированием в виде отдельного модуля, где то-же самое делалось по клоку. Но ситуация со слеками никак не изменилась. Еще непонятно - целенаправлено ли скобки т.о. расставлены или нет. Скрытый текст // Quartus II Verilog Template // Sum of four multipliers module sum_of_four_multipliers #(parameter WIDTH=18) ( input clk, ena, input [WIDTH-1:0] dataa, datab, datac, datad, input [WIDTH-1:0] datae, dataf, datag, datah, output reg [2*WIDTH+1:0] dataout ); always @ (posedge clk) begin if (ena == 1) begin dataout <= (dataa * datab + datac * datad) + (datae * dataf + datag * datah); end end endmodule Edited November 12, 2021 by Halfback Quote Ответить с цитированием Share this post Link to post Share on other sites
blackfin 0 Posted November 12, 2021 · Report post 25 minutes ago, Halfback said: Не поделитесь ссылкой или как в гугле поискать? Adder Trees, page 17: Advanced Synthesis Cookbook Quote Ответить с цитированием Share this post Link to post Share on other sites
des00 0 Posted November 12, 2021 · Report post 1 hour ago, Halfback said: Не поделитесь ссылкой или как в гугле поискать? Пока в поисковике вижу только Altera DSP Builder, но как я понимаю это не то что мне нужно... https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/manual/stx_cookbook.pdf 1 hour ago, Halfback said: обратил. У меня для Cyclone III (Quartus 13.0.1) нет такого примера, но есть вот такой темплейт для DSP Features/Sum of Four Multipliers (Stratix V, Arria-V, Cyclone-V and later device families) Мне не совсем понятно чем эта реализация отличается от моей. Если разница есть то ткните пожалуйста. количеством регистров и латентностью вычислений. Вот из каких кубиков вы будете собирать свой фильтр. Можно косвенно оценить задержки вашей схемы, для вычислений за 1 такт. 57 minutes ago, blackfin said: Adder Trees, page 17: Advanced Synthesis Cookbook это как раз сорцы к доке) Quote Ответить с цитированием Share this post Link to post Share on other sites