Notiz
Key Schedule
In this exercise, we will be implementing the key schedule of PRESENT Cipher. It creates all round keys based on the current key register and the current round counter. Initially, the key register contains the user-supplied key and is then updated very round. The interface is given as follows.

The key schedule takes an $80-bit$ or $120-bit$ input representing the current key register at port i_data, the $5-bit$ round counter at port i_round_counter and produces a $80-bit$ or $128-bit$ updated key register at port o_data. The two fixed bit widths shall be configurable with the parameter key_size. Note that PRESENT only uses the uppermost $64$ bits of the key register for the round key. For the 80-bit implementation, the update of the key register $k=k_{79},k_{78},….,k_1,k_0$ is done as follows:
- $k_{79},k_{78},…….k_1,k_0=k_{18},k_{17},….,k_{20},k_{19}$
- $k_{79},k_{78},k_{77},k_{76}=S[k_{79},k_{78},k_{77},k_{76}]$
- $k_{19},k_{18},k_{17},k_{16},k_{15}=(k_{19},k_{18},k_{17},k_{16},k_{15}) \oplus \text{round_counter}$
In the first step , $k$ is rotated to the left by $61$ bits. After that, the MSB nibble is fed to the PRESENT-specific S-box and is replaced by its output. Finally, the bits $k_{19}……k_{15}$ are XORed with the bits of the $5-bit$ round counter.
For the $128-bit$ implementation, the update of the key register $k$ = $k_{127},k_{78},…,k_1,k_0$ is done as follows:
- $k_{127},k_{126},….,k_1,k_0 = k_{66},k_{65},….k_{68},k_{67}$
- $k_{127},k_{126},k_{125},k_{124} = S[k_{127},k_{126},k_{125},k_{124}]$
- $k_{123},k_{122},k_{121},k_{120} = S[k_{123},k_{122},k_{121},k_{120}]$
- $k_{66},k_{65},k_{63},k_{62} = (k_{66},k_{65},k_{64},k_{63},k_{62}) \oplus \text{round_counter}$
In the first step, $k$ is rotated to the left by $61$ bits. After that, the MSB and second MSB nibbles are fed to the PRESENT-specific S-box and are replaced by its respective output. Finally, the bits $k_{66},….k_{62}$ of $k$ are XORed with the bits of the $5-bit$ round counter.
Task 1:
[!Question] Question For the implementation of the key schedule
present_key_scheduleadd the testbench filepresent_key_schedule_tb.vhdland the golden reference filespresent_key_schedule_80_stimuli_results.txtandpresent_key_schedule_128_stimuli_result.txt. Undersources→designright click onpresent_key_schedule.vhdland selectSet as Topunder sources →simright click onpresent_key_schedule_tb.vhdland selectSet as Top. Implementpresent_key_scheduleas $80-bit$ and $128-bit$ variant. Based on the parameterkey_size, the corresponding implementation shall beconditionally generated. Implement both until the testbench tests are performed successfully.
Solutions:
entity present_key_schedule is
generic (
key_size : integer := 80
);
port (
i_data : in std_ulogic_vector(key_size - 1 downto 0);
i_round_counter : in std_ulogic_vector(4 downto 0);
o_data : out std_ulogic_vector(key_size - 1 downto 0)
);
end entity present_key_schedule;
architecture rtl of present_key_schedule is
begin
assert key_size = 80 or key_size = 128
report "key_size must be 80 or 128"
severity failure;
gen_80 : if key_size = 80 generate
signal rotated : std_ulogic_vector(79 downto 0);
begin
-- Rotate the current key left by 61 bits.
rotated <= i_data(18 downto 0) & i_data(79 downto 19);
-- Substitute the highest four bits.
sbox_inst : entity work.present_sbox
port map (
i_data => rotated(79 downto 76),
o_data => o_data(79 downto 76)
);
o_data(75 downto 20) <= rotated(75 downto 20);
-- Combine five key bits with the round number.
o_data(19 downto 15) <=
rotated(19 downto 15) xor i_round_counter;
o_data(14 downto 0) <= rotated(14 downto 0);
end generate gen_80;
gen_128 : if key_size = 128 generate
signal rotated : std_ulogic_vector(127 downto 0);
begin
rotated <= i_data(66 downto 0) & i_data(127 downto 67);
sbox_high : entity work.present_sbox
port map (
i_data => rotated(127 downto 124),
o_data => o_data(127 downto 124)
);
sbox_second : entity work.present_sbox
port map (
i_data => rotated(123 downto 120),
o_data => o_data(123 downto 120)
);
o_data(119 downto 67) <= rotated(119 downto 67);
o_data(66 downto 62) <= rotated(66 downto 62) xor i_round_counter;
o_data(61 downto 0) <= rotated(61 downto 0);
end generate gen_128;
With our existing FPGA, xc7a35tcsg324-2L the simulation of our result:

The elaborated design for the task is:

Now for the testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use std.env.all;
use std.textio.all;
use ieee.std_logic_textio.all;
entity key_schedule_tb is
end entity key_schedule_tb;
architecture tb of key_schedule_tb is
constant bit_width_80 : integer := 80;
constant bit_width_128 : integer := 128;
component present_key_schedule is
generic (
key_size : integer
);
port(
i_data: in std_ulogic_vector(key_size-1 downto 0);
i_round_counter: in std_ulogic_vector(4 downto 0);
o_data: out std_ulogic_vector(key_size-1 downto 0)
);
end component present_key_schedule;
signal key_schedule_in_80 : std_ulogic_vector(bit_width_80-1 downto 0);
signal key_schedule_out_80 : std_ulogic_vector(bit_width_80-1 downto 0);
signal key_schedule_in_128 : std_ulogic_vector(bit_width_128-1 downto 0);
signal key_schedule_out_128 : std_ulogic_vector(bit_width_128-1 downto 0);
signal round_counter : std_ulogic_vector(4 downto 0);
begin
present_key_schedule_80_inst: present_key_schedule
generic map (
key_size => 80
)
port map (
i_data => key_schedule_in_80,
i_round_counter => round_counter,
o_data => key_schedule_out_80
);
present_key_schedule_128_inst: present_key_schedule
generic map (
key_size => 128
)
port map (
i_data => key_schedule_in_128,
i_round_counter => round_counter,
o_data => key_schedule_out_128
);
present_perm_layer_test : process
variable round_counter_val : integer;
variable key_schedule_80_out_val : std_ulogic_vector (bit_width_80-1 downto 0);
variable key_schedule_128_out_val : std_ulogic_vector (bit_width_128-1 downto 0);
file in_out_vectors : text;
variable get_line : line;
variable sep_whitespace : character;
variable key_in_80 : std_ulogic_vector(bit_width_80-1 downto 0);
variable key_in_128 : std_ulogic_vector(bit_width_128-1 downto 0);
variable get_key : boolean;
begin
file_open(in_out_vectors, "present_key_schedule_80_stimuli_results.txt", read_mode);
key_schedule_in_128 <= (others =>'X');
key_schedule_128_out_val := (others => '0');
while not endfile(in_out_vectors) loop
round_counter_val := 1;
get_key := true;
key_schedule_in_80 <= (others =>'X');
round_counter <= (others =>'X');
key_schedule_80_out_val := (others => '0');
wait for 50 ns;
while round_counter_val < 32 loop
if get_key = true then
readline(in_out_vectors, get_line);
read(get_line, key_in_80);
get_key := false;
end if;
read(get_line, sep_whitespace);
read(get_line, key_schedule_80_out_val);
-- Pass the variable to a signal to allow the key-scheduler to use it
round_counter <= std_ulogic_vector(to_unsigned(round_counter_val, 5));
key_schedule_in_80 <= key_in_80;
wait for 10 ns;
assert key_schedule_out_80 = key_schedule_80_out_val report "Key Schedule 80 Bit output wrong! " & "Round Counter Value: " & to_hstring(to_bitvector(round_counter)) & "h" & " | Key Input: " & to_hstring(to_bitvector(key_in_80)) & "h" & " | Expected Output: " & to_hstring(to_bitvector(key_schedule_80_out_val)) & "h" & " | Actual Output: " & to_hstring(to_bitvector(key_schedule_out_80)) & "h" & " | Diff Output: " & to_hstring(to_bitvector(key_schedule_out_80 xor key_schedule_80_out_val)) & "h" severity failure;
key_in_80 := key_schedule_out_80;
round_counter_val := round_counter_val + 1;
wait for 10 ns;
end loop;
end loop;
key_schedule_in_80 <= (others =>'X');
key_schedule_80_out_val := (others => '0');
round_counter <= (others =>'X');
wait for 100 ns;
assert false report "Key Schedule 80 Bit test passed!" severity note;
file_open(in_out_vectors, "present_key_schedule_128_stimuli_results.txt", read_mode);
while not endfile(in_out_vectors) loop
round_counter_val := 1;
get_key := true;
key_schedule_in_128 <= (others =>'X');
round_counter <= (others =>'X');
key_schedule_128_out_val := (others => '0');
wait for 50 ns;
while round_counter_val < 32 loop
if get_key = true then
readline(in_out_vectors, get_line);
read(get_line, key_in_128);
get_key := false;
end if;
read(get_line, sep_whitespace);
read(get_line, key_schedule_128_out_val);
-- Pass the variable to a signal to allow the key-scheduler to use it
round_counter <= std_ulogic_vector(to_unsigned(round_counter_val, 5));
key_schedule_in_128 <= key_in_128;
wait for 10 ns;
assert key_schedule_out_128 = key_schedule_128_out_val report "Key Schedule 128 Bit output wrong! " & "Round Counter Value: " & to_hstring(to_bitvector(round_counter)) & "h" & " | Key Input: " & to_hstring(to_bitvector(key_in_128)) & "h" & " | Expected Output: " & to_hstring(to_bitvector(key_schedule_128_out_val)) & "h" & " | Actual Output: " & to_hstring(to_bitvector(key_schedule_out_128)) & "h" & " | Diff Output: " & to_hstring(to_bitvector(key_schedule_out_128 xor key_schedule_128_out_val)) & "h" severity failure;
key_in_128 := key_schedule_out_128;
round_counter_val := round_counter_val + 1;
wait for 10 ns;
end loop;
end loop;
key_schedule_in_128 <= (others =>'X');
round_counter <= (others =>'X');
wait for 100 ns;
assert false report "Key Schedule 128 Bit test passed!" severity note;
std.env.finish;
end process present_perm_layer_test;
end architecture tb;
For the reference, the two txt files are listed below
For $80-bit$ present_key_schedule_80_stimuli_results.txt
10011101011000010001011110011111011101101100100111000110010100000000001100101001 11000000011001010011001110101100001000101111001111101110110110011011100011001010 10110111000110010101100000001100101001100111010110000100010111110111110111011011 00011111101110110111011011100011001010110000000110010100110011110011000010001011 00010110000100010110001111110111011011101101110001100101011000100011001010011001 10010110010100110010001011000010001011000111111011101101110110010000110010101100 01100001100101011001001011001010011001000101100001000101100011001101110110111011 11101011101101110110110000110010101100100101100101001100100010001000100010110001 01010001000101100011110101110110111011011000011001010110010011110010100110010001 00010101001100100010101000100010110001111010111011011101101101000100101011001001 00111001010110010010001010100110010001010100010001011000111100001101101110110110 01011011011101101100011100101011001001000101010011001000101011010000101100011110 11110001011000111100101101101110110110001110010101100100100011001001100100010101 11100011001000101011111000101100011110010110110111011011000110100010110010010001 10010101100100100011110001100100010101111100010110001111001010101011101101100011 00000111011011000111001010110010010001111000110010001010111111110011000111100101 00010110001111001010000011101101100011100101011001001000111110011001000101011111 10110010001010111110001011000111100101000001110110110001110000100100100100011111 10011001001000111111011001000101011111000101100011110010100010101011011000111000 00000110110001110001001100100100011111101100100010101111100000101001111001010001 00000011110010100010000011011000111000100110010010001111110100110001010111110000 10100010101111100000000001111001010001000001101100011100010001100001000111111010 01000010001111110101010001010111110000000000111100101000100010000110001110001000 11001100011100010000100001000111111010101000101011111000000010100110010100010001 10011100101000100011100110001110001000010000100011111101010111010101111100000001 11111011111000000011001110010100010001110011000111000100001011011001111110101011 10000011111101010111111101111100000001100111001010001000111010110011100010000101 10100111000100001011000001111110101011111110111110000000110000111101000100011101 11011010001000111011010011100010000101100000111111010101111100111111000000011000 11011110000000110001101101000100011101101001110001000010110011110111101010111110 00011111010101111101101111000000011000110110100010001110110111001000100001011001 11100001000010110010001111101010111110110111100000001100011000101001000111011011
11000000111100011001001001110111100000000100100011001110000011100011010100010101 01000110101000101011100000011110001100100100111011110000000010011001100111000001 10110011001110000010100011010100010101110000001111000110010010001101111000000001 01011011110000000011011001100111000001010001101010001010111000011111100011001001 10111111000110010010101101111000000001101100110011100000101000010101000101011100 01101010001010111001011111100011001001010110111100000000110110110001110000010100 10100011100000101000110101000101011100101111110001100100101011101110000000011011 01111100000000110111010001110000010100011010100010101110010111000000110010010101 00110001100100101010111110000000011011101000111000001010001100010001010111001011 01100010101110010110011000110010010101011111000000001101110101010100000101000110 11111000001010001100110001010111001011001100011001001010101110110000000110111010 10100000001101110101111100000101000110011000101011100101100111010100100101010111 11111001001010101111010000000110111010111110000010100011001101110101110010110011 00011011100101100111111100100101010111101000000011011101011110101001010001100110 00000010100011001100001101110010110011111110010010101011110101110001101110101111 00010011011101011110000001010001100110000110111001011001111110110001010101111010 10100010101011110100001001101110101111000000101000110011000001011100101100111111 10001001011001111111010001010101111010000100110111010111100010011100011001100000 10111000110011000001000100101100111111101000101010111101000000001011101011110001 01010111010111100011011100011001100000100010010110011111110110001101011110100000 01011010111101000000101011101011110001101110001100110000010011101011001111111011 01110110011111110110101101011110100000010101110101111000110101101110011000001001 01111100110000010010111011001111111011010110101111010000001000001010111100011010 01010101111000110100111110011000001001011101100111111101101001101111101000000100 01111111010000001000101010111100011010011111001100000100101101110011111110110100 00010111111101101000111111101000000100010101011110001101001100101110000010010110 00001100000100101100001011111110110100011111110100000010001001111111000110100110 00101110001101001100000110000010010110000101111111011010001100100010000001000100 10010100000010001000010111000110100110000011000001001011000001011111101101000110 10001111011010001101001010000001000100001011100011010011000010001000100101100000 01010001001011000001000111101101000110100101000000100010000110000001101001100001 11000011010011000010101000100101100000100011110110100011010001011000010001000011
and for the $128-bit$ is present_key_schedule_128_stimuli_results.txt
10011101011000010001011110011111011101101100100111000110010100000000001100101001 11000000011001010011001110101100001000101111001111101110110110011011100011001010 10110111000110010101100000001100101001100111010110000100010111110111110111011011 00011111101110110111011011100011001010110000000110010100110011110011000010001011 00010110000100010110001111110111011011101101110001100101011000100011001010011001 10010110010100110010001011000010001011000111111011101101110110010000110010101100 01100001100101011001001011001010011001000101100001000101100011001101110110111011 11101011101101110110110000110010101100100101100101001100100010001000100010110001 01010001000101100011110101110110111011011000011001010110010011110010100110010001 00010101001100100010101000100010110001111010111011011101101101000100101011001001 00111001010110010010001010100110010001010100010001011000111100001101101110110110 01011011011101101100011100101011001001000101010011001000101011010000101100011110 11110001011000111100101101101110110110001110010101100100100011001001100100010101 11100011001000101011111000101100011110010110110111011011000110100010110010010001 10010101100100100011110001100100010101111100010110001111001010101011101101100011 00000111011011000111001010110010010001111000110010001010111111110011000111100101 00010110001111001010000011101101100011100101011001001000111110011001000101011111 10110010001010111110001011000111100101000001110110110001110000100100100100011111 10011001001000111111011001000101011111000101100011110010100010101011011000111000 00000110110001110001001100100100011111101100100010101111100000101001111001010001 00000011110010100010000011011000111000100110010010001111110100110001010111110000 10100010101111100000000001111001010001000001101100011100010001100001000111111010 01000010001111110101010001010111110000000000111100101000100010000110001110001000 11001100011100010000100001000111111010101000101011111000000010100110010100010001 10011100101000100011100110001110001000010000100011111101010111010101111100000001 11111011111000000011001110010100010001110011000111000100001011011001111110101011 10000011111101010111111101111100000001100111001010001000111010110011100010000101 10100111000100001011000001111110101011111110111110000000110000111101000100011101 11011010001000111011010011100010000101100000111111010101111100111111000000011000 11011110000000110001101101000100011101101001110001000010110011110111101010111110 00011111010101111101101111000000011000110110100010001110110111001000100001011001 11100001000010110010001111101010111110110111100000001100011000101001000111011011
11000000111100011001001001110111100000000100100011001110000011100011010100010101 01000110101000101011100000011110001100100100111011110000000010011001100111000001 10110011001110000010100011010100010101110000001111000110010010001101111000000001 01011011110000000011011001100111000001010001101010001010111000011111100011001001 10111111000110010010101101111000000001101100110011100000101000010101000101011100 01101010001010111001011111100011001001010110111100000000110110110001110000010100 10100011100000101000110101000101011100101111110001100100101011101110000000011011 01111100000000110111010001110000010100011010100010101110010111000000110010010101 00110001100100101010111110000000011011101000111000001010001100010001010111001011 01100010101110010110011000110010010101011111000000001101110101010100000101000110 11111000001010001100110001010111001011001100011001001010101110110000000110111010 10100000001101110101111100000101000110011000101011100101100111010100100101010111 11111001001010101111010000000110111010111110000010100011001101110101110010110011 00011011100101100111111100100101010111101000000011011101011110101001010001100110 00000010100011001100001101110010110011111110010010101011110101110001101110101111 00010011011101011110000001010001100110000110111001011001111110110001010101111010 10100010101011110100001001101110101111000000101000110011000001011100101100111111 10001001011001111111010001010101111010000100110111010111100010011100011001100000 10111000110011000001000100101100111111101000101010111101000000001011101011110001 01010111010111100011011100011001100000100010010110011111110110001101011110100000 01011010111101000000101011101011110001101110001100110000010011101011001111111011 01110110011111110110101101011110100000010101110101111000110101101110011000001001 01111100110000010010111011001111111011010110101111010000001000001010111100011010 01010101111000110100111110011000001001011101100111111101101001101111101000000100 01111111010000001000101010111100011010011111001100000100101101110011111110110100 00010111111101101000111111101000000100010101011110001101001100101110000010010110 00001100000100101100001011111110110100011111110100000010001001111111000110100110 00101110001101001100000110000010010110000101111111011010001100100010000001000100 10010100000010001000010111000110100110000011000001001011000001011111101101000110 10001111011010001101001010000001000100001011100011010011000010001000100101100000 01010001001011000001000111101101000110100101000000100010000110000001101001100001 11000011010011000010101000100101100000100011110110100011010001011000010001000011
On running the testbenchmark:

It seems there has been an error as none of the wave is seen. On debugging, (within TCL Console), I got to know that the text files were not being loaded. After loading those .txt files within the Simulation sources, we got the output.

