Reputation: 98
Alright guys, sorry if this is a question that's been asked already, as I'm new enough to VHDL logic design to not know exactly how to term a particular concept.
What I'm trying to do is implement the AES-256 algorithm in VHDL for FPGA use.
I have a port named:
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;
How in the architecture do I designate each byte worth of input
as an array
of individual byte-worth segments for the subBytes()
process of the AES algorithm?
Upvotes: 1
Views: 3423
Reputation: 1646
Here's how I defined it when I had to implement 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;
This was the public interface:
function encrypt(
plain_text: std_logic_vector(BLOCK_LENGTH-1 downto 0);
cypher_key: in key_type
) return std_logic_vector;
And here you can see some of the private methods. Note that the main processing methods take in an object 'state_type' and return another value, also of 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;
I found it useful to declare some functions to convert to and from the custom types and 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;
If someone finds it useful I may upload the entire code to GitHub upon request.
Upvotes: 1
Reputation:
From looking in the standard the byte values in AES are organized into columns and rows, you basically need and indexing system to identity array subranges that specify which 8 bits of the input are associated with which row and column.
If you need to loop (as in a generate loop, come on this hardware) you could use multidimensional arrays and assign them from the the input array subranges, where you have row and column indexes. You could make the input array an array of 8 bit things to follow FIPS-197 closely:
You'd find the notation system used in the FIPS is different from the Rijndael submission, you're better off using a common reference system with anyone who might offer help at some point. The FIPS appears to imply you should be using big endian arrays, while you've declared input as little endian.
I'll demonstrate with a design specification that analyzes, elaborates and simulates. (Can't guarantee it is correct, it's late and I'm a bit peckish).
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;
This gives you indexes on bytes so you can use generate statements and do byte steering for transformations, in terms of State (S
shown). You could of course dispense with the subtype declarations and ranges for the input slices directly.
Upvotes: 2
Reputation: 16
A byte is eight bits; so, std_logic_vector(7 downto 0)
would be correct. std_logic_vector
is an array of std_logic
-- each std_logic
can represent a single digital bit.
Upvotes: 0