|
Евклидово расстояние на Xilinx DSP48 |
|
|
|
Feb 18 2016, 09:31
|

я только учусь...
     
Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839

|
Цитата(count_enable @ Feb 18 2016, 11:18)  Вот такую задачку сейчас обдумываю. Надо считать евклидово расстояние, координаты точек передаются парами последовательно: А(0) В(0), А(1) В(1), А(2) В(2). Евклидово расстояние это sqrt(sum((А-B )^2)). Корень посчитаю кордиком, сумму аккумулятором, а вот как быть с квадратом разницы? Возможно ли это сделать на одном DSP48 блоке за вменяемое количество циклов? Подскажите где прочитать об этом. Все числа с фикс. точкой. Для альтеры - примерыС Xilinx давно не работал, попробуйте, должно аналогичным способом описываться....
--------------------
If it doesn't work in simulation, it won't work on the board.
"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
|
|
|
|
|
Feb 18 2016, 09:37
|
Гуру
     
Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261

|
Цитата(count_enable @ Feb 18 2016, 13:18)  Корень посчитаю кордиком, сумму аккумулятором, а вот как быть с квадратом разницы? Возможно ли это сделать на одном DSP48 блоке за вменяемое количество циклов? Так готовый IP-Core комплексного умножителя должен подойти. Там и латентность выбрать можно. Примерно так: X_re = A(0)-B(0); X_im = A(1)-B(1); Y_re = A(0)-B(0); Y_im = B(1)-A(1); X*Y = [A(0)-B(0)]^2+[A(1)-B(1)]^2; PS. Хотя, если все значения идут с задержкой в один такт, то можно, КМК, и один умножитель использовать .. Наверное, это будет оптимальнее по ресурсам.
|
|
|
|
|
Feb 18 2016, 10:18
|
Местный
  
Группа: Свой
Сообщений: 310
Регистрация: 28-01-13
Из: Лондон
Пользователь №: 75 384

|
Цитата(blackfin @ Feb 18 2016, 13:37)  Так готовый IP-Core комплексного умножителя должен подойти. Там же вроде 2 пары только можно за маш. цикл умножать? Maverick, не совсем понял как связана рекомендуемая тема с возведением в квадрат. Вы предлагаете закольцевать выход DSP на его же вход Carry, и поштучно возводить аргументы в квадрат, аккумулируя их? Звучит интересно. Так можно считать расстояния в N-мерном пространстве, и решение в принципе простое. Но наверно надо выбросить все внутренние регистры, потому что ждать 7 клоков задержки на один аргумент что-то неохота.
|
|
|
|
|
Feb 18 2016, 10:35
|
Гуру
     
Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261

|
Цитата(count_enable @ Feb 18 2016, 14:18)  Там же вроде 2 пары только можно за маш. цикл умножать? Ну, если у Вас в каждом такте приходит одна пара A и B, то можно умножитель с накоплением использовать: Код input signed [] A0,A1,A2; input signed [] B0,B1,B2;
wire signed [] SA = (T == 0) ? A0 : (T == 1) ? A1 : (T == 2) ? A2 : 0; wire signed [] SB = (T == 0) ? B0 : (T == 1) ? B1 : (T == 2) ? B2 : 0;
reg signed [] D;
always @(posedge clk) begin D <= SA - SB; end
wire [] P;
multadd multadd_m(.clk(clk),.A(D),.B(D),.C(P),.P(P));
reg [] R;
always @(posedge clk) begin if (sclr) R <= 0; else if (valid) R <= P; end PS. И даже задержка не нужна. Нужен сигнал valid совпадающий по времени с результатом суммирования: T = mult_latency + add_latency + 2;
|
|
|
|
|
Feb 18 2016, 11:13
|
Местный
  
Группа: Свой
Сообщений: 310
Регистрация: 28-01-13
Из: Лондон
Пользователь №: 75 384

|
Цитата(blackfin @ Feb 18 2016, 14:35)  Ну, если у Вас в каждом такте приходит одна пара A и B, то можно умножитель с накоплением использовать: Извините, верилог знаю только со словарём. Где в этом коде возведение в степень (А-В )^2?
|
|
|
|
|
Feb 18 2016, 11:33
|

я только учусь...
     
Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839

|
Цитата(count_enable @ Feb 18 2016, 13:19)  Код library IEEE; use IEEE.std_logic_1164.all; use ieee.numeric_std.all;
entity half_dsp_block is generic (WIDTH: integer := 18); port ( clock : in std_logic; areset : in std_logic; clock_ena : in std_logic; a0 : in std_logic_vector(WIDTH-1 downto 0); b0 : in std_logic_vector(WIDTH-1 downto 0); a1 : in std_logic_vector(WIDTH-1 downto 0); b1 : in std_logic_vector(WIDTH-1 downto 0); a2 : in std_logic_vector(WIDTH-1 downto 0); b2 : in std_logic_vector(WIDTH-1 downto 0); a3 : in std_logic_vector(WIDTH-1 downto 0); b3 : in std_logic_vector(WIDTH-1 downto 0); w : out std_logic_vector(2*WIDTH+1 downto 0)); end half_dsp_block;
architecture rtl of half_dsp_block is
signal a0_reg : signed(WIDTH-1 downto 0); signal b0_reg : signed(WIDTH-1 downto 0); signal a1_reg : signed(WIDTH-1 downto 0); signal b1_reg : signed(WIDTH-1 downto 0); signal a2_reg : signed(WIDTH-1 downto 0); signal b2_reg : signed(WIDTH-1 downto 0); signal a3_reg : signed(WIDTH-1 downto 0); signal b3_reg : signed(WIDTH-1 downto 0); signal p0 : signed(2*WIDTH downto 0); signal p1 : signed(2*WIDTH downto 0); signal w_sig : signed(2*WIDTH+1 downto 0);
begin
process (clock, areset) begin if (areset = '1') then -- asynchronous reset a0_reg <= (others => '0'); b0_reg <= (others => '0'); a1_reg <= (others => '0'); b1_reg <= (others => '0'); a2_reg <= (others => '0'); b2_reg <= (others => '0'); a3_reg <= (others => '0'); b3_reg <= (others => '0'); p0 <= (others => '0'); p1 <= (others => '0'); w_sig <= (others => '0'); elsif clock'event and clock = '1' and clock_ena = '1'then -- rising clock edge a0_reg <= signed(a0); b0_reg <= signed(b0); a1_reg <= signed(a0_reg); b1_reg <= signed(b1); a2_reg <= signed(a1_reg); b2_reg <= signed(b2); a3_reg <= signed(a2_reg); b3_reg <= signed(b3); --must follow the following order to be recognized to use shift register input p0 <= resize((a1_reg*b1_reg),p0'length) + resize((a0_reg*b0_reg),p0'length); p1 <= resize((a3_reg*b3_reg),p1'length) + resize((a2_reg*b2_reg),p1'length); w_sig <= resize(p0,w_sig'length) + resize(p1,w_sig'length); end if; end process;
w <= std_logic_vector(w_sig);
end rtl; Вы можете аналогичным способом поступить - для альтеры работало...
--------------------
If it doesn't work in simulation, it won't work on the board.
"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
|
|
|
|
|
Feb 18 2016, 11:41
|
Гуру
     
Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261

|
Цитата(count_enable @ Feb 18 2016, 15:13)  Извините, верилог знаю только со словарём. Где в этом коде возведение в степень (А-В )^2? Там три такта выполняется умножение: D*D. Цитата(count_enable @ Feb 18 2016, 15:19)  Последний multadd multadd_m(..,.A(D),.B(D),.C(P),.P(P)); ? И где Р это мой аккумулятор? Результат суммирования - в регистре R.
|
|
|
|
|
Feb 22 2016, 10:02
|
Гуру
     
Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261

|
Цитата(count_enable @ Feb 18 2016, 14:49)  Спасибо большое. Уже "увидел" как оно будет работать. Это прекрасно! Тем более, что мне заставить xbip_multadd работать в режиме аккумулятора и без warnings так и не удалось.  Для коротких векторов A и B синтезируется без ошибок xbip_dsp48_macro для единственной операции: (A+D)*B+P. Если вектора A и B длиннее 18 бит, то придется, вероятно, использовать mult_gen_0 в режиме умножителя и суммировать результаты умножения во внешнем аккумуляторе. Для xbip_dsp48_macro код получился вот такой: Код module acc ( clk, nrst, A0,A1,A2,B0,B1,B2, T,valid,R );
input clk; input nrst;
input signed [16:0] A0,A1,A2; input signed [16:0] B0,B1,B2; input [1:0] T; input valid; output [36:0] R;
wire signed [16:0] SA = (T == 0) ? A0 : (T == 1) ? A1 : (T == 2) ? A2 : 0; wire signed [16:0] SB = (T == 0) ? B0 : (T == 1) ? B1 : (T == 2) ? B2 : 0;
reg signed [17:0] D;
always @(posedge clk) begin D <= SA - SB; end
wire [36:0] P;
dsp48mac dsp48mac_m(.clk(clk),.a(D),.b(D),.d(0),.p(P));
reg [36:0] R;
always @(posedge clk or negedge nrst) begin if (nrst == 0) begin R <= 0; end else if (valid) begin R <= P; end end
endmodule
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|