//========
module DES (clk, reset, stopped, indata, result, keyresult);
//========
//
//    DES encryption
//
//    uses an LFSR to run through keys
//    each key value is used to encrypt a 64bit zero value
//
//    this is a pipelined design, after 16 iterations results
//    will appear, one per clk
//

input    clk;
input    reset;
input    stopped;
input    [63:0] indata;
output   [63:0] result;
output   [55:0] keyresult;

wire     clk;
wire     reset;
wire     stopped;

// the input data has to be put through an initial permutation
// before it can be used

wire [63:0] indata;

wire [31:0] L00 = {  indata[ 6], indata[14], indata[22], indata[30],
                     indata[38], indata[46], indata[54], indata[62],
                     indata[ 4], indata[12], indata[20], indata[28],
                     indata[36], indata[44], indata[52], indata[60],
                     indata[ 2], indata[10], indata[18], indata[26],
                     indata[34], indata[42], indata[50], indata[58],
                     indata[ 0], indata[ 8], indata[16], indata[24],
                     indata[32], indata[40], indata[48], indata[56]
                  };

wire [31:0] R00 = {  indata[ 7], indata[15], indata[23], indata[31],
                     indata[39], indata[47], indata[55], indata[63],
                     indata[ 5], indata[13], indata[21], indata[29],
                     indata[37], indata[45], indata[53], indata[61],
                     indata[ 3], indata[11], indata[19], indata[27],
                     indata[35], indata[43], indata[51], indata[59],
                     indata[ 1], indata[ 9], indata[17], indata[25],
                     indata[33], indata[41], indata[49], indata[57]
                  };

// the keys are generated by a 56 bit LFSR. This is extended by 16 bits
// the right to allow "old" values to be known within this DES module
// and by three further bits for the benefit of the external pipeline

wire [74:0] keyval;

LFSR56 counter(clk, reset, stopped, keyval);

// the pipeline results are not valid until we are about to see the 16th clock
// [remember that the results are available on the wire before the clock occurs]
// and the 16th extension bit of keyval (bit3) will be '0' until that happens
// so we test bit4 ... because we need the value that's valid at the clock!

reg  pipeActive;

always @(posedge clk)
begin
   if (reset)
      pipeActive <= 0;
   else
      pipeActive <= pipeActive | keyval[4];
end

// round 01 - inputs are: L00, R00
//            we use keyval shifted by 0 bits (ie bits 74-19)
//            this is permuted into k01
//            we create f01, a non-linear transform of R00 & k01
//            we then create L01 and R01 for the next stage

wire [47:0] k01;
k_select_01 keysel01(keyval[74:19], k01);

wire [31:0] f01;
f_function  fun01(R00, k01, f01);

reg  [31:0] L01;
reg  [31:0] R01;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R01 <= L00 ^ f01;
      L01 <= R00;
   end
end

// round 02 - inputs are: L01, R01
//            we use keyval shifted by 1 bits (ie bits 73-18)
//            this is permuted into k02
//            we create f02, a non-linear transform of R01 & k02
//            we then create L02 and R02 for the next stage

wire [47:0] k02;
k_select_02 keysel02(keyval[73:18], k02);

wire [31:0] f02;
f_function  fun02(R01, k02, f02);

reg  [31:0] L02;
reg  [31:0] R02;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R02 <= L01 ^ f02;
      L02 <= R01;
   end
end

// round 03 - inputs are: L02, R02
//            we use keyval shifted by 2 bits (ie bits 72-17)
//            this is permuted into k03
//            we create f03, a non-linear transform of R02 & k03
//            we then create L03 and R03 for the next stage

wire [47:0] k03;
k_select_03 keysel03(keyval[72:17], k03);

wire [31:0] f03;
f_function  fun03(R02, k03, f03);

reg  [31:0] L03;
reg  [31:0] R03;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R03 <= L02 ^ f03;
      L03 <= R02;
   end
end

// round 04 - inputs are: L03, R03
//            we use keyval shifted by 3 bits (ie bits 71-16)
//            this is permuted into k04
//            we create f04, a non-linear transform of R03 & k04
//            we then create L04 and R04 for the next stage

wire [47:0] k04;
k_select_04 keysel04(keyval[71:16], k04);

wire [31:0] f04;
f_function  fun04(R03, k04, f04);

reg  [31:0] L04;
reg  [31:0] R04;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R04 <= L03 ^ f04;
      L04 <= R03;
   end
end

// round 05 - inputs are: L04, R04
//            we use keyval shifted by 4 bits (ie bits 70-15)
//            this is permuted into k05
//            we create f05, a non-linear transform of R04 & k05
//            we then create L05 and R05 for the next stage

wire [47:0] k05;
k_select_05 keysel05(keyval[70:15], k05);

wire [31:0] f05;
f_function  fun05(R04, k05, f05);

reg  [31:0] L05;
reg  [31:0] R05;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R05 <= L04 ^ f05;
      L05 <= R04;
   end
end

// round 06 - inputs are: L05, R05
//            we use keyval shifted by 5 bits (ie bits 69-14)
//            this is permuted into k06
//            we create f06, a non-linear transform of R05 & k06
//            we then create L06 and R06 for the next stage

wire [47:0] k06;
k_select_06 keysel06(keyval[69:14], k06);

wire [31:0] f06;
f_function  fun06(R05, k06, f06);

reg  [31:0] L06;
reg  [31:0] R06;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R06 <= L05 ^ f06;
      L06 <= R05;
   end
end

// round 07 - inputs are: L06, R06
//            we use keyval shifted by 6 bits (ie bits 68-13)
//            this is permuted into k07
//            we create f07, a non-linear transform of R06 & k07
//            we then create L07 and R07 for the next stage

wire [47:0] k07;
k_select_07 keysel07(keyval[68:13], k07);

wire [31:0] f07;
f_function  fun07(R06, k07, f07);

reg  [31:0] L07;
reg  [31:0] R07;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R07 <= L06 ^ f07;
      L07 <= R06;
   end
end

// round 08 - inputs are: L07, R07
//            we use keyval shifted by 7 bits (ie bits 67-12)
//            this is permuted into k08
//            we create f08, a non-linear transform of R07 & k08
//            we then create L08 and R08 for the next stage

wire [47:0] k08;
k_select_08 keysel08(keyval[67:12], k08);

wire [31:0] f08;
f_function  fun08(R07, k08, f08);

reg  [31:0] L08;
reg  [31:0] R08;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R08 <= L07 ^ f08;
      L08 <= R07;
   end
end

// round 09 - inputs are: L08, R08
//            we use keyval shifted by 8 bits (ie bits 66-11)
//            this is permuted into k09
//            we create f09, a non-linear transform of R08 & k09
//            we then create L09 and R09 for the next stage

wire [47:0] k09;
k_select_09 keysel09(keyval[66:11], k09);

wire [31:0] f09;
f_function  fun09(R08, k09, f09);

reg  [31:0] L09;
reg  [31:0] R09;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R09 <= L08 ^ f09;
      L09 <= R08;
   end
end

// round 10 - inputs are: L09, R09
//            we use keyval shifted by 9 bits (ie bits 65-10)
//            this is permuted into k10
//            we create f10, a non-linear transform of R09 & k10
//            we then create L10 and R10 for the next stage

wire [47:0] k10;
k_select_10 keysel10(keyval[65:10], k10);

wire [31:0] f10;
f_function  fun10(R09, k10, f10);

reg  [31:0] L10;
reg  [31:0] R10;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R10 <= L09 ^ f10;
      L10 <= R09;
   end
end

// round 11 - inputs are: L10, R10
//            we use keyval shifted by 10 bits (ie bits 64-9)
//            this is permuted into k11
//            we create f11, a non-linear transform of R10 & k11
//            we then create L11 and R11 for the next stage

wire [47:0] k11;
k_select_11 keysel11(keyval[64:9], k11);

wire [31:0] f11;
f_function  fun11(R10, k11, f11);

reg  [31:0] L11;
reg  [31:0] R11;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R11 <= L10 ^ f11;
      L11 <= R10;
   end
end

// round 12 - inputs are: L11, R11
//            we use keyval shifted by 11 bits (ie bits 63-8)
//            this is permuted into k12
//            we create f12, a non-linear transform of R11 & k12
//            we then create L12 and R12 for the next stage

wire [47:0] k12;
k_select_12 keysel12(keyval[63:8], k12);

wire [31:0] f12;
f_function  fun12(R11, k12, f12);

reg  [31:0] L12;
reg  [31:0] R12;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R12 <= L11 ^ f12;
      L12 <= R11;
   end
end

// round 13 - inputs are: L12, R12
//            we use keyval shifted by 12 bits (ie bits 62-7)
//            this is permuted into k13
//            we create f13, a non-linear transform of R12 & k13
//            we then create L13 and R13 for the next stage

wire [47:0] k13;
k_select_13 keysel13(keyval[62:7], k13);

wire [31:0] f13;
f_function  fun13(R12, k13, f13);

reg  [31:0] L13;
reg  [31:0] R13;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R13 <= L12 ^ f13;
      L13 <= R12;
   end
end

// round 14 - inputs are: L13, R13
//            we use keyval shifted by 13 bits (ie bits 61-6)
//            this is permuted into k14
//            we create f14, a non-linear transform of R13 & k14
//            we then create L14 and R14 for the next stage

wire [47:0] k14;
k_select_14 keysel14(keyval[61:6], k14);

wire [31:0] f14;
f_function  fun14(R13, k14, f14);

reg  [31:0] L14;
reg  [31:0] R14;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R14 <= L13 ^ f14;
      L14 <= R13;
   end
end

// round 15 - inputs are: L14, R14
//            we use keyval shifted by 14 bits (ie bits 60-5)
//            this is permuted into k15
//            we create f15, a non-linear transform of R14 & k15
//            we then create L15 and R15 for the next stage

wire [47:0] k15;
k_select_15 keysel15(keyval[60:5], k15);

wire [31:0] f15;
f_function  fun15(R14, k15, f15);

reg  [31:0] L15;
reg  [31:0] R15;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R15 <= L14 ^ f15;
      L15 <= R14;
   end
end

// round 16 - inputs are: L15, R15
//            we use keyval shifted by 15 bits (ie bits 59-4)
//            this is permuted into k16
//            we create f16, a non-linear transform of R15 & k16
//            we then create L16 and R16 for the next stage

wire [47:0] k16;
k_select_16 keysel16(keyval[59:4], k16);

wire [31:0] f16;
f_function  fun16(R15, k16, f16);

reg  [31:0] L16;
reg  [31:0] R16;

always @(posedge clk)
begin
   if (!stopped)
   begin
      R16 <= L15 ^ f16;
      L16 <= R15;
   end
end

// perform the final permutation
//
// NB: FIPS 46 expresses this as 1..64
//     here we express it as R16[31..0] and L16[31..0]
//     (noting that L16 is on the right! of the "pre-output" block

wire [63:0] result = (pipeActive) ? {
         L16[24], R16[24], L16[16], R16[16], L16[ 8], R16[ 8], L16[ 0], R16[ 0],
         L16[25], R16[25], L16[17], R16[17], L16[ 9], R16[ 9], L16[ 1], R16[ 1], 
         L16[26], R16[26], L16[18], R16[18], L16[10], R16[10], L16[ 2], R16[ 2], 
         L16[27], R16[27], L16[19], R16[19], L16[11], R16[11], L16[ 3], R16[ 3], 
         L16[28], R16[28], L16[20], R16[20], L16[12], R16[12], L16[ 4], R16[ 4], 
         L16[29], R16[29], L16[21], R16[21], L16[13], R16[13], L16[ 5], R16[ 5],
         L16[30], R16[30], L16[22], R16[22], L16[14], R16[14], L16[ 6], R16[ 6], 
         L16[31], R16[31], L16[23], R16[23], L16[15], R16[15], L16[ 7], R16[ 7]
                                    } : 0;

// note that we pass out the result before the next clock (because it is a
// continuous assignment to a wire, but we put the key into the keyresult
// register AFTER the next clock ... the external logic allows for the
// relevant delay (and indeed allows for the three clock delay that we
// have introduced by having the extra extension of the LFSR register)

reg [55:0] keyresult;

always @(posedge clk)
begin
      keyresult <= keyval[55:0];
end

endmodule
