Прикинул на пальцах Ваши матрицы, вот чего вышло :
- float был переделан в fixed point 32 бита (16/16)
- sqrt был заменен заглушкой [ float sqrt(float v) { return v; } ] - под рукой
не оказалось подходящей реализации
- интерфейс к массивам был оставлен single-port async ram и выведен на пины (изврат конечно, никто не спорит)
- для оценки взят камень EP1C20F400C6, так как пинов получилось в районе 256 :
- clk
- reset
- start_processing
- processing_inv_is_done
- float d[32] out - просто регистр
- float A[32] out
- float A[32] in
- A_addr[8]
- A_we
- float S[32] out
- float S[32] in
- S_addr[8]
- S_we
- float K[32] out
- float K[32] in
- K_addr[8]
- K_we
- async_ram_en - обчая линия
- замечания по f() :
- переменные kr и ki используются с неопределенным значением
- опущены последние 4 строки f()
Без какой либо особой оптимизации по скорости - for ex. 1 цикл остался тупо линейным, у меня вышло
2911 тактов на оценочной частоте 50Mhz. Предварительная оценка (т.е. максимум) данной f() по ресурсам такова :
Device Utilization for EP1C20F400C:
Resource Used Avail Utilization
-----------------------------------------------
IOs 258 301 85.71%
LCs 14216 20060 70.87%
в квартусе :
+--------------------------------------------------------------------------------+
; Fitter Resource Usage Summary ;
+---------------------------------------------+----------------------------------+
; Resource ; Usage ;
+---------------------------------------------+----------------------------------+
; Total logic elements ; 13,909 / 20,060 ( 69 % ) ;
; -- Combinational with no register ; 13443 ;
; -- Register only ; 8;
; -- Combinational with a register ; 458;
; ;;
; Logic element usage by number of LUT inputs ;;
; -- 4 input functions ; 2577;
; -- 3 input functions ; 7711;
; -- 2 input functions ; 3472 ;
; -- 1 input functions ; 148 ;
; -- 0 input functions ; 1 ;
; ; ;
; Logic elements by mode ; ;
; -- normal mode ; 7024 ;
; -- arithmetic mode ; 6885 ;
; -- qfbk mode ; 102 ;
; -- register cascade mode ; 0 ;
; -- synchronous clear/load mode ; 466 ;
; -- asynchronous clear/load mode ; 0 ;
; ; ;
; Total LABs ; 1,528 / 2,006 ( 76 % ) ;
; Logic elements in carry chains ; 7119 ;
; User inserted logic elements ; 0 ;
; Virtual pins ; 0 ;
; I/O pins ; 258 / 301 ( 86 % ) ;
; -- Clock pins ; 2 / 2 ( 100 % ) ;
; Global signals ; 1 ;
; M4Ks ; 0 / 64 ( 0 % ) ;
; Total memory bits ; 0 / 294,912 ( 0 % ) ;
; Total RAM block bits ; 0 / 294,912 ( 0 % ) ;
; PLLs ; 0 / 2 ( 0 % ) ;
; Global clocks ; 1 / 8 ( 13 % ) ;
+---------------------------------------------+----------------------------------+
Заводится эта фигня, если верить precision'у, а оснований не верить у нас
нет, где-то на 65.062MHz, min period - 15.370 ns, квартус как всегда более консервативен :
; Worst-case tsu ; N/A ; None ; 26.537 ns S_rsc_singleport_data_out[3] ; inv_inv_proc_1|slc_i32_l90_cse_24_ ; -- ; clk ; 0 ;
; Worst-case tco ; N/A ; None ; 164.411 ns ; inv_inv_proc_1|div_div_b_17_ ; K_rsc_singleport_data_in[0] ; clk ; -- ; 0 ;
; Worst-case tpd ; N/A ; None ; 35.901 ns ; K_rsc_singleport_data_out[0] ; S_rsc_singleport_data_in[17] ; -- ; -- ; 0 ;
; Worst-case th ; N/A ; None ; -2.489 ns ; d[5] ; inv_inv_proc_1|inv_d_5_ ; -- ; clk ; 0 ;
; Clock Setup: 'clk' ; 0.256 ns ; 50.00 MHz ( period = 20.000 ns ) ; 50.65 MHz ( period = 19.744 ns ) ; inv_inv_proc_1|slc_i32_l90_cse_18_ ; inv_inv_proc_1|inv_ai_1_26_ ; clk ; clk ; 0 ;
; Clock Hold: 'clk' ; 0.633 ns ; 50.00 MHz ( period = 20.000 ns ) ; N/A ; inv_inv_proc_1|inv_q_1__4_1_0_ ; inv_inv_proc_1|inv_q_1__4_1_0_ ; clk ; clk ; 0 ;
; Total number of failed paths ; ; ; ; ; ; ; ; 0
Если взять cyclone-2 (так как в проекте заюзаны mul и div), данные засунуть в internal dual-port ram, да еще потратить время на оптимизацию, то результат по ресурсам обычно можно сократить вдвое, а скорость поднять в 4 - 10 раз.
Также приделывается нормальный интерфейс к данным и т.д. и т.п., короче шлифовать можно до опупения.
Итого получаем грубо 2911 * 19.75ns = ~57.5 мкс (без учета sqrt) на _всю_ операцию в FGPA.
Ваш ход, принц