diff options
author | Joachim StroĢmbergson <joachim@secworks.se> | 2018-05-21 15:35:55 +0200 |
---|---|---|
committer | Joachim StroĢmbergson <joachim@secworks.se> | 2018-05-21 15:35:55 +0200 |
commit | e389761d61a5616add66ce2dacd0f13feb68d1e1 (patch) | |
tree | 2fc3494df24eef6a05d51a478257eebf53760bb6 /src/rtl/aes_core.v |
Adding inital version of AES core optimized for performance.
Diffstat (limited to 'src/rtl/aes_core.v')
-rw-r--r-- | src/rtl/aes_core.v | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/rtl/aes_core.v b/src/rtl/aes_core.v new file mode 100644 index 0000000..5196a1f --- /dev/null +++ b/src/rtl/aes_core.v @@ -0,0 +1,339 @@ +//====================================================================== +// +// aes.core.v +// ---------- +// The AES core. This core supports key size of 128, and 256 bits. +// Most of the functionality is within the submodules. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2014, NORDUnet A/S +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - 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. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// 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 +// HOLDER 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_core( + input wire clk, + input wire reset_n, + + input wire encdec, + input wire init, + input wire next, + output wire ready, + + input wire [255 : 0] key, + input wire keylen, + + input wire [127 : 0] block, + output wire [127 : 0] result, + output wire result_valid + ); + + + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam CTRL_IDLE = 2'h0; + localparam CTRL_INIT = 2'h1; + localparam CTRL_NEXT = 2'h2; + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [1 : 0] aes_core_ctrl_reg; + reg [1 : 0] aes_core_ctrl_new; + reg aes_core_ctrl_we; + + reg result_valid_reg; + reg result_valid_new; + reg result_valid_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg init_state; + + wire [127 : 0] round_key; + wire key_ready; + + reg enc_next; + wire [3 : 0] enc_round_nr; + wire [127 : 0] enc_new_block; + wire enc_ready; + wire [31 : 0] enc_sboxw; + + reg dec_next; + wire [3 : 0] dec_round_nr; + wire [127 : 0] dec_new_block; + wire dec_ready; + + reg [127 : 0] muxed_new_block; + reg [3 : 0] muxed_round_nr; + reg muxed_ready; + + wire [31 : 0] keymem_sboxw; + + reg [31 : 0] muxed_sboxw; + wire [31 : 0] new_sboxw; + + + //---------------------------------------------------------------- + // Instantiations. + //---------------------------------------------------------------- + aes_encipher_block enc_block( + .clk(clk), + .reset_n(reset_n), + + .next(enc_next), + + .keylen(keylen), + .round(enc_round_nr), + .round_key(round_key), + + .sboxw(enc_sboxw), + .new_sboxw(new_sboxw), + + .block(block), + .new_block(enc_new_block), + .ready(enc_ready) + ); + + + aes_decipher_block dec_block( + .clk(clk), + .reset_n(reset_n), + + .next(dec_next), + + .keylen(keylen), + .round(dec_round_nr), + .round_key(round_key), + + .block(block), + .new_block(dec_new_block), + .ready(dec_ready) + ); + + + aes_key_mem keymem( + .clk(clk), + .reset_n(reset_n), + + .key(key), + .keylen(keylen), + .init(init), + + .round(muxed_round_nr), + .round_key(round_key), + .ready(key_ready), + + .sboxw(keymem_sboxw), + .new_sboxw(new_sboxw) + ); + + + aes_sbox sbox_inst(.sboxw(muxed_sboxw), .new_sboxw(new_sboxw)); + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign ready = ready_reg; + assign result = muxed_new_block; + assign result_valid = result_valid_reg; + + + //---------------------------------------------------------------- + // 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 + result_valid_reg <= 1'b0; + ready_reg <= 1'b1; + aes_core_ctrl_reg <= CTRL_IDLE; + end + else + begin + if (result_valid_we) + result_valid_reg <= result_valid_new; + + if (ready_we) + ready_reg <= ready_new; + + if (aes_core_ctrl_we) + aes_core_ctrl_reg <= aes_core_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // sbox_mux + // + // Controls which of the encipher datapath or the key memory + // that gets access to the sbox. + //---------------------------------------------------------------- + always @* + begin : sbox_mux + if (init_state) + begin + muxed_sboxw = keymem_sboxw; + end + else + begin + muxed_sboxw = enc_sboxw; + end + end // sbox_mux + + + //---------------------------------------------------------------- + // encdex_mux + // + // Controls which of the datapaths that get the next signal, have + // access to the memory as well as the block processing result. + //---------------------------------------------------------------- + always @* + begin : encdec_mux + enc_next = 1'b0; + dec_next = 1'b0; + + if (encdec) + begin + // Encipher operations + enc_next = next; + muxed_round_nr = enc_round_nr; + muxed_new_block = enc_new_block; + muxed_ready = enc_ready; + end + else + begin + // Decipher operations + dec_next = next; + muxed_round_nr = dec_round_nr; + muxed_new_block = dec_new_block; + muxed_ready = dec_ready; + end + end // encdec_mux + + + //---------------------------------------------------------------- + // aes_core_ctrl + // + // Control FSM for aes core. Basically tracks if we are in + // key init, encipher or decipher modes and connects the + // different submodules to shared resources and interface ports. + //---------------------------------------------------------------- + always @* + begin : aes_core_ctrl + init_state = 1'b0; + ready_new = 1'b0; + ready_we = 1'b0; + result_valid_new = 1'b0; + result_valid_we = 1'b0; + aes_core_ctrl_new = CTRL_IDLE; + aes_core_ctrl_we = 1'b0; + + case (aes_core_ctrl_reg) + CTRL_IDLE: + begin + if (init) + begin + init_state = 1'b1; + ready_new = 1'b0; + ready_we = 1'b1; + result_valid_new = 1'b0; + result_valid_we = 1'b1; + aes_core_ctrl_new = CTRL_INIT; + aes_core_ctrl_we = 1'b1; + end + else if (next) + begin + init_state = 1'b0; + ready_new = 1'b0; + ready_we = 1'b1; + result_valid_new = 1'b0; + result_valid_we = 1'b1; + aes_core_ctrl_new = CTRL_NEXT; + aes_core_ctrl_we = 1'b1; + end + end + + CTRL_INIT: + begin + init_state = 1'b1; + + if (key_ready) + begin + ready_new = 1'b1; + ready_we = 1'b1; + aes_core_ctrl_new = CTRL_IDLE; + aes_core_ctrl_we = 1'b1; + end + end + + CTRL_NEXT: + begin + init_state = 1'b0; + + if (muxed_ready) + begin + ready_new = 1'b1; + ready_we = 1'b1; + result_valid_new = 1'b1; + result_valid_we = 1'b1; + aes_core_ctrl_new = CTRL_IDLE; + aes_core_ctrl_we = 1'b1; + end + end + + default: + begin + + end + endcase // case (aes_core_ctrl_reg) + + end // aes_core_ctrl +endmodule // aes_core + +//====================================================================== +// EOF aes_core.v +//====================================================================== |