From 1ecc3b5ccceda62110c20c55683167ce9ab3cf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Thu, 27 Nov 2014 15:48:42 +0100 Subject: Adding RTL source files for the AES core. --- src/rtl/aes_key_mem.v | 479 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 479 insertions(+) create mode 100644 src/rtl/aes_key_mem.v (limited to 'src/rtl/aes_key_mem.v') diff --git a/src/rtl/aes_key_mem.v b/src/rtl/aes_key_mem.v new file mode 100644 index 0000000..e681c93 --- /dev/null +++ b/src/rtl/aes_key_mem.v @@ -0,0 +1,479 @@ +//====================================================================== +// +// aes_key_mem.v +// ------------- +// The AES key memort including round key generator. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2014, SUNET +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module aes_key_mem( + input wire clk, + input wire reset_n, + + input wire [255 : 0] key, + input wire keylen, + input wire init, + + input wire [3 : 0] round, + output wire [127 : 0] round_key, + output wire ready, + + + output wire [31 : 0] sboxw, + input wire [31 : 0] new_sboxw + ); + + + //---------------------------------------------------------------- + // Parameters. + //---------------------------------------------------------------- + parameter AES_128_BIT_KEY = 1'h0; + parameter AES_256_BIT_KEY = 1'h1; + + parameter AES_128_NUM_ROUNDS = 4'ha; + parameter AES_256_NUM_ROUNDS = 4'he; + + parameter CTRL_IDLE = 3'h0; + parameter CTRL_INIT = 3'h1; + parameter CTRL_GENERATE = 3'h2; + parameter CTRL_DONE = 3'h3; + + + //---------------------------------------------------------------- + // Registers. + //---------------------------------------------------------------- + reg [127 : 0] key_mem [0 : 14]; + reg [127 : 0] key_mem_new; + reg key_mem_we; + + reg [127 : 0] prev_key0_reg; + reg [127 : 0] prev_key0_new; + reg prev_key0_we; + + reg [127 : 0] prev_key1_reg; + reg [127 : 0] prev_key1_new; + reg prev_key1_we; + + reg [3 : 0] round_ctr_reg; + reg [3 : 0] round_ctr_new; + reg round_ctr_rst; + reg round_ctr_inc; + reg round_ctr_we; + + reg [2 : 0] key_mem_ctrl_reg; + reg [2 : 0] key_mem_ctrl_new; + reg key_mem_ctrl_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [7 : 0] rcon_reg; + reg [7 : 0] rcon_new; + reg rcon_we; + reg rcon_set; + reg rcon_next; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [31 : 0] tmp_sboxw; + + reg round_key_update; + reg [3 : 0] num_rounds; + + reg [127 : 0] tmp_round_key; + + + //---------------------------------------------------------------- + // Concurrent assignments for ports. + //---------------------------------------------------------------- + assign round_key = tmp_round_key; + assign ready = ready_reg; + assign sboxw = tmp_sboxw; + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin: reg_update + if (!reset_n) + begin + key_mem [0] <= 128'h00000000000000000000000000000000; + key_mem [1] <= 128'h00000000000000000000000000000000; + key_mem [2] <= 128'h00000000000000000000000000000000; + key_mem [3] <= 128'h00000000000000000000000000000000; + key_mem [4] <= 128'h00000000000000000000000000000000; + key_mem [5] <= 128'h00000000000000000000000000000000; + key_mem [6] <= 128'h00000000000000000000000000000000; + key_mem [7] <= 128'h00000000000000000000000000000000; + key_mem [8] <= 128'h00000000000000000000000000000000; + key_mem [9] <= 128'h00000000000000000000000000000000; + key_mem [10] <= 128'h00000000000000000000000000000000; + key_mem [11] <= 128'h00000000000000000000000000000000; + key_mem [12] <= 128'h00000000000000000000000000000000; + key_mem [13] <= 128'h00000000000000000000000000000000; + key_mem [14] <= 128'h00000000000000000000000000000000; + prev_key0_reg <= 128'h00000000000000000000000000000000; + prev_key1_reg <= 128'h00000000000000000000000000000000; + rcon_reg <= 8'h00; + ready_reg <= 0; + round_ctr_reg <= 4'h0; + key_mem_ctrl_reg <= CTRL_IDLE; + end + else + begin + if (round_ctr_we) + begin + round_ctr_reg <= round_ctr_new; + end + + if (ready_we) + begin + ready_reg <= ready_new; + end + + if (rcon_we) + begin + rcon_reg <= rcon_new; + end + + if (key_mem_we) + begin + key_mem[round_ctr_reg] <= key_mem_new; + end + + if (prev_key0_we) + begin + prev_key0_reg <= prev_key0_new; + end + + if (prev_key1_we) + begin + prev_key1_reg <= prev_key1_new; + end + + if (key_mem_ctrl_we) + begin + key_mem_ctrl_reg <= key_mem_ctrl_new; + end + end + end // reg_update + + + //---------------------------------------------------------------- + // key_mem_read + // + // Combinational read port for the key memory. + //---------------------------------------------------------------- + always @* + begin : key_mem_read + tmp_round_key = key_mem[round]; + end // key_mem_read + + + //---------------------------------------------------------------- + // round_key_gen + // + // The round key generator logic for AES-128 and AES-256. + //---------------------------------------------------------------- + always @* + begin: round_key_gen + reg [31 : 0] w0, w1, w2, w3, w4, w5, w6, w7; + reg [31 : 0] k0, k1, k2, k3; + reg [31 : 0] rconw, rotstw, tw, trw; + + // Default assignments. + key_mem_new = 128'h00000000000000000000000000000000; + key_mem_we = 0; + prev_key0_new = 128'h00000000000000000000000000000000; + prev_key0_we = 0; + prev_key1_new = 128'h00000000000000000000000000000000; + prev_key1_we = 0; + + k0 = 32'h00000000; + k1 = 32'h00000000; + k2 = 32'h00000000; + k3 = 32'h00000000; + + rcon_set = 1; + rcon_next = 0; + + // Extract words and calculate intermediate values. + // Perform rotation of sbox word etc. + w0 = prev_key0_reg[127 : 096]; + w1 = prev_key0_reg[095 : 064]; + w2 = prev_key0_reg[063 : 032]; + w3 = prev_key0_reg[031 : 000]; + + w4 = prev_key1_reg[127 : 096]; + w5 = prev_key1_reg[095 : 064]; + w6 = prev_key1_reg[063 : 032]; + w7 = prev_key1_reg[031 : 000]; + + rconw = {rcon_reg, 24'h000000}; + tmp_sboxw = w7; + rotstw = {new_sboxw[23 : 00], new_sboxw[31 : 24]}; + trw = rotstw ^ rconw; + tw = new_sboxw; + + // Generate the specific round keys. + if (round_key_update) + begin + rcon_set = 0; + key_mem_we = 1; + case (keylen) + AES_128_BIT_KEY: + begin + if (round_ctr_reg == 0) + begin + key_mem_new = key[255 : 128]; + prev_key1_new = key[255 : 128]; + prev_key1_we = 1; + rcon_next = 1; + end + else + begin + k0 = w4 ^ trw; + k1 = w5 ^ w4 ^ trw; + k2 = w6 ^ w5 ^ w4 ^ trw; + k3 = w7 ^ w6 ^ w5 ^ w4 ^ trw; + + key_mem_new = {k0, k1, k2, k3}; + prev_key1_new = {k0, k1, k2, k3}; + prev_key1_we = 1; + rcon_next = 1; + end + end + + AES_256_BIT_KEY: + begin + if (round_ctr_reg == 0) + begin + key_mem_new = key[255 : 128]; + prev_key0_new = key[255 : 128]; + prev_key0_we = 1; + end + else if (round_ctr_reg == 1) + begin + key_mem_new = key[127 : 0]; + prev_key1_new = key[127 : 0]; + prev_key1_we = 1; + rcon_next = 1; + end + else + begin + if (round_ctr_reg[0] == 0) + begin + k0 = w0 ^ trw; + k1 = w1 ^ w0 ^ trw; + k2 = w2 ^ w1 ^ w0 ^ trw; + k3 = w3 ^ w2 ^ w1 ^ w0 ^ trw; + end + else + begin + k0 = w0 ^ tw; + k1 = w1 ^ w0 ^ tw; + k2 = w2 ^ w1 ^ w0 ^ tw; + k3 = w3 ^ w2 ^ w1 ^ w0 ^ tw; + rcon_next = 1; + end + + // Store the generated round keys. + key_mem_new = {k0, k1, k2, k3}; + prev_key1_new = {k0, k1, k2, k3}; + prev_key1_we = 1; + prev_key0_new = prev_key1_reg; + prev_key0_we = 1; + end + end + + default: + begin + end + endcase // case (keylen) + end + end // round_key_gen + + + //---------------------------------------------------------------- + // rcon_logic + // + // Caclulates the rcon value for the different key expansion + // iterations. + //---------------------------------------------------------------- + always @* + begin : rcon_logic + reg [7 : 0] tmp_rcon; + rcon_new = 8'h00; + rcon_we = 0; + + tmp_rcon = {rcon_reg[6 : 0], 1'b0} ^ (8'h1b & {8{rcon_reg[7]}}); + + if (rcon_set) + begin + rcon_new = 8'h8d; + rcon_we = 1; + end + + if (rcon_next) + begin + rcon_new = tmp_rcon[7 : 0]; + rcon_we = 1; + end + end + + + //---------------------------------------------------------------- + // round_ctr + // + // The round counter logic with increase and reset. + //---------------------------------------------------------------- + always @* + begin : round_ctr + round_ctr_new = 4'h0; + round_ctr_we = 0; + + if (round_ctr_rst) + begin + round_ctr_new = 4'h0; + round_ctr_we = 1; + end + + else if (round_ctr_inc) + begin + round_ctr_new = round_ctr_reg + 1'b1; + round_ctr_we = 1; + end + end + + + //---------------------------------------------------------------- + // num_rounds_logic + // + // Logic to select the number of rounds to generate keys for + //---------------------------------------------------------------- + always @* + begin : num_rounds_logic + num_rounds = 4'h0; + + case (keylen) + AES_128_BIT_KEY: + begin + num_rounds = AES_128_NUM_ROUNDS; + end + + AES_256_BIT_KEY: + begin + num_rounds = AES_256_NUM_ROUNDS; + end + + default: + begin + end + endcase // case (keylen) + end + + + //---------------------------------------------------------------- + // key_mem_ctrl + // + // + // The FSM that controls the round key generation. + //---------------------------------------------------------------- + always @* + begin: key_mem_ctrl + // Default assignments. + ready_new = 0; + ready_we = 0; + round_key_update = 0; + round_ctr_rst = 0; + round_ctr_inc = 0; + key_mem_ctrl_new = CTRL_IDLE; + key_mem_ctrl_we = 0; + + case(key_mem_ctrl_reg) + CTRL_IDLE: + begin + if (init) + begin + ready_new = 0; + ready_we = 1; + key_mem_ctrl_new = CTRL_INIT; + key_mem_ctrl_we = 1; + end + end + + CTRL_INIT: + begin + round_ctr_rst = 1; + key_mem_ctrl_new = CTRL_GENERATE; + key_mem_ctrl_we = 1; + end + + CTRL_GENERATE: + begin + round_ctr_inc = 1; + round_key_update = 1; + if (round_ctr_reg == num_rounds) + begin + key_mem_ctrl_new = CTRL_DONE; + key_mem_ctrl_we = 1; + end + end + + CTRL_DONE: + begin + ready_new = 1; + ready_we = 1; + key_mem_ctrl_new = CTRL_IDLE; + key_mem_ctrl_we = 1; + end + + default: + begin + end + endcase // case (key_mem_ctrl_reg) + + end // key_mem_ctrl +endmodule // aes_key_mem + +//====================================================================== +// EOF aes_key_mem.v +//====================================================================== -- cgit v1.2.3