This website uses cookies. By using this site, you consent to the use of cookies. For more information, please take a look at our Privacy Policy.
Home > FPGA Technical Tutorials > Design Recipes for FPGAs Using Verilog and VHDL > Design Optimization Example: DES > Initial Design

TABLE OF CONTENTS

Xilinx FPGA FPGA Forum

Initial Design

FONT SIZE : AAA

Introduction

The overall structure of the DES algorithm is shown in Figure 19.1.

The core algorithm is repeated 16 times with a different subkey for each round. These subkeys are 48 bits long and are generated from the original 56-bit key. The algorithm was converted directly to VHDL using a functional decomposition style (i.e., functions were created to represent each equivalent function in DES).

Overall Structure

The first stage in this design was to create an entity and an architecture with the required inputs and outputs and a single process containing the overall algorithm. This resulted in the VHDL outline here:


library ieee;

use ieee.std_logic_1164.all;

entity DES is

port (

plaintext : in std_logic_vector(1 to 64);

key : in std_logic_vector(1 to 64);

encrypt : in std_logic;

go : in std_logic;

ciphertext : out std_logic_vector(1 to 64);

done : out std_logic

);

end;

architecture behavior of DES is

subtype vec56 is std_logic_vector(1 to 56);

.

subtype vec64 is std_logic_vector(1 to 64);

begin

process

begin

wait until go = 1;

done <= 0;

wait for 0 ns;

ciphertext <=

des_core(plaintext, key_reduce(key), encrypt);

done <= 1;

end process;

end;

This process is a direct implementation of the main DES routine. The only implementation-specific feature is that the model waits for the signal go to be raised before

Overall structure of the DES algorithmpng

Figure 19.1 Overall structure of the DES algorithm.

starting processing and it raises the signal done at the end of processing, implementing a basic handshaking protocol.

This algorithm requires the two functions key_reduce and des_core. The former strips the parity bits from the key and the latter then implements the whole DES algorithm. The key_reduce function reduces the key from 64 to 56 bits and permutes the bits to form the initial state of the subkey:

function key_reduce(key : in vec64) return vec56 is

−−moods inline

begin

return

key(57) & key(49) & key(41) & key(33) &

.

key(28) & key(20) & key(12) & key(4);

end;

The compiler directive –moods inline causes the synthesizer to inline the function. This allows the optimizer more scope for optimization of the circuit. The des_core function applies the basic DES algorithm 16 times on a slice of the data using a different subkey on each iteration:

function des_core

−−moods inline

(plaintext : vec64;

key : vec56;

encrypt : std_logic)

return vec64

is

variable data : vec64;

variable working_key : vec56 := key;

begin

data := initial_permutation(plaintext);

for round in 0 to 15 loop

working_key :=

key_rotate(working_key,round,encrypt);

data := data(33 to 64) &

(f(data(33 to 64),key_compress(working_key))

xor

data(1 to 32));

end loop;

return

final_permutation(data(33 to 64) & data(1 to 32));

end;

The DES algorithm is made up of the key transformation functions key_rotate and key_compress, and the data transformation functions initial_permutation, f and final_permutation.

Data Transformations

The data transformations initial_permutation and final_permutation are simply hard-wired bit-swapping routines implemented using concatenation.

function initial_permutation(data : vec64) return vec64 is

begin

−−moods inline

return

data(58) & data(50) & data(42) & data(34) &

.

data(31) & data(23) & data(15) & data(7);

end;

function final_permutation(data : in vec64) return vec64 is

begin

−−moods inline

return

data(40) & data(8) & data(48) & data(16) &

.

data(49) & data(17) & data(57) & data(25);

end;

The f function is the main data transform, which is applied 16 times to the rightmost half, a 32-bit slice, of the data path. It takes as its second argument a 48-bit subkey generated by the key_compress function.

function f(data : vec32; subkey : vec48) return vec32 is

begin

−−moods inline

return permute(substitute(expand(data) xor

subkey));

end;

The function first takes the 32-bit slice of the datapath and expands it into 48 bits using the expand function. The expand function is again just a rearrangement of bits; input bits are replicated in a special pattern to expand the 32-bit input to the 48-bit output.

function expand(data : vec32) return vec48 is

begin

−−moods inline

return

data(32) & data(1) & data(2) &

.

data(31) & data(32) & data(1);

end;

This expanded word is then exclusive-ORed with the subkey and fed into a substitute block. This substitutes a different 4-bit pattern for each 6-bit slice of the input pattern (remember that the original input has been expanded from 32 bits to 48 bits, so there are eight substitutions in all). The substitution also has the effect of reducing the output back to 32 bits again. The

substitute algorithm first splits the input 48 bits into eight 6-bit slices. Each slice is then used to lookup a substitution pattern for that 6-bit input. This structure is known as the S-block. In the initial implementation, a single ROM is used to store all the substitution patterns. The substitution combines a block index with the input data to form an address, which is then used to lookup the substitution value in the S-block ROM. This address calculation is encapsulated in the smap function.

function smap(index : vec3; data : vec6) return vec4 is

−−moods inline

type S_block_type is

array(0 to 511) of natural range 0 to 15;

constant S_block : S_block_type :=

−−moods ROM

(

14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,

.

2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11

);

begin

return

vec4(to_unsigned(S_block(to_integer(unsigned(

index & data(1) & data(6) & data(2 to 5)))), 4));

end;

The eight substitutions are carried out by the eight calls to smap in the substitute function.

function substitute(data : vec48) return vec32 is

−−moods inline

begin

return

smap("000",data(1 to 6)) &

.

smap("111",data(43 to 48));

end;

The final stage of the datapath transform is the permute function, which is another bit-swapping routine:

function permute (data : in vec32) return vec32 is

−−moods inline

begin

return

data(16) & data(7) & data(20) & data(21) &

.

data(22) & data(11) & data(4) & data(25);

end;

These functions define the whole of the datapath part of the algorithm.

Key Transformations

The encryption key also needs to be transformed a number of times—specifically, before each data transformation, the key is rotated and then a smaller subkey is extracted by selecting 48 of the 56 bits of the key. The rotation is the most complicated part of the key transformation. The 56-bit key is split into two halves and each half rotated by 0, 1, or 2 bits depending on which round of the DES algorithm is being implemented. The direction of the rotation is to the left during encryption and to the right during decryption. The algorithm is split into two functions: do_rotate which, as the name suggests, does the rotation, and key_rotate which calls do_rotate twice, once for each half of the key. The do_rotate function uses a ROM to store the rotate distances for each round, numbered from 0 to 15:

function do_rotate

−−moods inline

(key : in vec28;

round : natural range 0 to 15;

encrypt : std_logic)

return vec28 is

type distance_type is

array (natural range 0 to 15) of integer range 0 to 2;

constant encrypt_shift_distance : distance_type :=

−−moods ROM

(1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1);

constant decrypt_shift_distance : distance_type :=

−−moods ROM

(0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1);

variable result : vec28;

begin

if encrypt = 1 then

result :=

vec28(unsigned(key) rol

encrypt_shift_distance(round));

else

result :=

vec28(unsigned(key) ror

decrypt_shift_distance(round));

end if;

return result;

end;

The key_rotate function simply calls the previous function twice:

function key_rotate

−−moods inline

(key : in vec56;

round : natural range 0 to 15;

encrypt : std_logic)

return vec56 is

begin

return do_rotate(key(1 to 28),round,encrypt) &

do_rotate(key(29 to 56),round,encrypt);

end;

Finally, the key compression function key_compress selects 48 of the 56 bits to pass to the S-block algorithm.

function key_compress(key : in vec56) return vec48 is

begin

−−moods inline

return

key(14) & key(17) & key(11) & key(24) &

.

key(50) & key(36) & key(29) & key(32);

end;

  • XC3090-100PG175M

    Manufacturer:Xilinx

  • FPGA XC3000 Family 6K Gates 320 Cells 100MHz 5V 175-Pin CPGA
  • Product Categories:

    Lifecycle:Obsolete -

    RoHS: No RoHS

  • XC2V2000-4BFG957C

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 2M Gates 24192 Cells 650MHz 0.15um Technology 1.5V 957-Pin FCBGA
  • Product Categories:

    Lifecycle:Obsolete -

    RoHS:

  • XC2V2000-4BGG575I

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 2M Gates 24192 Cells 650MHz 0.15um Technology 1.5V 575-Pin BGA
  • Product Categories: FPGAs (Field Programmable Gate Array)

    Lifecycle:Obsolete -

    RoHS:

  • XC2V2000-4FG676C

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 2M Gates 24192 Cells 650MHz 0.15um Technology 1.5V 676-Pin FBGA
  • Product Categories:

    Lifecycle:Obsolete -

    RoHS:

  • XC4028XLA-08BG256C

    Manufacturer:Xilinx

  • FPGA XC4000XLA Family 28K Gates 2432 Cells 263MHz 0.35um Technology 3.3V 256-Pin BGA
  • Product Categories:

    Lifecycle:Obsolete -

    RoHS: No RoHS

Need Help?

Support

If you have any questions about the product and related issues, Please contact us.