blob: 71d2f61aa97f2483e69765a09ad1dc775347e5b8 [file] [log] [blame]
//======================================================================
//
// aes.v
// --------
// Top level wrapper for the AES block cipher core.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2013, 2014 Secworks Sweden AB
// 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(
// Clock and reset.
input wire clk,
input wire reset_n,
// Control.
input wire cs,
input wire we,
// Data ports.
input wire [7 : 0] address,
input wire [31 : 0] write_data,
output wire [31 : 0] read_data
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
localparam ADDR_NAME0 = 8'h00;
localparam ADDR_NAME1 = 8'h01;
localparam ADDR_VERSION = 8'h02;
localparam ADDR_CTRL = 8'h08;
localparam CTRL_INIT_BIT = 0;
localparam CTRL_NEXT_BIT = 1;
localparam ADDR_STATUS = 8'h09;
localparam STATUS_READY_BIT = 0;
localparam STATUS_VALID_BIT = 1;
localparam ADDR_CONFIG = 8'h0a;
localparam CTRL_ENCDEC_BIT = 0;
localparam CTRL_KEYLEN_BIT = 1;
localparam ADDR_KEY0 = 8'h10;
localparam ADDR_KEY7 = 8'h17;
localparam ADDR_BLOCK0 = 8'h20;
localparam ADDR_BLOCK3 = 8'h23;
localparam ADDR_RESULT0 = 8'h30;
localparam ADDR_RESULT3 = 8'h33;
localparam CORE_NAME0 = 32'h61657320; // "aes "
localparam CORE_NAME1 = 32'h20202020; // " "
localparam CORE_VERSION = 32'h302e3630; // "0.60"
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg init_reg;
reg init_new;
reg next_reg;
reg next_new;
reg encdec_reg;
reg keylen_reg;
reg config_we;
reg [31 : 0] block_reg [0 : 3];
reg block_we;
reg [31 : 0] key_reg [0 : 7];
reg key_we;
reg [127 : 0] result_reg;
reg valid_reg;
reg ready_reg;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [31 : 0] tmp_read_data;
wire core_encdec;
wire core_init;
wire core_next;
wire core_ready;
wire [255 : 0] core_key;
wire core_keylen;
wire [127 : 0] core_block;
wire [127 : 0] core_result;
wire core_valid;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign read_data = tmp_read_data;
assign core_key = {key_reg[0], key_reg[1], key_reg[2], key_reg[3],
key_reg[4], key_reg[5], key_reg[6], key_reg[7]};
assign core_block = {block_reg[0], block_reg[1],
block_reg[2], block_reg[3]};
assign core_init = init_reg;
assign core_next = next_reg;
assign core_encdec = encdec_reg;
assign core_keylen = keylen_reg;
//----------------------------------------------------------------
// core instantiation.
//----------------------------------------------------------------
aes_core core(
.clk(clk),
.reset_n(reset_n),
.encdec(core_encdec),
.init(core_init),
.next(core_next),
.ready(core_ready),
.key(core_key),
.keylen(core_keylen),
.block(core_block),
.result(core_result),
.result_valid(core_valid)
);
//----------------------------------------------------------------
// reg_update
// Update functionality for all registers in the core.
// All registers are positive edge triggered with asynchronous
// active low reset.
//----------------------------------------------------------------
always @ (posedge clk or negedge reset_n)
begin : reg_update
integer i;
if (!reset_n)
begin
for (i = 0 ; i < 4 ; i = i + 1)
block_reg[i] <= 32'h0;
for (i = 0 ; i < 8 ; i = i + 1)
key_reg[i] <= 32'h0;
init_reg <= 1'b0;
next_reg <= 1'b0;
encdec_reg <= 1'b0;
keylen_reg <= 1'b0;
result_reg <= 128'h0;
valid_reg <= 1'b0;
ready_reg <= 1'b0;
end
else
begin
ready_reg <= core_ready;
valid_reg <= core_valid;
result_reg <= core_result;
init_reg <= init_new;
next_reg <= next_new;
if (config_we)
begin
encdec_reg <= write_data[CTRL_ENCDEC_BIT];
keylen_reg <= write_data[CTRL_KEYLEN_BIT];
end
if (key_we)
key_reg[address[2 : 0]] <= write_data;
if (block_we)
block_reg[address[1 : 0]] <= write_data;
end
end // reg_update
//----------------------------------------------------------------
// api
//
// The interface command decoding logic.
//----------------------------------------------------------------
always @*
begin : api
init_new = 1'b0;
next_new = 1'b0;
config_we = 1'b0;
key_we = 1'b0;
block_we = 1'b0;
tmp_read_data = 32'h0;
if (cs)
begin
if (we)
begin
if (address == ADDR_CTRL)
begin
init_new = write_data[CTRL_INIT_BIT];
next_new = write_data[CTRL_NEXT_BIT];
end
if (address == ADDR_CONFIG)
config_we = 1'b1;
if ((address >= ADDR_KEY0) && (address <= ADDR_KEY7))
key_we = 1'b1;
if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK3))
block_we = 1'b1;
end // if (we)
else
begin
case (address)
ADDR_NAME0: tmp_read_data = CORE_NAME0;
ADDR_NAME1: tmp_read_data = CORE_NAME1;
ADDR_VERSION: tmp_read_data = CORE_VERSION;
ADDR_CTRL: tmp_read_data = {28'h0, keylen_reg, encdec_reg, next_reg, init_reg};
ADDR_STATUS: tmp_read_data = {30'h0, valid_reg, ready_reg};
default:
begin
end
endcase // case (address)
if ((address >= ADDR_RESULT0) && (address <= ADDR_RESULT3))
tmp_read_data = result_reg[(3 - (address - ADDR_RESULT0)) * 32 +: 32];
end
end
end // addr_decoder
endmodule // aes
//======================================================================
// EOF aes.v
//======================================================================
//======================================================================
//
// 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) 2013, 2014, Secworks Sweden AB
// 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_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
//======================================================================
//======================================================================
//
// aes_decipher_block.v
// --------------------
// The AES decipher round. A pure combinational module that implements
// the initial round, main round and final round logic for
// decciper operations.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2013, 2014, Secworks Sweden AB
// 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_decipher_block(
input wire clk,
input wire reset_n,
input wire next,
input wire keylen,
output wire [3 : 0] round,
input wire [127 : 0] round_key,
input wire [127 : 0] block,
output wire [127 : 0] new_block,
output wire ready
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
localparam AES_128_BIT_KEY = 1'h0;
localparam AES_256_BIT_KEY = 1'h1;
localparam AES128_ROUNDS = 4'ha;
localparam AES256_ROUNDS = 4'he;
localparam NO_UPDATE = 3'h0;
localparam INIT_UPDATE = 3'h1;
localparam SBOX_UPDATE = 3'h2;
localparam MAIN_UPDATE = 3'h3;
localparam FINAL_UPDATE = 3'h4;
localparam CTRL_IDLE = 3'h0;
localparam CTRL_INIT = 3'h1;
localparam CTRL_SBOX = 3'h2;
localparam CTRL_MAIN = 3'h3;
localparam CTRL_FINAL = 3'h4;
//----------------------------------------------------------------
// Gaolis multiplication functions for Inverse MixColumn.
//----------------------------------------------------------------
function [7 : 0] gm2(input [7 : 0] op);
begin
gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}});
end
endfunction // gm2
function [7 : 0] gm3(input [7 : 0] op);
begin
gm3 = gm2(op) ^ op;
end
endfunction // gm3
function [7 : 0] gm4(input [7 : 0] op);
begin
gm4 = gm2(gm2(op));
end
endfunction // gm4
function [7 : 0] gm8(input [7 : 0] op);
begin
gm8 = gm2(gm4(op));
end
endfunction // gm8
function [7 : 0] gm09(input [7 : 0] op);
begin
gm09 = gm8(op) ^ op;
end
endfunction // gm09
function [7 : 0] gm11(input [7 : 0] op);
begin
gm11 = gm8(op) ^ gm2(op) ^ op;
end
endfunction // gm11
function [7 : 0] gm13(input [7 : 0] op);
begin
gm13 = gm8(op) ^ gm4(op) ^ op;
end
endfunction // gm13
function [7 : 0] gm14(input [7 : 0] op);
begin
gm14 = gm8(op) ^ gm4(op) ^ gm2(op);
end
endfunction // gm14
function [31 : 0] inv_mixw(input [31 : 0] w);
reg [7 : 0] b0, b1, b2, b3;
reg [7 : 0] mb0, mb1, mb2, mb3;
begin
b0 = w[31 : 24];
b1 = w[23 : 16];
b2 = w[15 : 08];
b3 = w[07 : 00];
mb0 = gm14(b0) ^ gm11(b1) ^ gm13(b2) ^ gm09(b3);
mb1 = gm09(b0) ^ gm14(b1) ^ gm11(b2) ^ gm13(b3);
mb2 = gm13(b0) ^ gm09(b1) ^ gm14(b2) ^ gm11(b3);
mb3 = gm11(b0) ^ gm13(b1) ^ gm09(b2) ^ gm14(b3);
inv_mixw = {mb0, mb1, mb2, mb3};
end
endfunction // mixw
function [127 : 0] inv_mixcolumns(input [127 : 0] data);
reg [31 : 0] w0, w1, w2, w3;
reg [31 : 0] ws0, ws1, ws2, ws3;
begin
w0 = data[127 : 096];
w1 = data[095 : 064];
w2 = data[063 : 032];
w3 = data[031 : 000];
ws0 = inv_mixw(w0);
ws1 = inv_mixw(w1);
ws2 = inv_mixw(w2);
ws3 = inv_mixw(w3);
inv_mixcolumns = {ws0, ws1, ws2, ws3};
end
endfunction // inv_mixcolumns
function [127 : 0] inv_shiftrows(input [127 : 0] data);
reg [31 : 0] w0, w1, w2, w3;
reg [31 : 0] ws0, ws1, ws2, ws3;
begin
w0 = data[127 : 096];
w1 = data[095 : 064];
w2 = data[063 : 032];
w3 = data[031 : 000];
ws0 = {w0[31 : 24], w3[23 : 16], w2[15 : 08], w1[07 : 00]};
ws1 = {w1[31 : 24], w0[23 : 16], w3[15 : 08], w2[07 : 00]};
ws2 = {w2[31 : 24], w1[23 : 16], w0[15 : 08], w3[07 : 00]};
ws3 = {w3[31 : 24], w2[23 : 16], w1[15 : 08], w0[07 : 00]};
inv_shiftrows = {ws0, ws1, ws2, ws3};
end
endfunction // inv_shiftrows
function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey);
begin
addroundkey = data ^ rkey;
end
endfunction // addroundkey
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [1 : 0] sword_ctr_reg;
reg [1 : 0] sword_ctr_new;
reg sword_ctr_we;
reg sword_ctr_inc;
reg sword_ctr_rst;
reg [3 : 0] round_ctr_reg;
reg [3 : 0] round_ctr_new;
reg round_ctr_we;
reg round_ctr_set;
reg round_ctr_dec;
reg [127 : 0] block_new;
reg [31 : 0] block_w0_reg;
reg [31 : 0] block_w1_reg;
reg [31 : 0] block_w2_reg;
reg [31 : 0] block_w3_reg;
reg block_w0_we;
reg block_w1_we;
reg block_w2_we;
reg block_w3_we;
reg ready_reg;
reg ready_new;
reg ready_we;
reg [2 : 0] dec_ctrl_reg;
reg [2 : 0] dec_ctrl_new;
reg dec_ctrl_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [31 : 0] tmp_sboxw;
wire [31 : 0] new_sboxw;
reg [2 : 0] update_type;
//----------------------------------------------------------------
// Instantiations.
//----------------------------------------------------------------
aes_inv_sbox inv_sbox_inst(.sword(tmp_sboxw), .new_sword(new_sboxw));
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign round = round_ctr_reg;
assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
assign ready = ready_reg;
//----------------------------------------------------------------
// reg_update
//
// Update functionality for all registers in the core.
// All registers are positive edge triggered with synchronous
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk or negedge reset_n)
begin: reg_update
if (!reset_n)
begin
block_w0_reg <= 32'h0;
block_w1_reg <= 32'h0;
block_w2_reg <= 32'h0;
block_w3_reg <= 32'h0;
sword_ctr_reg <= 2'h0;
round_ctr_reg <= 4'h0;
ready_reg <= 1'b1;
dec_ctrl_reg <= CTRL_IDLE;
end
else
begin
if (block_w0_we)
block_w0_reg <= block_new[127 : 096];
if (block_w1_we)
block_w1_reg <= block_new[095 : 064];
if (block_w2_we)
block_w2_reg <= block_new[063 : 032];
if (block_w3_we)
block_w3_reg <= block_new[031 : 000];
if (sword_ctr_we)
sword_ctr_reg <= sword_ctr_new;
if (round_ctr_we)
round_ctr_reg <= round_ctr_new;
if (ready_we)
ready_reg <= ready_new;
if (dec_ctrl_we)
dec_ctrl_reg <= dec_ctrl_new;
end
end // reg_update
//----------------------------------------------------------------
// round_logic
//
// The logic needed to implement init, main and final rounds.
//----------------------------------------------------------------
always @*
begin : round_logic
reg [127 : 0] old_block, inv_shiftrows_block, inv_mixcolumns_block;
reg [127 : 0] addkey_block;
inv_shiftrows_block = 128'h0;
inv_mixcolumns_block = 128'h0;
addkey_block = 128'h0;
block_new = 128'h0;
tmp_sboxw = 32'h0;
block_w0_we = 1'b0;
block_w1_we = 1'b0;
block_w2_we = 1'b0;
block_w3_we = 1'b0;
old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
// Update based on update type.
case (update_type)
// InitRound
INIT_UPDATE:
begin
old_block = block;
addkey_block = addroundkey(old_block, round_key);
inv_shiftrows_block = inv_shiftrows(addkey_block);
block_new = inv_shiftrows_block;
block_w0_we = 1'b1;
block_w1_we = 1'b1;
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
SBOX_UPDATE:
begin
block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw};
case (sword_ctr_reg)
2'h0:
begin
tmp_sboxw = block_w0_reg;
block_w0_we = 1'b1;
end
2'h1:
begin
tmp_sboxw = block_w1_reg;
block_w1_we = 1'b1;
end
2'h2:
begin
tmp_sboxw = block_w2_reg;
block_w2_we = 1'b1;
end
2'h3:
begin
tmp_sboxw = block_w3_reg;
block_w3_we = 1'b1;
end
endcase // case (sbox_mux_ctrl_reg)
end
MAIN_UPDATE:
begin
addkey_block = addroundkey(old_block, round_key);
inv_mixcolumns_block = inv_mixcolumns(addkey_block);
inv_shiftrows_block = inv_shiftrows(inv_mixcolumns_block);
block_new = inv_shiftrows_block;
block_w0_we = 1'b1;
block_w1_we = 1'b1;
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
FINAL_UPDATE:
begin
block_new = addroundkey(old_block, round_key);
block_w0_we = 1'b1;
block_w1_we = 1'b1;
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
default:
begin
end
endcase // case (update_type)
end // round_logic
//----------------------------------------------------------------
// sword_ctr
//
// The subbytes word counter with reset and increase logic.
//----------------------------------------------------------------
always @*
begin : sword_ctr
sword_ctr_new = 2'h0;
sword_ctr_we = 1'b0;
if (sword_ctr_rst)
begin
sword_ctr_new = 2'h0;
sword_ctr_we = 1'b1;
end
else if (sword_ctr_inc)
begin
sword_ctr_new = sword_ctr_reg + 1'b1;
sword_ctr_we = 1'b1;
end
end // sword_ctr
//----------------------------------------------------------------
// round_ctr
//
// The round counter with reset and increase logic.
//----------------------------------------------------------------
always @*
begin : round_ctr
round_ctr_new = 4'h0;
round_ctr_we = 1'b0;
if (round_ctr_set)
begin
if (keylen == AES_256_BIT_KEY)
begin
round_ctr_new = AES256_ROUNDS;
end
else
begin
round_ctr_new = AES128_ROUNDS;
end
round_ctr_we = 1'b1;
end
else if (round_ctr_dec)
begin
round_ctr_new = round_ctr_reg - 1'b1;
round_ctr_we = 1'b1;
end
end // round_ctr
//----------------------------------------------------------------
// decipher_ctrl
//
// The FSM that controls the decipher operations.
//----------------------------------------------------------------
always @*
begin: decipher_ctrl
sword_ctr_inc = 1'b0;
sword_ctr_rst = 1'b0;
round_ctr_dec = 1'b0;
round_ctr_set = 1'b0;
ready_new = 1'b0;
ready_we = 1'b0;
update_type = NO_UPDATE;
dec_ctrl_new = CTRL_IDLE;
dec_ctrl_we = 1'b0;
case(dec_ctrl_reg)
CTRL_IDLE:
begin
if (next)
begin
round_ctr_set = 1'b1;
ready_new = 1'b0;
ready_we = 1'b1;
dec_ctrl_new = CTRL_INIT;
dec_ctrl_we = 1'b1;
end
end
CTRL_INIT:
begin
sword_ctr_rst = 1'b1;
update_type = INIT_UPDATE;
dec_ctrl_new = CTRL_SBOX;
dec_ctrl_we = 1'b1;
end
CTRL_SBOX:
begin
sword_ctr_inc = 1'b1;
update_type = SBOX_UPDATE;
if (sword_ctr_reg == 2'h3)
begin
round_ctr_dec = 1'b1;
dec_ctrl_new = CTRL_MAIN;
dec_ctrl_we = 1'b1;
end
end
CTRL_MAIN:
begin
sword_ctr_rst = 1'b1;
if (round_ctr_reg > 0)
begin
update_type = MAIN_UPDATE;
dec_ctrl_new = CTRL_SBOX;
dec_ctrl_we = 1'b1;
end
else
begin
update_type = FINAL_UPDATE;
ready_new = 1'b1;
ready_we = 1'b1;
dec_ctrl_new = CTRL_IDLE;
dec_ctrl_we = 1'b1;
end
end
default:
begin
// Empty. Just here to make the synthesis tool happy.
end
endcase // case (dec_ctrl_reg)
end // decipher_ctrl
endmodule // aes_decipher_block
//======================================================================
// EOF aes_decipher_block.v
//======================================================================
//======================================================================
//
// aes_inv_sbox.v
// --------------
// The inverse AES S-box. Basically a 256 Byte ROM.
//
//
// Copyright (c) 2013 Secworks Sweden AB
// 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_inv_sbox(
input wire [31 : 0] sword,
output wire [31 : 0] new_sword
);
//----------------------------------------------------------------
// The inverse sbox array.
//----------------------------------------------------------------
wire [7 : 0] inv_sbox [0 : 255];
//----------------------------------------------------------------
// Four parallel muxes.
//----------------------------------------------------------------
assign new_sword[31 : 24] = inv_sbox[sword[31 : 24]];
assign new_sword[23 : 16] = inv_sbox[sword[23 : 16]];
assign new_sword[15 : 08] = inv_sbox[sword[15 : 08]];
assign new_sword[07 : 00] = inv_sbox[sword[07 : 00]];
//----------------------------------------------------------------
// Creating the contents of the array.
//----------------------------------------------------------------
assign inv_sbox[8'h00] = 8'h52;
assign inv_sbox[8'h01] = 8'h09;
assign inv_sbox[8'h02] = 8'h6a;
assign inv_sbox[8'h03] = 8'hd5;
assign inv_sbox[8'h04] = 8'h30;
assign inv_sbox[8'h05] = 8'h36;
assign inv_sbox[8'h06] = 8'ha5;
assign inv_sbox[8'h07] = 8'h38;
assign inv_sbox[8'h08] = 8'hbf;
assign inv_sbox[8'h09] = 8'h40;
assign inv_sbox[8'h0a] = 8'ha3;
assign inv_sbox[8'h0b] = 8'h9e;
assign inv_sbox[8'h0c] = 8'h81;
assign inv_sbox[8'h0d] = 8'hf3;
assign inv_sbox[8'h0e] = 8'hd7;
assign inv_sbox[8'h0f] = 8'hfb;
assign inv_sbox[8'h10] = 8'h7c;
assign inv_sbox[8'h11] = 8'he3;
assign inv_sbox[8'h12] = 8'h39;
assign inv_sbox[8'h13] = 8'h82;
assign inv_sbox[8'h14] = 8'h9b;
assign inv_sbox[8'h15] = 8'h2f;
assign inv_sbox[8'h16] = 8'hff;
assign inv_sbox[8'h17] = 8'h87;
assign inv_sbox[8'h18] = 8'h34;
assign inv_sbox[8'h19] = 8'h8e;
assign inv_sbox[8'h1a] = 8'h43;
assign inv_sbox[8'h1b] = 8'h44;
assign inv_sbox[8'h1c] = 8'hc4;
assign inv_sbox[8'h1d] = 8'hde;
assign inv_sbox[8'h1e] = 8'he9;
assign inv_sbox[8'h1f] = 8'hcb;
assign inv_sbox[8'h20] = 8'h54;
assign inv_sbox[8'h21] = 8'h7b;
assign inv_sbox[8'h22] = 8'h94;
assign inv_sbox[8'h23] = 8'h32;
assign inv_sbox[8'h24] = 8'ha6;
assign inv_sbox[8'h25] = 8'hc2;
assign inv_sbox[8'h26] = 8'h23;
assign inv_sbox[8'h27] = 8'h3d;
assign inv_sbox[8'h28] = 8'hee;
assign inv_sbox[8'h29] = 8'h4c;
assign inv_sbox[8'h2a] = 8'h95;
assign inv_sbox[8'h2b] = 8'h0b;
assign inv_sbox[8'h2c] = 8'h42;
assign inv_sbox[8'h2d] = 8'hfa;
assign inv_sbox[8'h2e] = 8'hc3;
assign inv_sbox[8'h2f] = 8'h4e;
assign inv_sbox[8'h30] = 8'h08;
assign inv_sbox[8'h31] = 8'h2e;
assign inv_sbox[8'h32] = 8'ha1;
assign inv_sbox[8'h33] = 8'h66;
assign inv_sbox[8'h34] = 8'h28;
assign inv_sbox[8'h35] = 8'hd9;
assign inv_sbox[8'h36] = 8'h24;
assign inv_sbox[8'h37] = 8'hb2;
assign inv_sbox[8'h38] = 8'h76;
assign inv_sbox[8'h39] = 8'h5b;
assign inv_sbox[8'h3a] = 8'ha2;
assign inv_sbox[8'h3b] = 8'h49;
assign inv_sbox[8'h3c] = 8'h6d;
assign inv_sbox[8'h3d] = 8'h8b;
assign inv_sbox[8'h3e] = 8'hd1;
assign inv_sbox[8'h3f] = 8'h25;
assign inv_sbox[8'h40] = 8'h72;
assign inv_sbox[8'h41] = 8'hf8;
assign inv_sbox[8'h42] = 8'hf6;
assign inv_sbox[8'h43] = 8'h64;
assign inv_sbox[8'h44] = 8'h86;
assign inv_sbox[8'h45] = 8'h68;
assign inv_sbox[8'h46] = 8'h98;
assign inv_sbox[8'h47] = 8'h16;
assign inv_sbox[8'h48] = 8'hd4;
assign inv_sbox[8'h49] = 8'ha4;
assign inv_sbox[8'h4a] = 8'h5c;
assign inv_sbox[8'h4b] = 8'hcc;
assign inv_sbox[8'h4c] = 8'h5d;
assign inv_sbox[8'h4d] = 8'h65;
assign inv_sbox[8'h4e] = 8'hb6;
assign inv_sbox[8'h4f] = 8'h92;
assign inv_sbox[8'h50] = 8'h6c;
assign inv_sbox[8'h51] = 8'h70;
assign inv_sbox[8'h52] = 8'h48;
assign inv_sbox[8'h53] = 8'h50;
assign inv_sbox[8'h54] = 8'hfd;
assign inv_sbox[8'h55] = 8'hed;
assign inv_sbox[8'h56] = 8'hb9;
assign inv_sbox[8'h57] = 8'hda;
assign inv_sbox[8'h58] = 8'h5e;
assign inv_sbox[8'h59] = 8'h15;
assign inv_sbox[8'h5a] = 8'h46;
assign inv_sbox[8'h5b] = 8'h57;
assign inv_sbox[8'h5c] = 8'ha7;
assign inv_sbox[8'h5d] = 8'h8d;
assign inv_sbox[8'h5e] = 8'h9d;
assign inv_sbox[8'h5f] = 8'h84;
assign inv_sbox[8'h60] = 8'h90;
assign inv_sbox[8'h61] = 8'hd8;
assign inv_sbox[8'h62] = 8'hab;
assign inv_sbox[8'h63] = 8'h00;
assign inv_sbox[8'h64] = 8'h8c;
assign inv_sbox[8'h65] = 8'hbc;
assign inv_sbox[8'h66] = 8'hd3;
assign inv_sbox[8'h67] = 8'h0a;
assign inv_sbox[8'h68] = 8'hf7;
assign inv_sbox[8'h69] = 8'he4;
assign inv_sbox[8'h6a] = 8'h58;
assign inv_sbox[8'h6b] = 8'h05;
assign inv_sbox[8'h6c] = 8'hb8;
assign inv_sbox[8'h6d] = 8'hb3;
assign inv_sbox[8'h6e] = 8'h45;
assign inv_sbox[8'h6f] = 8'h06;
assign inv_sbox[8'h70] = 8'hd0;
assign inv_sbox[8'h71] = 8'h2c;
assign inv_sbox[8'h72] = 8'h1e;
assign inv_sbox[8'h73] = 8'h8f;
assign inv_sbox[8'h74] = 8'hca;
assign inv_sbox[8'h75] = 8'h3f;
assign inv_sbox[8'h76] = 8'h0f;
assign inv_sbox[8'h77] = 8'h02;
assign inv_sbox[8'h78] = 8'hc1;
assign inv_sbox[8'h79] = 8'haf;
assign inv_sbox[8'h7a] = 8'hbd;
assign inv_sbox[8'h7b] = 8'h03;
assign inv_sbox[8'h7c] = 8'h01;
assign inv_sbox[8'h7d] = 8'h13;
assign inv_sbox[8'h7e] = 8'h8a;
assign inv_sbox[8'h7f] = 8'h6b;
assign inv_sbox[8'h80] = 8'h3a;
assign inv_sbox[8'h81] = 8'h91;
assign inv_sbox[8'h82] = 8'h11;
assign inv_sbox[8'h83] = 8'h41;
assign inv_sbox[8'h84] = 8'h4f;
assign inv_sbox[8'h85] = 8'h67;
assign inv_sbox[8'h86] = 8'hdc;
assign inv_sbox[8'h87] = 8'hea;
assign inv_sbox[8'h88] = 8'h97;
assign inv_sbox[8'h89] = 8'hf2;
assign inv_sbox[8'h8a] = 8'hcf;
assign inv_sbox[8'h8b] = 8'hce;
assign inv_sbox[8'h8c] = 8'hf0;
assign inv_sbox[8'h8d] = 8'hb4;
assign inv_sbox[8'h8e] = 8'he6;
assign inv_sbox[8'h8f] = 8'h73;
assign inv_sbox[8'h90] = 8'h96;
assign inv_sbox[8'h91] = 8'hac;
assign inv_sbox[8'h92] = 8'h74;
assign inv_sbox[8'h93] = 8'h22;
assign inv_sbox[8'h94] = 8'he7;
assign inv_sbox[8'h95] = 8'had;
assign inv_sbox[8'h96] = 8'h35;
assign inv_sbox[8'h97] = 8'h85;
assign inv_sbox[8'h98] = 8'he2;
assign inv_sbox[8'h99] = 8'hf9;
assign inv_sbox[8'h9a] = 8'h37;
assign inv_sbox[8'h9b] = 8'he8;
assign inv_sbox[8'h9c] = 8'h1c;
assign inv_sbox[8'h9d] = 8'h75;
assign inv_sbox[8'h9e] = 8'hdf;
assign inv_sbox[8'h9f] = 8'h6e;
assign inv_sbox[8'ha0] = 8'h47;
assign inv_sbox[8'ha1] = 8'hf1;
assign inv_sbox[8'ha2] = 8'h1a;
assign inv_sbox[8'ha3] = 8'h71;
assign inv_sbox[8'ha4] = 8'h1d;
assign inv_sbox[8'ha5] = 8'h29;
assign inv_sbox[8'ha6] = 8'hc5;
assign inv_sbox[8'ha7] = 8'h89;
assign inv_sbox[8'ha8] = 8'h6f;
assign inv_sbox[8'ha9] = 8'hb7;
assign inv_sbox[8'haa] = 8'h62;
assign inv_sbox[8'hab] = 8'h0e;
assign inv_sbox[8'hac] = 8'haa;
assign inv_sbox[8'had] = 8'h18;
assign inv_sbox[8'hae] = 8'hbe;
assign inv_sbox[8'haf] = 8'h1b;
assign inv_sbox[8'hb0] = 8'hfc;
assign inv_sbox[8'hb1] = 8'h56;
assign inv_sbox[8'hb2] = 8'h3e;
assign inv_sbox[8'hb3] = 8'h4b;
assign inv_sbox[8'hb4] = 8'hc6;
assign inv_sbox[8'hb5] = 8'hd2;
assign inv_sbox[8'hb6] = 8'h79;
assign inv_sbox[8'hb7] = 8'h20;
assign inv_sbox[8'hb8] = 8'h9a;
assign inv_sbox[8'hb9] = 8'hdb;
assign inv_sbox[8'hba] = 8'hc0;
assign inv_sbox[8'hbb] = 8'hfe;
assign inv_sbox[8'hbc] = 8'h78;
assign inv_sbox[8'hbd] = 8'hcd;
assign inv_sbox[8'hbe] = 8'h5a;
assign inv_sbox[8'hbf] = 8'hf4;
assign inv_sbox[8'hc0] = 8'h1f;
assign inv_sbox[8'hc1] = 8'hdd;
assign inv_sbox[8'hc2] = 8'ha8;
assign inv_sbox[8'hc3] = 8'h33;
assign inv_sbox[8'hc4] = 8'h88;
assign inv_sbox[8'hc5] = 8'h07;
assign inv_sbox[8'hc6] = 8'hc7;
assign inv_sbox[8'hc7] = 8'h31;
assign inv_sbox[8'hc8] = 8'hb1;
assign inv_sbox[8'hc9] = 8'h12;
assign inv_sbox[8'hca] = 8'h10;
assign inv_sbox[8'hcb] = 8'h59;
assign inv_sbox[8'hcc] = 8'h27;
assign inv_sbox[8'hcd] = 8'h80;
assign inv_sbox[8'hce] = 8'hec;
assign inv_sbox[8'hcf] = 8'h5f;
assign inv_sbox[8'hd0] = 8'h60;
assign inv_sbox[8'hd1] = 8'h51;
assign inv_sbox[8'hd2] = 8'h7f;
assign inv_sbox[8'hd3] = 8'ha9;
assign inv_sbox[8'hd4] = 8'h19;
assign inv_sbox[8'hd5] = 8'hb5;
assign inv_sbox[8'hd6] = 8'h4a;
assign inv_sbox[8'hd7] = 8'h0d;
assign inv_sbox[8'hd8] = 8'h2d;
assign inv_sbox[8'hd9] = 8'he5;
assign inv_sbox[8'hda] = 8'h7a;
assign inv_sbox[8'hdb] = 8'h9f;
assign inv_sbox[8'hdc] = 8'h93;
assign inv_sbox[8'hdd] = 8'hc9;
assign inv_sbox[8'hde] = 8'h9c;
assign inv_sbox[8'hdf] = 8'hef;
assign inv_sbox[8'he0] = 8'ha0;
assign inv_sbox[8'he1] = 8'he0;
assign inv_sbox[8'he2] = 8'h3b;
assign inv_sbox[8'he3] = 8'h4d;
assign inv_sbox[8'he4] = 8'hae;
assign inv_sbox[8'he5] = 8'h2a;
assign inv_sbox[8'he6] = 8'hf5;
assign inv_sbox[8'he7] = 8'hb0;
assign inv_sbox[8'he8] = 8'hc8;
assign inv_sbox[8'he9] = 8'heb;
assign inv_sbox[8'hea] = 8'hbb;
assign inv_sbox[8'heb] = 8'h3c;
assign inv_sbox[8'hec] = 8'h83;
assign inv_sbox[8'hed] = 8'h53;
assign inv_sbox[8'hee] = 8'h99;
assign inv_sbox[8'hef] = 8'h61;
assign inv_sbox[8'hf0] = 8'h17;
assign inv_sbox[8'hf1] = 8'h2b;
assign inv_sbox[8'hf2] = 8'h04;
assign inv_sbox[8'hf3] = 8'h7e;
assign inv_sbox[8'hf4] = 8'hba;
assign inv_sbox[8'hf5] = 8'h77;
assign inv_sbox[8'hf6] = 8'hd6;
assign inv_sbox[8'hf7] = 8'h26;
assign inv_sbox[8'hf8] = 8'he1;
assign inv_sbox[8'hf9] = 8'h69;
assign inv_sbox[8'hfa] = 8'h14;
assign inv_sbox[8'hfb] = 8'h63;
assign inv_sbox[8'hfc] = 8'h55;
assign inv_sbox[8'hfd] = 8'h21;
assign inv_sbox[8'hfe] = 8'h0c;
assign inv_sbox[8'hff] = 8'h7d;
endmodule // aes_inv_sbox
//======================================================================
// EOF aes_inv_sbox.v
//======================================================================
//======================================================================
//
// aes_key_mem.v
// -------------
// The AES key memory including round key generator.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2013 Secworks Sweden AB
// 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.
//----------------------------------------------------------------
localparam AES_128_BIT_KEY = 1'h0;
localparam AES_256_BIT_KEY = 1'h1;
localparam AES_128_NUM_ROUNDS = 10;
localparam AES_256_NUM_ROUNDS = 14;
localparam CTRL_IDLE = 3'h0;
localparam CTRL_INIT = 3'h1;
localparam CTRL_GENERATE = 3'h2;
localparam 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 [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
integer i;
if (!reset_n)
begin
for (i = 0 ; i <= AES_256_NUM_ROUNDS ; i = i + 1)
key_mem [i] <= 128'h0;
rcon_reg <= 8'h0;
ready_reg <= 1'b0;
round_ctr_reg <= 4'h0;
key_mem_ctrl_reg <= CTRL_IDLE;
end
else
begin
if (round_ctr_we)
round_ctr_reg <= round_ctr_new;
if (ready_we)
ready_reg <= ready_new;
if (rcon_we)
rcon_reg <= rcon_new;
if (key_mem_we)
key_mem[round_ctr_reg] <= key_mem_new;
if (prev_key0_we)
prev_key0_reg <= prev_key0_new;
if (prev_key1_we)
prev_key1_reg <= prev_key1_new;
if (key_mem_ctrl_we)
key_mem_ctrl_reg <= key_mem_ctrl_new;
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'h0;
key_mem_we = 1'b0;
prev_key0_new = 128'h0;
prev_key0_we = 1'b0;
prev_key1_new = 128'h0;
prev_key1_we = 1'b0;
k0 = 32'h0;
k1 = 32'h0;
k2 = 32'h0;
k3 = 32'h0;
rcon_set = 1'b1;
rcon_next = 1'b0;
// 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'h0};
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 = 1'b0;
key_mem_we = 1'b1;
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'b1;
rcon_next = 1'b1;
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'b1;
rcon_next = 1'b1;
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'b1;
end
else if (round_ctr_reg == 1)
begin
key_mem_new = key[127 : 0];
prev_key1_new = key[127 : 0];
prev_key1_we = 1'b1;
rcon_next = 1'b1;
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'b1;
end
// Store the generated round keys.
key_mem_new = {k0, k1, k2, k3};
prev_key1_new = {k0, k1, k2, k3};
prev_key1_we = 1'b1;
prev_key0_new = prev_key1_reg;
prev_key0_we = 1'b1;
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 = 1'b0;
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'b1;
end
if (rcon_next)
begin
rcon_new = tmp_rcon[7 : 0];
rcon_we = 1'b1;
end
end
//----------------------------------------------------------------
// round_ctr
//
// The round counter logic with increase and reset.
//----------------------------------------------------------------
always @*
begin : round_ctr
round_ctr_new = 4'h0;
round_ctr_we = 1'b0;
if (round_ctr_rst)
begin
round_ctr_new = 4'h0;
round_ctr_we = 1'b1;
end
else if (round_ctr_inc)
begin
round_ctr_new = round_ctr_reg + 1'b1;
round_ctr_we = 1'b1;
end
end
//----------------------------------------------------------------
// key_mem_ctrl
//
//
// The FSM that controls the round key generation.
//----------------------------------------------------------------
always @*
begin: key_mem_ctrl
reg [3 : 0] num_rounds;
// Default assignments.
ready_new = 1'b0;
ready_we = 1'b0;
round_key_update = 1'b0;
round_ctr_rst = 1'b0;
round_ctr_inc = 1'b0;
key_mem_ctrl_new = CTRL_IDLE;
key_mem_ctrl_we = 1'b0;
if (keylen == AES_128_BIT_KEY)
num_rounds = AES_128_NUM_ROUNDS;
else
num_rounds = AES_256_NUM_ROUNDS;
case(key_mem_ctrl_reg)
CTRL_IDLE:
begin
if (init)
begin
ready_new = 1'b0;
ready_we = 1'b1;
key_mem_ctrl_new = CTRL_INIT;
key_mem_ctrl_we = 1'b1;
end
end
CTRL_INIT:
begin
round_ctr_rst = 1'b1;
key_mem_ctrl_new = CTRL_GENERATE;
key_mem_ctrl_we = 1'b1;
end
CTRL_GENERATE:
begin
round_ctr_inc = 1'b1;
round_key_update = 1'b1;
if (round_ctr_reg == num_rounds)
begin
key_mem_ctrl_new = CTRL_DONE;
key_mem_ctrl_we = 1'b1;
end
end
CTRL_DONE:
begin
ready_new = 1'b1;
ready_we = 1'b1;
key_mem_ctrl_new = CTRL_IDLE;
key_mem_ctrl_we = 1'b1;
end
default:
begin
end
endcase // case (key_mem_ctrl_reg)
end // key_mem_ctrl
endmodule // aes_key_mem
//======================================================================
// EOF aes_key_mem.v
//======================================================================
//======================================================================
//
// aes_sbox.v
// ----------
// The AES S-box. Basically a 256 Byte ROM. This implementation
// contains four parallel S-boxes to handle a 32 bit word.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2014, Secworks Sweden AB
// 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_sbox(
input wire [31 : 0] sboxw,
output wire [31 : 0] new_sboxw
);
//----------------------------------------------------------------
// The sbox array.
//----------------------------------------------------------------
wire [7 : 0] sbox [0 : 255];
//----------------------------------------------------------------
// Four parallel muxes.
//----------------------------------------------------------------
assign new_sboxw[31 : 24] = sbox[sboxw[31 : 24]];
assign new_sboxw[23 : 16] = sbox[sboxw[23 : 16]];
assign new_sboxw[15 : 08] = sbox[sboxw[15 : 08]];
assign new_sboxw[07 : 00] = sbox[sboxw[07 : 00]];
//----------------------------------------------------------------
// Creating the sbox array contents.
//----------------------------------------------------------------
assign sbox[8'h00] = 8'h63;
assign sbox[8'h01] = 8'h7c;
assign sbox[8'h02] = 8'h77;
assign sbox[8'h03] = 8'h7b;
assign sbox[8'h04] = 8'hf2;
assign sbox[8'h05] = 8'h6b;
assign sbox[8'h06] = 8'h6f;
assign sbox[8'h07] = 8'hc5;
assign sbox[8'h08] = 8'h30;
assign sbox[8'h09] = 8'h01;
assign sbox[8'h0a] = 8'h67;
assign sbox[8'h0b] = 8'h2b;
assign sbox[8'h0c] = 8'hfe;
assign sbox[8'h0d] = 8'hd7;
assign sbox[8'h0e] = 8'hab;
assign sbox[8'h0f] = 8'h76;
assign sbox[8'h10] = 8'hca;
assign sbox[8'h11] = 8'h82;
assign sbox[8'h12] = 8'hc9;
assign sbox[8'h13] = 8'h7d;
assign sbox[8'h14] = 8'hfa;
assign sbox[8'h15] = 8'h59;
assign sbox[8'h16] = 8'h47;
assign sbox[8'h17] = 8'hf0;
assign sbox[8'h18] = 8'had;
assign sbox[8'h19] = 8'hd4;
assign sbox[8'h1a] = 8'ha2;
assign sbox[8'h1b] = 8'haf;
assign sbox[8'h1c] = 8'h9c;
assign sbox[8'h1d] = 8'ha4;
assign sbox[8'h1e] = 8'h72;
assign sbox[8'h1f] = 8'hc0;
assign sbox[8'h20] = 8'hb7;
assign sbox[8'h21] = 8'hfd;
assign sbox[8'h22] = 8'h93;
assign sbox[8'h23] = 8'h26;
assign sbox[8'h24] = 8'h36;
assign sbox[8'h25] = 8'h3f;
assign sbox[8'h26] = 8'hf7;
assign sbox[8'h27] = 8'hcc;
assign sbox[8'h28] = 8'h34;
assign sbox[8'h29] = 8'ha5;
assign sbox[8'h2a] = 8'he5;
assign sbox[8'h2b] = 8'hf1;
assign sbox[8'h2c] = 8'h71;
assign sbox[8'h2d] = 8'hd8;
assign sbox[8'h2e] = 8'h31;
assign sbox[8'h2f] = 8'h15;
assign sbox[8'h30] = 8'h04;
assign sbox[8'h31] = 8'hc7;
assign sbox[8'h32] = 8'h23;
assign sbox[8'h33] = 8'hc3;
assign sbox[8'h34] = 8'h18;
assign sbox[8'h35] = 8'h96;
assign sbox[8'h36] = 8'h05;
assign sbox[8'h37] = 8'h9a;
assign sbox[8'h38] = 8'h07;
assign sbox[8'h39] = 8'h12;
assign sbox[8'h3a] = 8'h80;
assign sbox[8'h3b] = 8'he2;
assign sbox[8'h3c] = 8'heb;
assign sbox[8'h3d] = 8'h27;
assign sbox[8'h3e] = 8'hb2;
assign sbox[8'h3f] = 8'h75;
assign sbox[8'h40] = 8'h09;
assign sbox[8'h41] = 8'h83;
assign sbox[8'h42] = 8'h2c;
assign sbox[8'h43] = 8'h1a;
assign sbox[8'h44] = 8'h1b;
assign sbox[8'h45] = 8'h6e;
assign sbox[8'h46] = 8'h5a;
assign sbox[8'h47] = 8'ha0;
assign sbox[8'h48] = 8'h52;
assign sbox[8'h49] = 8'h3b;
assign sbox[8'h4a] = 8'hd6;
assign sbox[8'h4b] = 8'hb3;
assign sbox[8'h4c] = 8'h29;
assign sbox[8'h4d] = 8'he3;
assign sbox[8'h4e] = 8'h2f;
assign sbox[8'h4f] = 8'h84;
assign sbox[8'h50] = 8'h53;
assign sbox[8'h51] = 8'hd1;
assign sbox[8'h52] = 8'h00;
assign sbox[8'h53] = 8'hed;
assign sbox[8'h54] = 8'h20;
assign sbox[8'h55] = 8'hfc;
assign sbox[8'h56] = 8'hb1;
assign sbox[8'h57] = 8'h5b;
assign sbox[8'h58] = 8'h6a;
assign sbox[8'h59] = 8'hcb;
assign sbox[8'h5a] = 8'hbe;
assign sbox[8'h5b] = 8'h39;
assign sbox[8'h5c] = 8'h4a;
assign sbox[8'h5d] = 8'h4c;
assign sbox[8'h5e] = 8'h58;
assign sbox[8'h5f] = 8'hcf;
assign sbox[8'h60] = 8'hd0;
assign sbox[8'h61] = 8'hef;
assign sbox[8'h62] = 8'haa;
assign sbox[8'h63] = 8'hfb;
assign sbox[8'h64] = 8'h43;
assign sbox[8'h65] = 8'h4d;
assign sbox[8'h66] = 8'h33;
assign sbox[8'h67] = 8'h85;
assign sbox[8'h68] = 8'h45;
assign sbox[8'h69] = 8'hf9;
assign sbox[8'h6a] = 8'h02;
assign sbox[8'h6b] = 8'h7f;
assign sbox[8'h6c] = 8'h50;
assign sbox[8'h6d] = 8'h3c;
assign sbox[8'h6e] = 8'h9f;
assign sbox[8'h6f] = 8'ha8;
assign sbox[8'h70] = 8'h51;
assign sbox[8'h71] = 8'ha3;
assign sbox[8'h72] = 8'h40;
assign sbox[8'h73] = 8'h8f;
assign sbox[8'h74] = 8'h92;
assign sbox[8'h75] = 8'h9d;
assign sbox[8'h76] = 8'h38;
assign sbox[8'h77] = 8'hf5;
assign sbox[8'h78] = 8'hbc;
assign sbox[8'h79] = 8'hb6;
assign sbox[8'h7a] = 8'hda;
assign sbox[8'h7b] = 8'h21;
assign sbox[8'h7c] = 8'h10;
assign sbox[8'h7d] = 8'hff;
assign sbox[8'h7e] = 8'hf3;
assign sbox[8'h7f] = 8'hd2;
assign sbox[8'h80] = 8'hcd;
assign sbox[8'h81] = 8'h0c;
assign sbox[8'h82] = 8'h13;
assign sbox[8'h83] = 8'hec;
assign sbox[8'h84] = 8'h5f;
assign sbox[8'h85] = 8'h97;
assign sbox[8'h86] = 8'h44;
assign sbox[8'h87] = 8'h17;
assign sbox[8'h88] = 8'hc4;
assign sbox[8'h89] = 8'ha7;
assign sbox[8'h8a] = 8'h7e;
assign sbox[8'h8b] = 8'h3d;
assign sbox[8'h8c] = 8'h64;
assign sbox[8'h8d] = 8'h5d;
assign sbox[8'h8e] = 8'h19;
assign sbox[8'h8f] = 8'h73;
assign sbox[8'h90] = 8'h60;
assign sbox[8'h91] = 8'h81;
assign sbox[8'h92] = 8'h4f;
assign sbox[8'h93] = 8'hdc;
assign sbox[8'h94] = 8'h22;
assign sbox[8'h95] = 8'h2a;
assign sbox[8'h96] = 8'h90;
assign sbox[8'h97] = 8'h88;
assign sbox[8'h98] = 8'h46;
assign sbox[8'h99] = 8'hee;
assign sbox[8'h9a] = 8'hb8;
assign sbox[8'h9b] = 8'h14;
assign sbox[8'h9c] = 8'hde;
assign sbox[8'h9d] = 8'h5e;
assign sbox[8'h9e] = 8'h0b;
assign sbox[8'h9f] = 8'hdb;
assign sbox[8'ha0] = 8'he0;
assign sbox[8'ha1] = 8'h32;
assign sbox[8'ha2] = 8'h3a;
assign sbox[8'ha3] = 8'h0a;
assign sbox[8'ha4] = 8'h49;
assign sbox[8'ha5] = 8'h06;
assign sbox[8'ha6] = 8'h24;
assign sbox[8'ha7] = 8'h5c;
assign sbox[8'ha8] = 8'hc2;
assign sbox[8'ha9] = 8'hd3;
assign sbox[8'haa] = 8'hac;
assign sbox[8'hab] = 8'h62;
assign sbox[8'hac] = 8'h91;
assign sbox[8'had] = 8'h95;
assign sbox[8'hae] = 8'he4;
assign sbox[8'haf] = 8'h79;
assign sbox[8'hb0] = 8'he7;
assign sbox[8'hb1] = 8'hc8;
assign sbox[8'hb2] = 8'h37;
assign sbox[8'hb3] = 8'h6d;
assign sbox[8'hb4] = 8'h8d;
assign sbox[8'hb5] = 8'hd5;
assign sbox[8'hb6] = 8'h4e;
assign sbox[8'hb7] = 8'ha9;
assign sbox[8'hb8] = 8'h6c;
assign sbox[8'hb9] = 8'h56;
assign sbox[8'hba] = 8'hf4;
assign sbox[8'hbb] = 8'hea;
assign sbox[8'hbc] = 8'h65;
assign sbox[8'hbd] = 8'h7a;
assign sbox[8'hbe] = 8'hae;
assign sbox[8'hbf] = 8'h08;
assign sbox[8'hc0] = 8'hba;
assign sbox[8'hc1] = 8'h78;
assign sbox[8'hc2] = 8'h25;
assign sbox[8'hc3] = 8'h2e;
assign sbox[8'hc4] = 8'h1c;
assign sbox[8'hc5] = 8'ha6;
assign sbox[8'hc6] = 8'hb4;
assign sbox[8'hc7] = 8'hc6;
assign sbox[8'hc8] = 8'he8;
assign sbox[8'hc9] = 8'hdd;
assign sbox[8'hca] = 8'h74;
assign sbox[8'hcb] = 8'h1f;
assign sbox[8'hcc] = 8'h4b;
assign sbox[8'hcd] = 8'hbd;
assign sbox[8'hce] = 8'h8b;
assign sbox[8'hcf] = 8'h8a;
assign sbox[8'hd0] = 8'h70;
assign sbox[8'hd1] = 8'h3e;
assign sbox[8'hd2] = 8'hb5;
assign sbox[8'hd3] = 8'h66;
assign sbox[8'hd4] = 8'h48;
assign sbox[8'hd5] = 8'h03;
assign sbox[8'hd6] = 8'hf6;
assign sbox[8'hd7] = 8'h0e;
assign sbox[8'hd8] = 8'h61;
assign sbox[8'hd9] = 8'h35;
assign sbox[8'hda] = 8'h57;
assign sbox[8'hdb] = 8'hb9;
assign sbox[8'hdc] = 8'h86;
assign sbox[8'hdd] = 8'hc1;
assign sbox[8'hde] = 8'h1d;
assign sbox[8'hdf] = 8'h9e;
assign sbox[8'he0] = 8'he1;
assign sbox[8'he1] = 8'hf8;
assign sbox[8'he2] = 8'h98;
assign sbox[8'he3] = 8'h11;
assign sbox[8'he4] = 8'h69;
assign sbox[8'he5] = 8'hd9;
assign sbox[8'he6] = 8'h8e;
assign sbox[8'he7] = 8'h94;
assign sbox[8'he8] = 8'h9b;
assign sbox[8'he9] = 8'h1e;
assign sbox[8'hea] = 8'h87;
assign sbox[8'heb] = 8'he9;
assign sbox[8'hec] = 8'hce;
assign sbox[8'hed] = 8'h55;
assign sbox[8'hee] = 8'h28;
assign sbox[8'hef] = 8'hdf;
assign sbox[8'hf0] = 8'h8c;
assign sbox[8'hf1] = 8'ha1;
assign sbox[8'hf2] = 8'h89;
assign sbox[8'hf3] = 8'h0d;
assign sbox[8'hf4] = 8'hbf;
assign sbox[8'hf5] = 8'he6;
assign sbox[8'hf6] = 8'h42;
assign sbox[8'hf7] = 8'h68;
assign sbox[8'hf8] = 8'h41;
assign sbox[8'hf9] = 8'h99;
assign sbox[8'hfa] = 8'h2d;
assign sbox[8'hfb] = 8'h0f;
assign sbox[8'hfc] = 8'hb0;
assign sbox[8'hfd] = 8'h54;
assign sbox[8'hfe] = 8'hbb;
assign sbox[8'hff] = 8'h16;
endmodule // aes_sbox
//======================================================================
// EOF aes_sbox.v
//======================================================================
//======================================================================
//
// aes_encipher_block.v
// --------------------
// The AES encipher round. A pure combinational module that implements
// the initial round, main round and final round logic for
// enciper operations.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2013, 2014, Secworks Sweden AB
// 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_encipher_block(
input wire clk,
input wire reset_n,
input wire next,
input wire keylen,
output wire [3 : 0] round,
input wire [127 : 0] round_key,
output wire [31 : 0] sboxw,
input wire [31 : 0] new_sboxw,
input wire [127 : 0] block,
output wire [127 : 0] new_block,
output wire ready
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
localparam AES_128_BIT_KEY = 1'h0;
localparam AES_256_BIT_KEY = 1'h1;
localparam AES128_ROUNDS = 4'ha;
localparam AES256_ROUNDS = 4'he;
localparam NO_UPDATE = 3'h0;
localparam INIT_UPDATE = 3'h1;
localparam SBOX_UPDATE = 3'h2;
localparam MAIN_UPDATE = 3'h3;
localparam FINAL_UPDATE = 3'h4;
localparam CTRL_IDLE = 3'h0;
localparam CTRL_INIT = 3'h1;
localparam CTRL_SBOX = 3'h2;
localparam CTRL_MAIN = 3'h3;
localparam CTRL_FINAL = 3'h4;
//----------------------------------------------------------------
// Round functions with sub functions.
//----------------------------------------------------------------
function [7 : 0] gm2(input [7 : 0] op);
begin
gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}});
end
endfunction // gm2
function [7 : 0] gm3(input [7 : 0] op);
begin
gm3 = gm2(op) ^ op;
end
endfunction // gm3
function [31 : 0] mixw(input [31 : 0] w);
reg [7 : 0] b0, b1, b2, b3;
reg [7 : 0] mb0, mb1, mb2, mb3;
begin
b0 = w[31 : 24];
b1 = w[23 : 16];
b2 = w[15 : 08];
b3 = w[07 : 00];
mb0 = gm2(b0) ^ gm3(b1) ^ b2 ^ b3;
mb1 = b0 ^ gm2(b1) ^ gm3(b2) ^ b3;
mb2 = b0 ^ b1 ^ gm2(b2) ^ gm3(b3);
mb3 = gm3(b0) ^ b1 ^ b2 ^ gm2(b3);
mixw = {mb0, mb1, mb2, mb3};
end
endfunction // mixw
function [127 : 0] mixcolumns(input [127 : 0] data);
reg [31 : 0] w0, w1, w2, w3;
reg [31 : 0] ws0, ws1, ws2, ws3;
begin
w0 = data[127 : 096];
w1 = data[095 : 064];
w2 = data[063 : 032];
w3 = data[031 : 000];
ws0 = mixw(w0);
ws1 = mixw(w1);
ws2 = mixw(w2);
ws3 = mixw(w3);
mixcolumns = {ws0, ws1, ws2, ws3};
end
endfunction // mixcolumns
function [127 : 0] shiftrows(input [127 : 0] data);
reg [31 : 0] w0, w1, w2, w3;
reg [31 : 0] ws0, ws1, ws2, ws3;
begin
w0 = data[127 : 096];
w1 = data[095 : 064];
w2 = data[063 : 032];
w3 = data[031 : 000];
ws0 = {w0[31 : 24], w1[23 : 16], w2[15 : 08], w3[07 : 00]};
ws1 = {w1[31 : 24], w2[23 : 16], w3[15 : 08], w0[07 : 00]};
ws2 = {w2[31 : 24], w3[23 : 16], w0[15 : 08], w1[07 : 00]};
ws3 = {w3[31 : 24], w0[23 : 16], w1[15 : 08], w2[07 : 00]};
shiftrows = {ws0, ws1, ws2, ws3};
end
endfunction // shiftrows
function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey);
begin
addroundkey = data ^ rkey;
end
endfunction // addroundkey
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [1 : 0] sword_ctr_reg;
reg [1 : 0] sword_ctr_new;
reg sword_ctr_we;
reg sword_ctr_inc;
reg sword_ctr_rst;
reg [3 : 0] round_ctr_reg;
reg [3 : 0] round_ctr_new;
reg round_ctr_we;
reg round_ctr_rst;
reg round_ctr_inc;
reg [127 : 0] block_new;
reg [31 : 0] block_w0_reg;
reg [31 : 0] block_w1_reg;
reg [31 : 0] block_w2_reg;
reg [31 : 0] block_w3_reg;
reg block_w0_we;
reg block_w1_we;
reg block_w2_we;
reg block_w3_we;
reg ready_reg;
reg ready_new;
reg ready_we;
reg [2 : 0] enc_ctrl_reg;
reg [2 : 0] enc_ctrl_new;
reg enc_ctrl_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [2 : 0] update_type;
reg [31 : 0] muxed_sboxw;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign round = round_ctr_reg;
assign sboxw = muxed_sboxw;
assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
assign ready = ready_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
block_w0_reg <= 32'h0;
block_w1_reg <= 32'h0;
block_w2_reg <= 32'h0;
block_w3_reg <= 32'h0;
sword_ctr_reg <= 2'h0;
round_ctr_reg <= 4'h0;
ready_reg <= 1'b1;
enc_ctrl_reg <= CTRL_IDLE;
end
else
begin
if (block_w0_we)
block_w0_reg <= block_new[127 : 096];
if (block_w1_we)
block_w1_reg <= block_new[095 : 064];
if (block_w2_we)
block_w2_reg <= block_new[063 : 032];
if (block_w3_we)
block_w3_reg <= block_new[031 : 000];
if (sword_ctr_we)
sword_ctr_reg <= sword_ctr_new;
if (round_ctr_we)
round_ctr_reg <= round_ctr_new;
if (ready_we)
ready_reg <= ready_new;
if (enc_ctrl_we)
enc_ctrl_reg <= enc_ctrl_new;
end
end // reg_update
//----------------------------------------------------------------
// round_logic
//
// The logic needed to implement init, main and final rounds.
//----------------------------------------------------------------
always @*
begin : round_logic
reg [127 : 0] old_block, shiftrows_block, mixcolumns_block;
reg [127 : 0] addkey_init_block, addkey_main_block, addkey_final_block;
block_new = 128'h0;
muxed_sboxw = 32'h0;
block_w0_we = 1'b0;
block_w1_we = 1'b0;
block_w2_we = 1'b0;
block_w3_we = 1'b0;
old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
shiftrows_block = shiftrows(old_block);
mixcolumns_block = mixcolumns(shiftrows_block);
addkey_init_block = addroundkey(block, round_key);
addkey_main_block = addroundkey(mixcolumns_block, round_key);
addkey_final_block = addroundkey(shiftrows_block, round_key);
case (update_type)
INIT_UPDATE:
begin
block_new = addkey_init_block;
block_w0_we = 1'b1;
block_w1_we = 1'b1;
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
SBOX_UPDATE:
begin
block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw};
case (sword_ctr_reg)
2'h0:
begin
muxed_sboxw = block_w0_reg;
block_w0_we = 1'b1;
end
2'h1:
begin
muxed_sboxw = block_w1_reg;
block_w1_we = 1'b1;
end
2'h2:
begin
muxed_sboxw = block_w2_reg;
block_w2_we = 1'b1;
end
2'h3:
begin
muxed_sboxw = block_w3_reg;
block_w3_we = 1'b1;
end
endcase // case (sbox_mux_ctrl_reg)
end
MAIN_UPDATE:
begin
block_new = addkey_main_block;
block_w0_we = 1'b1;
block_w1_we = 1'b1;
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
FINAL_UPDATE:
begin
block_new = addkey_final_block;
block_w0_we = 1'b1;
block_w1_we = 1'b1;
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
default:
begin
end
endcase // case (update_type)
end // round_logic
//----------------------------------------------------------------
// sword_ctr
//
// The subbytes word counter with reset and increase logic.
//----------------------------------------------------------------
always @*
begin : sword_ctr
sword_ctr_new = 2'h0;
sword_ctr_we = 1'b0;
if (sword_ctr_rst)
begin
sword_ctr_new = 2'h0;
sword_ctr_we = 1'b1;
end
else if (sword_ctr_inc)
begin
sword_ctr_new = sword_ctr_reg + 1'b1;
sword_ctr_we = 1'b1;
end
end // sword_ctr
//----------------------------------------------------------------
// round_ctr
//
// The round counter with reset and increase logic.
//----------------------------------------------------------------
always @*
begin : round_ctr
round_ctr_new = 4'h0;
round_ctr_we = 1'b0;
if (round_ctr_rst)
begin
round_ctr_new = 4'h0;
round_ctr_we = 1'b1;
end
else if (round_ctr_inc)
begin
round_ctr_new = round_ctr_reg + 1'b1;
round_ctr_we = 1'b1;
end
end // round_ctr
//----------------------------------------------------------------
// encipher_ctrl
//
// The FSM that controls the encipher operations.
//----------------------------------------------------------------
always @*
begin: encipher_ctrl
reg [3 : 0] num_rounds;
// Default assignments.
sword_ctr_inc = 1'b0;
sword_ctr_rst = 1'b0;
round_ctr_inc = 1'b0;
round_ctr_rst = 1'b0;
ready_new = 1'b0;
ready_we = 1'b0;
update_type = NO_UPDATE;
enc_ctrl_new = CTRL_IDLE;
enc_ctrl_we = 1'b0;
if (keylen == AES_256_BIT_KEY)
begin
num_rounds = AES256_ROUNDS;
end
else
begin
num_rounds = AES128_ROUNDS;
end
case(enc_ctrl_reg)
CTRL_IDLE:
begin
if (next)
begin
round_ctr_rst = 1'b1;
ready_new = 1'b0;
ready_we = 1'b1;
enc_ctrl_new = CTRL_INIT;
enc_ctrl_we = 1'b1;
end
end
CTRL_INIT:
begin
round_ctr_inc = 1'b1;
sword_ctr_rst = 1'b1;
update_type = INIT_UPDATE;
enc_ctrl_new = CTRL_SBOX;
enc_ctrl_we = 1'b1;
end
CTRL_SBOX:
begin
sword_ctr_inc = 1'b1;
update_type = SBOX_UPDATE;
if (sword_ctr_reg == 2'h3)
begin
enc_ctrl_new = CTRL_MAIN;
enc_ctrl_we = 1'b1;
end
end
CTRL_MAIN:
begin
sword_ctr_rst = 1'b1;
round_ctr_inc = 1'b1;
if (round_ctr_reg < num_rounds)
begin
update_type = MAIN_UPDATE;
enc_ctrl_new = CTRL_SBOX;
enc_ctrl_we = 1'b1;
end
else
begin
update_type = FINAL_UPDATE;
ready_new = 1'b1;
ready_we = 1'b1;
enc_ctrl_new = CTRL_IDLE;
enc_ctrl_we = 1'b1;
end
end
default:
begin
// Empty. Just here to make the synthesis tool happy.
end
endcase // case (enc_ctrl_reg)
end // encipher_ctrl
endmodule // aes_encipher_block
//======================================================================
// EOF aes_encipher_block.v
//======================================================================