OpenCores
URL https://opencores.org/ocsvn/aes_highthroughput_lowarea/aes_highthroughput_lowarea/trunk

Subversion Repositories aes_highthroughput_lowarea

[/] [aes_highthroughput_lowarea/] [trunk/] [verilog/] [rtl/] [key_exp.v] - Rev 5

Go to most recent revision | Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  Key expansion module                                        ////
////                                                              ////
////  Description:                                                ////
////  Used to expand the key based on key expansion procudure     ////
////                                                              ////
////  To Do:                                                      ////
////   - done                                                     ////
////                                                              ////
////  Author(s):                                                  ////
////      - Luo Dongjun,   dongjun_luo@hotmail.com                ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
module key_exp (
   clk,
   reset_n,
   key_in,
   key_mode,
   key_start,
   wr,
   wr_addr,
   wr_data,
   key_ready
);
 
input             clk;
input             reset_n;
input   [255:0]   key_in;   // initial key value
input   [1:0]     key_mode; // 0:128, 1:192, 2:256
input             key_start;// start key expansion
output            wr;       // key expansion ram interface
output  [4:0]     wr_addr;
output  [63:0]    wr_data;
output            key_ready;
 
reg [31:0]  rcon;
reg         rcon_is_1b;
reg [1:0]   state,nstate,pstate;
reg [3:0]   round;
reg         sbox_in_valid;
reg [31:0]  sbox_in;
reg [4:0]   valid;
wire        sbox_out_valid;
wire [31:0] sbox_out;
wire [31:0] w0_next,w1_next,w2_next,w3_next,w4_next1,w5_next1,w6_next,w7_next;
wire [31:0] w4_next2,w5_next2;
reg [31:0]  w0,w1,w2,w3,w4,w5,w6,w7;
wire        wr1,wr2,wr3,init_wr1,init_wr2,init_wr3,init_wr4;
reg         wr;
wire [63:0] wr_data1,wr_data2,wr_data3;
reg         key_start_L,key_start_L2,key_start_L3;
reg         wr_256;
reg [4:0]   wr_addr;
reg [63:0]  wr_data;
reg         key_ready;
wire   [3:0] max_round_p1;
 
parameter   IDLE       = 2'b00,
            START      = 2'b01,
            GENKEY1    = 2'b10,
            GENKEY_256 = 2'b11;
 
assign max_round_p1[3:0] = (key_mode == 2'b00) ? 4'd11 : (key_mode == 2'b01 ? 4'd13 : 4'd15);
 
// rcon generation
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
   begin
      rcon[31:0] <= 32'h01000000;
      rcon_is_1b <= 1'b0;
   end
   else if (key_start)
   begin
      rcon[31:0] <= 32'h01000000;
      rcon_is_1b <= 1'b0;
   end
   else if (sbox_out_valid && (state[1:0] == GENKEY1))
   begin
      if (rcon[31])
      begin
         rcon[31:0] <= 32'h1b000000;
         rcon_is_1b <= 1'b1;
      end
      else if (rcon_is_1b)
      begin
         rcon[31:0] <= 32'h36000000;
         rcon_is_1b <= 1'b1;
      end
      else
         rcon[31:0] <= {rcon[30:0],1'b0};
   end
end
 
/*****************************************************************************/
// State machine for Key expansion
//
//
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)   
   begin
      state[1:0]  <= IDLE;
      pstate[1:0] <= IDLE;
   end
   else
   begin
      state[1:0]  <= nstate[1:0];
      pstate[1:0] <= state[1:0];
   end
end
 
always @ (*)
begin
   nstate[1:0] = state[1:0];
   case (state[1:0])
      IDLE: 
         if (key_start) nstate[1:0] = START;
      START:
      begin
         nstate[1:0] = GENKEY1;
      end
      GENKEY1:
      begin
         if (sbox_out_valid)
         begin
            if (key_mode == 2'b00) //128 bit mode 4 x 10 + 4
               if (round[3:0] == 4'd10)   nstate[1:0] = IDLE;
               else                       nstate[1:0] = START;
            else if (key_mode == 2'b01) // 192 bit mode 6 + 6 x 8 = 54 > 52
               if (round[3:0] == 4'd8) nstate[1:0] = IDLE;
               else                    nstate[1:0] = START;
            else if (round[3:0] == 4'd7)// 256 bit mode 8 + 8 x 7 = 64 > 60
               nstate[1:0] = IDLE;
            else
               nstate[1:0] = GENKEY_256;
         end
      end
      GENKEY_256:
      begin
         if (sbox_out_valid)
            nstate[1:0] = START;
      end
   endcase
end
 
// round counter: 10/12/14
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
      round[3:0] <= 1'b0;
   else if (nstate[1:0] == IDLE)
      round[3:0] <= 4'b0;
   else if (state[1:0] == START)
      round[3:0] <= round[3:0] + 1'b1;
end
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
   begin
      sbox_in_valid <= 1'b0;
      sbox_in[31:0] <= 32'b0;
   end
   else if (state[1:0] == START) // rotword
   begin
      sbox_in_valid <= 1'b1;
      if (key_mode == 2'b00) //128
         sbox_in[31:0] <= {w3[23:0],w3[31:24]};
      else if (key_mode == 2'b01) //192
         sbox_in[31:0] <= {w5[23:0],w5[31:24]};
      else //256
         sbox_in[31:0] <= {w7[23:0],w7[31:24]};
   end
   else if ((state[1:0] == GENKEY_256) && (pstate[1:0] ==GENKEY1))
   begin
      sbox_in_valid <= 1'b1;
      sbox_in[31:0] <= w3[31:0];
   end
   else
      sbox_in_valid <= 1'b0;
end
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
      valid[4:0] <= 5'b0;
   else
      valid[4:0] <= {valid[3:0],sbox_in_valid};
end
assign sbox_out_valid = valid[1];
 
sbox u_0(.clk(clk),.reset_n(reset_n),.enable(1'b1),.din(sbox_in[7:0]),.ende(1'b0),.en_dout(sbox_out[7:0]),.de_dout());
sbox u_1(.clk(clk),.reset_n(reset_n),.enable(1'b1),.din(sbox_in[15:8]),.ende(1'b0),.en_dout(sbox_out[15:8]),.de_dout());
sbox u_2(.clk(clk),.reset_n(reset_n),.enable(1'b1),.din(sbox_in[23:16]),.ende(1'b0),.en_dout(sbox_out[23:16]),.de_dout());
sbox u_3(.clk(clk),.reset_n(reset_n),.enable(1'b1),.din(sbox_in[31:24]),.ende(1'b0),.en_dout(sbox_out[31:24]),.de_dout());
 
/*****************************************************************************/
// key expansion calculation
//
//
assign w0_next[31:0] = sbox_out[31:0]^rcon[31:0]^w0[31:0];
assign w1_next[31:0] = w0_next[31:0]^w1[31:0];
assign w2_next[31:0] = w1_next[31:0]^w2[31:0];
assign w3_next[31:0] = w2_next[31:0]^w3[31:0];
assign w4_next1[31:0] = w3_next[31:0] ^ w4[31:0];
assign w5_next1[31:0] = w4_next1[31:0]^w5[31:0];
assign w4_next2[31:0] = sbox_out[31:0] ^ w4[31:0];
assign w5_next2[31:0] = w4_next2[31:0]^w5[31:0];
assign w6_next[31:0] = w5_next2[31:0]^w6[31:0];
assign w7_next[31:0] = w6_next[31:0]^w7[31:0];
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
   begin
      {w0[31:0],w1[31:0],w2[31:0],w3[31:0],w4[31:0],w5[31:0],w6[31:0],w7[31:0]} <= 256'b0;
   end
   else if (key_start)
   begin
      {w0[31:0],w1[31:0],w2[31:0],w3[31:0],w4[31:0],w5[31:0],w6[31:0],w7[31:0]} <= key_in[255:0];
   end
   else if ((key_mode[1:0] == 2'b10) && sbox_out_valid)
   begin
      if (state[1:0] == GENKEY1)
      begin
         w0[31:0] <= w0_next[31:0];
         w1[31:0] <= w1_next[31:0];
         w2[31:0] <= w2_next[31:0];
         w3[31:0] <= w3_next[31:0];
      end
      else
      begin
         w4[31:0] <= w4_next2[31:0];
         w5[31:0] <= w5_next2[31:0];
         w6[31:0] <= w6_next[31:0];
         w7[31:0] <= w7_next[31:0];
      end
   end
   else if (sbox_out_valid)
   begin
      w0[31:0] <= w0_next[31:0];
      w1[31:0] <= w1_next[31:0];
      w2[31:0] <= w2_next[31:0];
      w3[31:0] <= w3_next[31:0];
      if (key_mode[1:0] == 2'b01)
      begin
         w4[31:0] <= w4_next1[31:0];
         w5[31:0] <= w5_next1[31:0];
      end
   end
end
 
// write to external ram
assign init_wr1 = key_start;
assign init_wr2 = key_start_L;
assign init_wr3 = key_start_L2 && (key_mode[1:0] != 2'b00);
assign init_wr4 = key_start_L3 && (key_mode[1:0] == 2'b10);
assign wr1 = valid[2];
assign wr2 = valid[3];
assign wr3 = valid[4] && (key_mode[1:0] == 2'b01) && (state[1:0] != IDLE); // remove the last write 
 
assign wr_data1[63:0] = wr_256 ?{w4[31:0],w5[31:0]} : {w0[31:0],w1[31:0]};
assign wr_data2[63:0] = wr_256 ?{w6[31:0],w7[31:0]} : {w2[31:0],w3[31:0]};
assign wr_data3[63:0] = {w4[31:0],w5[31:0]};
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
      wr_256 <= 1'b0;
   else if (key_start)
      wr_256 <= 1'b0;
   else if (sbox_out_valid && (state[1:0] == GENKEY_256))
      wr_256 <= 1'b1;
   else if (sbox_out_valid)
      wr_256 <= 1'b0;
end
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
      {key_start_L3,key_start_L2,key_start_L} <= 3'b0;
   else
      {key_start_L3,key_start_L2,key_start_L} <= {key_start_L2,key_start_L,key_start};
end
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
      wr <= 1'b0;
   else 
      wr <= wr1 || wr2 || wr3 || init_wr1 || init_wr2 || init_wr3 || init_wr4;
end
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
   begin
      wr_data[63:0] <= 64'b0;
   end
   else
   begin
      if (init_wr1)
         wr_data[63:0] <= key_in[255:192];
      else if (init_wr2)
         wr_data[63:0] <= key_in[191:128];
      else if (init_wr3)
         wr_data[63:0] <= key_in[127:64];
      else if (init_wr4)
         wr_data[63:0] <= key_in[63:0];
      else if (wr1)
         wr_data[63:0] <= wr_data1[63:0];
      else if (wr2)
         wr_data[63:0] <= wr_data2[63:0];
      else if (wr3)
         wr_data[63:0] <= wr_data3[63:0];
   end
end
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
      wr_addr[4:0] <= 5'b0;
   else if (key_start)
      wr_addr[4:0] <= 5'd0;
   else if (wr)
      wr_addr[4:0] <= wr_addr[4:0] + 1'b1;
end
 
always @ (posedge clk or negedge reset_n)
begin
   if (!reset_n)
      key_ready <= 1'b0;
   else if (key_start)
      key_ready <= 1'b0;
   else if (wr_addr[4:1] == max_round_p1[3:0])
      key_ready <= 1'b1;
end
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.