Как обозначить порт как массив байтов в VHDL

Хорошо, ребята, извините, если этот вопрос уже задавался, поскольку я достаточно новичок в разработке логики VHDL, чтобы не знать, как именно назвать конкретную концепцию.

То, что я пытаюсь сделать, это реализовать алгоритм AES-256 в VHDL для использования FPGA.

У меня есть порт с именем:

entity rijndael is port
(
input : in std_logic_vector(255 downto 0)
subkey: in std_logic_vector(255 downto 0)
output: out std_logic_vector(255 downto 0)
);
end rijndael;

Как в архитектуре обозначить каждый байт со значением input как array отдельных сегментов со значением байта для процесса subBytes() алгоритма AES?


person blasthash    schedule 04.03.2014    source источник


Ответы (3)


Судя по стандарту, значения байтов в AES организованы в столбцы и строки, вам в основном нужна система индексации для поддиапазонов массива идентификаторов, которые указывают, какие 8 бит ввода связаны с какой строкой и столбцом.

Если вам нужно зациклиться (как в цикле генерации, на этом оборудовании), вы можете использовать многомерные массивы и назначать их из поддиапазонов входного массива, где у вас есть индексы строк и столбцов. Вы можете сделать входной массив массивом из 8-битных вещей, чтобы точно следовать FIPS-197:

Взаимосвязь входного, состояния и выходного байтов, 128-битный блок

Вы обнаружите, что система обозначений, используемая в FIPS, отличается от представленной Rijndael, вам лучше использовать общую справочную систему со всеми, кто может предложить помощь в какой-то момент. Похоже, что FIPS подразумевает, что вы должны использовать массивы с обратным порядком байтов, в то время как вы объявили ввод как прямой.

Я продемонстрирую спецификацию проекта, которая анализирует, разрабатывает и моделирует. (Не могу гарантировать, что это правильно, уже поздно, и я немного проголодался).

library ieee;
use ieee.std_logic_1164.all;

entity State is
    port (
        input:      in      std_logic_vector (0 to 255);
        output:     out     std_logic_vector (0 to 255)
    );

end entity;

architecture foo of State is

    subtype in0  is natural range   0 to   7;
    subtype in1  is natural range   8 to  15;
    subtype in2  is natural range  16 to  23;
    subtype in3  is natural range  24 to  31;
    subtype in4  is natural range  32 to  39;
    subtype in5  is natural range  40 to  47;
    subtype in6  is natural range  48 to  55;
    subtype in7  is natural range  56 to  63;
    subtype in8  is natural range  64 to  71;
    subtype in9  is natural range  72 to  79;
    subtype in10 is natural range  80 to  87;
    subtype in11 is natural range  88 to  95;
    subtype in12 is natural range  96 to 103;
    subtype in13 is natural range 104 to 111;
    subtype in14 is natural range 112 to 119;
    subtype in15 is natural range 120 to 127;
    subtype in16 is natural range 128 to 135;
    subtype in17 is natural range 136 to 143;
    subtype in18 is natural range 144 to 151;
    subtype in19 is natural range 152 to 159;
    subtype in20 is natural range 160 to 167;
    subtype in21 is natural range 168 to 175;
    subtype in22 is natural range 176 to 183;
    subtype in23 is natural range 184 to 191;
    subtype in24 is natural range 192 to 199;
    subtype in25 is natural range 200 to 207;
    subtype in26 is natural range 208 to 215;
    subtype in27 is natural range 216 to 223;
    subtype in28 is natural range 224 to 231;
    subtype in29 is natural range 232 to 239;
    subtype in30 is natural range 240 to 247;
    subtype in31 is natural range 248 to 255;

    type state_array is array   -- (row, col) of 8 bits
         (natural range 0 to 3, natural range 0 to 7)
                         of std_logic_vector(0 to 7); 

    signal S:   state_array;

begin 

    S <= state_array'( 
              ( input(in0),  input(in4),  input(in8),  input(in12),
                input(in16), input(in20), input(in24), input(in28) ),
              ( input(in1),  input(in5),  input(in9),  input(in13),
                input(in17), input(in21), input(in25), input(in29) ),
              ( input(in2),  input(in6),  input(in10), input(in14), 
                input(in18), input(in22), input(in26), input(in30) ),
              ( input(in3),  input(in7),  input(in11), input(in15),
                input(in19), input(in23), input(in27), input(in31) )
         );

    output <= S(0,0) & S(1,0) & S(2,0) & S(3,0) &  -- columns on side
              S(0,1) & S(1,1) & S(2,1) & S(3,1) &
              S(0,2) & S(1,2) & S(2,2) & S(3,2) &
              S(0,3) & S(1,3) & S(2,3) & S(3,3) &
              S(0,4) & S(1,4) & S(2,4) & S(3,4) &
              S(0,5) & S(1,5) & S(2,5) & S(3,5) &
              S(0,6) & S(1,6) & S(2,6) & S(3,6) &
              S(0,7) & S(1,7) & S(2,7) & S(3,7) ;

end architecture;

Это дает вам индексы для байтов, поэтому вы можете использовать операторы генерации и управлять байтами для преобразований с точки зрения состояния (показано S). Конечно, вы можете обойтись без объявлений подтипов и диапазонов для входных срезов напрямую.

person Community    schedule 04.03.2014

Вот как я это определил, когда мне пришлось реализовать AES-128:

constant KEY_LENGTH: integer := 128;
constant BLOCK_LENGTH: integer := 128;

subtype key_type is std_logic_vector(KEY_LENGTH-1 downto 0);
type key_array_type is array (natural range<>) of key_type;
subtype word_type is std_logic_vector(31 downto 0);
subtype byte_type is std_logic_vector(7 downto 0);
type state_type is array (0 to 3, 0 to 3) of std_logic_vector(7 downto 0);
type state_array_type is array (natural range<>) of state_type;
type column_type is array (0 to 3) of std_logic_vector(7 downto 0);
type column_array_type is array (natural range<>) of column_type;

Это был общедоступный интерфейс:

function encrypt(
    plain_text: std_logic_vector(BLOCK_LENGTH-1 downto 0);
    cypher_key: in key_type
) return std_logic_vector;

И здесь вы можете увидеть некоторые из приватных методов. Обратите внимание, что основные методы обработки принимают объект state_type и возвращают другое значение, также state_type:

function shift_rows(state_in: state_type) return state_type;
function mix_columns(state_in: state_type) return state_type;
function add_round_key(state: state_type; round_key: key_type) return state_type;
function mix_column(column_in: column_type) return column_type;
function expand_key(cypher_key: key_type) return column_array_type;
function round_key(expanded_key: column_array_type; round_number: integer) return key_type;

Я нашел полезным объявить некоторые функции для преобразования в и из пользовательских типов и std_logic_vector:

function vector_from_state(state: state_type) return std_logic_vector;
function state_from_vector(vector: std_logic_vector(127 downto 0)) return state_type;
function vector_from_column(column: column_type) return std_logic_vector;
function state_from_columns(columns: column_array_type) return state_type;
function vector_from_columns(columns: column_array_type) return std_logic_vector;
function columns_from_state(state: state_type) return column_array_type;

Если кому-то это покажется полезным, я могу загрузить весь код на GitHub по запросу.

person rick    schedule 06.03.2014

Байт — это восемь битов; поэтому std_logic_vector(7 downto 0) будет правильным. std_logic_vector — это массив std_logic — каждый std_logic может представлять один цифровой бит.

person user3273575    schedule 04.03.2014