Сокращение использования LUT в проекте Vivado HLS (криптосистема RSA с использованием умножения Монтгомери)

Вопрос / проблема для всех, кто имел опыт работы с Xilinx Vivado HLS и FPGA:

Мне нужна помощь в уменьшении числа использованных проектов в пределах HLS (то есть я не могу просто переделать проект в HDL). Я нацеливаюсь на Zedboard (Zynq 7020).

Я пытаюсь реализовать 2048-битный RSA в HLS, используя алгоритм умножения Монтгомери на множество слов Tenca-koc, показанный ниже (подробнее об алгоритме здесь):

Я написал этот алгоритм в HLS, и он работает в симуляции и C/RTL cosim. Мой алгоритм здесь:

#define MWR2MM_m 2048  // Bit-length of operands
#define MWR2MM_w 8     // word size
#define MWR2MM_e 257   // number of words per operand

// Type definitions
typedef ap_uint<1> bit_t;             // 1-bit scan
typedef ap_uint< MWR2MM_w > word_t;     // 8-bit words
typedef ap_uint< MWR2MM_m > rsaSize_t;  // m-bit operand size


/*
 * Multiple-word radix 2 montgomery multiplication using carry-propagate adder
 */
void mwr2mm_cpa(rsaSize_t X, rsaSize_t Yin, rsaSize_t Min, rsaSize_t* out)
{
    // extend operands to 2 extra words of 0
    ap_uint<MWR2MM_m + 2*MWR2MM_w> Y = Yin; 
    ap_uint<MWR2MM_m + 2*MWR2MM_w> M = Min;
    ap_uint<MWR2MM_m + 2*MWR2MM_w> S = 0;

    ap_uint<2> C = 0; // two carry bits
    bit_t qi = 0;     // an intermediate result bit

    // Store concatenations in a temporary variable to eliminate HLS compiler warnings about shift count
    ap_uint<MWR2MM_w> temp_concat=0; 

    //  scan X bit-by bit
    for (int i=0; i<MWR2MM_m; i++)
    {
        qi = (X[i]*Y[0]) xor S[0];

        // C gets top two bits of temp_concat, j'th word of S gets bottom 8 bits of temp_concat
        temp_concat = X[i]*Y.range(MWR2MM_w-1,0) + qi*M.range(MWR2MM_w-1,0) + S.range(MWR2MM_w-1,0);
        C = temp_concat.range(9,8);
        S.range(MWR2MM_w-1,0) = temp_concat.range(7,0);

        // scan Y and M word-by word, for each bit of X
        for (int j=1; j<=MWR2MM_e; j++)
        {
            temp_concat = C + X[i]*Y.range(MWR2MM_w*j+(MWR2MM_w-1), MWR2MM_w*j) + qi*M.range(MWR2MM_w*j+(MWR2MM_w-1), MWR2MM_w*j) + S.range(MWR2MM_w*j+(MWR2MM_w-1), MWR2MM_w*j);
            C = temp_concat.range(9,8);
            S.range(MWR2MM_w*j+(MWR2MM_w-1), MWR2MM_w*j) = temp_concat.range(7,0);

            S.range(MWR2MM_w*(j-1)+(MWR2MM_w-1), MWR2MM_w*(j-1)) = (S.bit(MWR2MM_w*j), S.range( MWR2MM_w*(j-1)+(MWR2MM_w-1), MWR2MM_w*(j-1)+1));
        }
        S.range(S.length()-1, S.length()-MWR2MM_w) = 0;
        C=0;
    }

    // if final partial sum is greater than the modulus, bring it back to proper range
    if (S >= M)
        S -= M;

    *out = S;
}

К сожалению, использование LUT огромно.

Это проблематично, потому что я должен быть в состоянии установить несколько из этих блоков на аппаратном уровне как подчиненные устройства Axi4.

Может ли кто-нибудь дать несколько советов относительно того, как я могу уменьшить использование LUT В КОНФИННАХ HLS?

Я уже пробовал следующее:

  • Экспериментируя с разной длиной слова
  • переключение входов верхнего уровня на массивы, чтобы они были BRAM (т.е. не использовали ap_uint<2048>, а вместо этого ap_uint foo[MWR2MM_e])
  • Эксперименты со всеми видами директив: разделение на несколько встроенных функций, архитектура потока данных, ограничения ресурсов на lshr и т. Д.

Тем не менее, ничто не может существенно снизить использование LUT. Есть ли явно очевидный способ уменьшить использование, который очевиден для всех?

В частности, я видел статьи о реализации алгоритма mwr2mm, который ( использует только один блок DSP и один BRAM). Стоит ли пытаться реализовать это с помощью HLS? Или нет никакого способа, которым я мог бы фактически управлять ресурсами, на которые отображается алгоритм, не описывая его в HDL?

Спасибо за помощь.

0 ответов

Другие вопросы по тегам