URL
https://opencores.org/ocsvn/apbtoaes128/apbtoaes128/trunk
Subversion Repositories apbtoaes128
Compare Revisions
- This comparison shows the changes necessary to convert path
/apbtoaes128
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/testbench/tb_aes_ip.v
0,0 → 1,636
module tb_aes_ip(); |
|
localparam AES_CR = 4'd00; |
localparam AES_SR = 4'd01; |
localparam AES_DINR = 4'd02; |
localparam AES_DOUTR = 4'd03; |
localparam AES_KEYR0 = 4'd04; |
localparam AES_KEYR1 = 4'd05; |
localparam AES_KEYR2 = 4'd06; |
localparam AES_KEYR3 = 4'd07; |
localparam AES_IVR0 = 4'd08; |
localparam AES_IVR1 = 4'd09; |
localparam AES_IVR2 = 4'd10; |
localparam AES_IVR3 = 4'd11; |
|
// Configuratin Bits |
localparam DMAOUTEN = 32'h00000001 << 12; |
localparam DMAINEN = 32'h00000001 << 11; |
localparam ERRIE = 32'h00000001 << 10; |
localparam CCFIE = 32'h00000001 << 9; |
localparam ERRC = 32'h00000001 << 8; |
localparam CCFC = 32'h00000001 << 7; |
localparam EBC = 32'h00000000; |
localparam CBC = 32'h00000001 << 5; |
localparam CTR = 32'h00000001 << 6; |
localparam ENCRYPTION = 32'h00000000; |
localparam KEY_DERIV = 32'h00000001 << 3; |
localparam DECRYPTION = 32'h00000001 << 4; |
localparam KEY_DECRYP = KEY_DERIV | DECRYPTION; |
localparam ENABLE = 32'h00000001; |
localparam DISABLE = 32'h00000000; |
|
wire int_ccf, int_err; |
wire dma_req_wr, dma_req_rd; |
wire [31:0] PRDATA; |
|
reg [31:0] PWDATA; |
reg [3:0] PADDR; |
reg PCLK, PRESETn; |
reg PSEL, PENABLE, PWRITE; |
|
reg [31:0] data_rd; |
|
reg [127:0] data_in; |
reg [127:0] key_in; |
reg [127:0] iv_in; |
reg [127:0] result; |
reg [127:0] golden; |
reg [127:0] result_rd; |
reg [127:0] iv_rd; |
reg [127:0] key_rd; |
reg error_chk; |
|
aes_ip AES_IP |
( |
.int_ccf ( int_ccf ), |
.int_err ( int_err ), |
.dma_req_wr ( dma_req_wr ), |
.dma_req_rd ( dma_req_rd ), |
.PRDATA ( PRDATA ), |
.PREADY ( PREADY ), |
.PSLVERR ( PSLVERR ), |
.PWDATA ( PWDATA ), |
.PADDR ( PADDR ), |
.PSEL ( PSEL ), |
.PENABLE ( PENABLE ), |
.PWRITE ( PWRITE ), |
.PCLK ( PCLK ), |
.PRESETn ( PRESETn ) |
); |
initial |
begin |
$dumpfile("tb_aes_ip.vcd"); |
$dumpvars(0,tb_aes_ip); |
end |
task reset; |
begin |
PCLK = 0; |
PSEL = 0; |
PENABLE = 0; |
PWDATA = 0; |
PWRITE = 0; |
PADDR = 0; |
PRESETn = 0; |
@(posedge PCLK); |
PRESETn = 1; |
end |
endtask |
|
task apb_write; |
input [31:0] addr; |
input [31:0] data_in; |
begin |
PSEL <= 1; |
PWRITE <= 1; |
PENABLE <= 0; |
PADDR <= addr; |
PWDATA <= data_in; |
@(posedge PCLK); |
PENABLE <= 1; |
@(posedge PCLK); |
PSEL <= 0; |
PENABLE <= 0; |
end |
endtask |
|
task apb_read; |
input [31:0] addr; |
output [31:0] data_out; |
begin |
PSEL <= 1; |
PENABLE <= 0; |
PWRITE <= 0; |
PADDR <= addr; |
@(posedge PCLK); |
PENABLE <= 1; |
@(posedge PCLK); |
data_out = PRDATA; |
PENABLE <= 0; |
PSEL <= 0; |
end |
endtask |
|
task write_iv; |
input [127:0] iv_in; |
begin |
apb_write(AES_IVR0, iv_in[ 31:0]); |
apb_write(AES_IVR1, iv_in[ 63:32]); |
apb_write(AES_IVR2, iv_in[ 95:64]); |
apb_write(AES_IVR3, iv_in[127:96]); |
end |
endtask |
|
task read_iv; |
output [127:0] iv_out; |
begin |
apb_read(AES_IVR0, iv_out[ 31:0]); |
apb_read(AES_IVR1, iv_out[ 63:32]); |
apb_read(AES_IVR2, iv_out[ 95:64]); |
apb_read(AES_IVR3, iv_out[127:96]); |
end |
endtask |
|
task write_key; |
input [127:0] key_in; |
begin |
apb_write(AES_KEYR0, key_in[ 31:0]); |
apb_write(AES_KEYR1, key_in[ 63:32]); |
apb_write(AES_KEYR2, key_in[ 95:64]); |
apb_write(AES_KEYR3, key_in[127:96]); |
end |
endtask |
|
task read_key; |
output [127:0] key_out; |
begin |
apb_read(AES_KEYR0, key_out[ 31:0]); |
apb_read(AES_KEYR1, key_out[ 63:32]); |
apb_read(AES_KEYR2, key_out[ 95:64]); |
apb_read(AES_KEYR3, key_out[127:96]); |
end |
endtask |
|
task write_data; |
input [127:0] data_in; |
begin |
apb_write(AES_DINR, data_in[127:96]); |
apb_write(AES_DINR, data_in[ 95:64]); |
apb_write(AES_DINR, data_in[ 63:32]); |
apb_write(AES_DINR, data_in[ 31: 0]); |
end |
endtask |
|
task write_data_dma; |
input [127:0] data_in; |
begin |
@(posedge dma_req_wr); |
apb_write(AES_DINR, data_in[127:96]); |
@(posedge dma_req_wr); |
apb_write(AES_DINR, data_in[ 95:64]); |
@(posedge dma_req_wr); |
apb_write(AES_DINR, data_in[ 63:32]); |
@(posedge dma_req_wr); |
apb_write(AES_DINR, data_in[ 31: 0]); |
end |
endtask |
|
task read_data; |
output [127:0] data_rd; |
begin |
apb_read(AES_DOUTR, data_rd[127:96]); |
apb_read(AES_DOUTR, data_rd[ 95:64]); |
apb_read(AES_DOUTR, data_rd[ 63:32]); |
apb_read(AES_DOUTR, data_rd[ 31: 0]); |
end |
endtask |
|
task read_data_dma; |
output [127:0] data_rd; |
begin |
@(posedge dma_req_rd); |
apb_read(AES_DOUTR, data_rd[127:96]); |
@(posedge dma_req_rd); |
apb_read(AES_DOUTR, data_rd[ 95:64]); |
@(posedge dma_req_rd); |
apb_read(AES_DOUTR, data_rd[ 63:32]); |
@(posedge dma_req_rd); |
apb_read(AES_DOUTR, data_rd[ 31: 0]); |
end |
endtask |
|
task check_result; |
input [127:0] result; |
input [127:0] golden; |
output error; |
begin |
error = 0; |
if(result != golden) |
begin |
$display("TEST FAILED!"); |
$display("Expected %x, obtained %x", golden, result); |
error = 1; |
end |
end |
endtask |
|
integer i, error; |
|
initial |
begin |
reset; |
iv_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
key_in = 128'h00112233445566778899aabbccddeeff; |
write_iv(iv_in); |
read_iv(iv_rd); |
if(iv_rd != iv_in) |
begin |
$display("Access to IV register failed!"); |
$display("Expected %x, obtained %x", iv_in, iv_rd); |
$stop; |
end |
write_key(key_in); |
read_key(key_rd); |
if(key_rd != key_in) |
begin |
$display("Access to KEY register failed!"); |
$display("Expected %x, obtained %x", key_in, key_rd); |
$stop; |
end |
apb_write(AES_CR, ENABLE); |
write_key(128'd50); |
read_iv(data_rd); |
read_data(result); |
apb_write(AES_CR, DISABLE); |
apb_read(AES_SR, data_rd); |
apb_write(AES_CR, ERRC); |
|
//ECB TESTS |
//ENCRYPTION |
error = 0; |
data_in = 128'h00112233445566778899aabbccddeeff; |
key_in = 128'h000102030405060708090a0b0c0d0e0f; |
golden = 128'h69c4e0d86a7b0430d8cdb78070b4c55a; |
write_key(key_in); |
apb_write(AES_CR, ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
data_in = 128'h3243f6a8885a308d313198a2e0370734; |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
golden = 128'h3925841d02dc09fbdc118597196a0b32; |
apb_write(AES_CR, DISABLE); |
write_key(key_in); |
apb_write(AES_CR, ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// KEY DERIVATION |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
golden = 128'hd014f9a8c9ee2589e13f0cc8b6630ca6; |
apb_write(AES_CR, DISABLE); |
write_key(key_in); |
apb_write(AES_CR, KEY_DERIV | ENABLE | CCFIE); |
@(posedge int_ccf); |
@(posedge PCLK); |
read_key(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// DECRYPTION |
data_in = 128'h69c4e0d86a7b0430d8cdb78070b4c55a; |
key_in = 128'h13111d7fe3944a17f307a78b4d2b30c5; |
golden = 128'h00112233445566778899aabbccddeeff; |
apb_write(AES_CR, DISABLE); |
write_key(key_in); |
apb_write(AES_CR, DECRYPTION | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// DECCYPTION WITH DERIVATION |
data_in = 128'h69c4e0d86a7b0430d8cdb78070b4c55a; |
key_in = 128'h000102030405060708090a0b0c0d0e0f; |
golden = 128'h00112233445566778899aabbccddeeff; |
apb_write(AES_CR, DISABLE); |
write_key(key_in); |
apb_write(AES_CR, KEY_DECRYP | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
key_in = 128'h000102030405060708090a0b0c0d0e0f; |
apb_write(AES_CR, DISABLE); |
write_key(key_in); |
apb_write(AES_CR, KEY_DERIV | ENABLE | CCFIE); |
@(posedge int_ccf); |
data_in = 128'h69c4e0d86a7b0430d8cdb78070b4c55a; |
golden = 128'h00112233445566778899aabbccddeeff; |
apb_write(AES_CR, DISABLE); |
apb_write(AES_CR, DECRYPTION | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
if(!error) |
$display("ECB TEST PASSED!"); |
else |
$display("ECB TEST FAILED!\n Founded %d errors", error); |
|
// CBC Encryption |
error = 0; |
apb_write(AES_CR, DISABLE); |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
iv_in = 128'h000102030405060708090a0b0c0d0e0f; |
|
//BLOCK 1 |
data_in = 128'h6bc1bee22e409f96e93d7e117393172a; |
golden = 128'h7649abac8119b246cee98e9b12e9197d; |
write_key(key_in); |
write_iv(iv_in); |
apb_write(AES_CR, CBC | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 2 |
data_in = 128'hae2d8a571e03ac9c9eb76fac45af8e51; |
golden = 128'h5086cb9b507219ee95db113a917678b2; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 3 |
data_in = 128'h30c81c46a35ce411e5fbc1191a0a52ef; |
golden = 128'h73bed6b8e3c1743b7116e69e22229516; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 4 |
data_in = 128'hf69f2445df4f9b17ad2b417be66c3710; |
golden = 128'h3ff1caa1681fac09120eca307586e1a7; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// CBC DECRYPTION |
apb_write(AES_CR, DISABLE); |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
iv_in = 128'h000102030405060708090a0b0c0d0e0f; |
|
//BLOCK 1 |
data_in = 128'h7649abac8119b246cee98e9b12e9197d; |
golden = 128'h6bc1bee22e409f96e93d7e117393172a; |
write_key(key_in); |
write_iv(iv_in); |
apb_write(AES_CR, CBC | KEY_DECRYP | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 2 |
data_in = 128'h5086cb9b507219ee95db113a917678b2; |
golden = 128'hae2d8a571e03ac9c9eb76fac45af8e51 ; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 3 |
data_in = 128'h73bed6b8e3c1743b7116e69e22229516; |
golden = 128'h30c81c46a35ce411e5fbc1191a0a52ef ; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 4 |
data_in = 128'h3ff1caa1681fac09120eca307586e1a7; |
golden = 128'hf69f2445df4f9b17ad2b417be66c3710; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
if(!error) |
$display("CBC TEST PASSED!"); |
else |
$display("CBC TEST FAILED!\n Founded %d errors", error); |
|
// CTR Encryption |
error = 0; |
apb_write(AES_CR, DISABLE); |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
iv_in = 128'hf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff; |
|
//BLOCK 1 |
data_in = 128'h6bc1bee22e409f96e93d7e117393172a; |
golden = 128'h874d6191b620e3261bef6864990db6ce ; |
write_key(key_in); |
write_iv(iv_in); |
apb_write(AES_CR, CTR | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 2 |
data_in = 128'hae2d8a571e03ac9c9eb76fac45af8e51; |
golden = 128'h9806f66b7970fdff8617187bb9fffdff; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 3 |
data_in = 128'h30c81c46a35ce411e5fbc1191a0a52ef; |
golden = 128'h5ae4df3edbd5d35e5b4f09020db03eab; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 4 |
data_in = 128'hf69f2445df4f9b17ad2b417be66c3710; |
golden = 128'h1e031dda2fbe03d1792170a0f3009cee ; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// CTR DECRYPTION |
apb_write(AES_CR, DISABLE); |
iv_in = 128'hf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff; |
//BLOCK 1 |
data_in = 128'h874d6191b620e3261bef6864990db6ce; |
golden = 128'h6bc1bee22e409f96e93d7e117393172a; |
write_iv(iv_in); |
apb_write(AES_CR, CTR | KEY_DECRYP | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 2 |
data_in = 128'h9806f66b7970fdff8617187bb9fffdff; |
golden = 128'hae2d8a571e03ac9c9eb76fac45af8e51; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 3 |
data_in = 128'h5ae4df3edbd5d35e5b4f09020db03eab; |
golden = 128'h30c81c46a35ce411e5fbc1191a0a52ef; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 4 |
data_in = 128'h1e031dda2fbe03d1792170a0f3009cee; |
golden = 128'hf69f2445df4f9b17ad2b417be66c3710; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
if(!error) |
$display("CTR TEST PASSED!"); |
else |
$display("CTR TEST FAILED!\n Founded %d errors", error); |
|
error = 0; |
data_in = 128'h00112233445566778899aabbccddeeff; |
key_in = 128'h000102030405060708090a0b0c0d0e0f; |
golden = 128'h69c4e0d86a7b0430d8cdb78070b4c55a; |
write_key(key_in); |
apb_write(AES_CR, ENABLE | CCFIE); |
write_data(data_in); |
repeat(30) |
@(posedge PCLK); |
apb_write(AES_CR, DISABLE); |
// KEY DERIVATION |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
golden = 128'hd014f9a8c9ee2589e13f0cc8b6630ca6; |
write_key(key_in); |
apb_write(AES_CR, KEY_DERIV | ENABLE | CCFIE); |
@(posedge int_ccf); |
@(posedge PCLK); // A LEITURA DA CHAVE DEVE SER INICIADA UM CLOCK AP\D2S A SUBIDA DE CCF |
read_key(result); |
check_result(result, golden, error_chk); |
|
// TEST SUSPEND FUNCTIONALITY |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
iv_in = 128'h000102030405060708090a0b0c0d0e0f; |
|
//BLOCK 1 |
data_in = 128'h6bc1bee22e409f96e93d7e117393172a; |
golden = 128'h7649abac8119b246cee98e9b12e9197d; |
write_key(key_in); |
write_iv(iv_in); |
apb_write(AES_CR, CBC | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 2 |
data_in = 128'hae2d8a571e03ac9c9eb76fac45af8e51; |
golden = 128'h5086cb9b507219ee95db113a917678b2; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
//suspend processing |
apb_write(AES_CR, DISABLE); |
result_rd = result; |
read_iv(iv_rd); |
read_key(key_rd); |
|
//begin new processing |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
golden = 128'hd014f9a8c9ee2589e13f0cc8b6630ca6; |
write_key(key_in); |
apb_write(AES_CR, KEY_DERIV | ENABLE | CCFIE); |
@(posedge int_ccf); |
@(posedge PCLK); // A LEITURA DA CHAVE DEVE SER INICIADA UM CLOCK AP\D2S A SUBIDA DE CCF |
read_key(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
//continues processing |
// BLOCK 3 |
key_in = 128'h2b7e151628aed2a6abf7158809cf4f3c; |
apb_write(AES_CR, DISABLE); |
write_key(key_in); |
write_iv(result_rd); |
data_in = 128'h30c81c46a35ce411e5fbc1191a0a52ef; |
golden = 128'h73bed6b8e3c1743b7116e69e22229516; |
apb_write(AES_CR, CBC | ENABLE | CCFIE); |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
|
// BLOCK 4 |
data_in = 128'hf69f2445df4f9b17ad2b417be66c3710; |
golden = 128'h3ff1caa1681fac09120eca307586e1a7; |
write_data(data_in); |
@(posedge int_ccf); |
read_data(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
if(!error) |
$display("SUSPEND MODE TEST PASSED!"); |
else |
$display("SUSPEND MODE TEST FAILED!\n Founded %d errors", error); |
|
//DMA TEST |
error = 0; |
apb_write(AES_CR, DISABLE); |
data_in = 128'h00112233445566778899aabbccddeeff; |
key_in = 128'h000102030405060708090a0b0c0d0e0f; |
golden = 128'h69c4e0d86a7b0430d8cdb78070b4c55a; |
write_key(key_in); |
apb_write(AES_CR, DMAINEN | DMAOUTEN | ENABLE | CCFIE); |
write_data_dma(data_in); |
@(posedge int_ccf); |
read_data_dma(result); |
check_result(result, golden, error_chk); |
error = error + error_chk; |
if(!error) |
$display("DMA TEST PASSED!"); |
else |
$display("DMA TEST FAILED!\n Founded %d errors", error); |
$stop; |
end |
|
always #10 |
PCLK = !PCLK; |
endmodule |
/trunk/rtl/sBox.v
0,0 → 1,97
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module sBox |
#( |
parameter SBOX_NUM = 4 |
)( |
//OUTPUTS |
output [8*SBOX_NUM - 1:0] sbox_out_enc, |
output [8*SBOX_NUM - 1:0] sbox_out_dec, |
//INPUTS |
input [8*SBOX_NUM - 1:0] sbox_in, |
input enc_dec, |
input clk |
); |
sBox_8 SBOX[SBOX_NUM - 1:0] |
( |
.sbox_out_enc ( sbox_out_enc ), |
.sbox_out_dec ( sbox_out_dec ), |
.sbox_in ( sbox_in ), |
.enc_dec ( enc_dec ), |
.clk ( clk ) |
); |
|
endmodule |
/trunk/rtl/host_interface.v
0,0 → 1,447
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module host_interface |
( |
// OUTPUTS |
output [3:0] key_en, |
output [1:0] col_addr, |
output [1:0] chmod, |
output [1:0] mode, |
output [1:0] data_type, |
output col_wr_en, |
output col_rd_en, |
output [1:0] key_sel, |
output [3:0] iv_en, |
output [3:0] iv_sel, |
output int_ccf, |
output int_err, |
output disable_core, |
output reg first_block, |
output dma_req_wr, |
output dma_req_rd, |
output reg start_core, |
output [31:0] PRDATA, |
//INPUTS |
input [3:0] PADDR, |
input [31:0] PWDATA, |
input PWRITE, |
input PENABLE, |
input PSEL, |
input PCLK, |
input PRESETn, |
input [31:0] key_bus, |
input [31:0] col_bus, |
input [31:0] iv_bus, |
input ccf_set |
); |
|
//`include "include/host_interface.vh" |
|
//===================================================================================== |
// Memory Mapped Registers Address |
//===================================================================================== |
localparam AES_CR = 4'd00; |
localparam AES_SR = 4'd01; |
localparam AES_DINR = 4'd02; |
localparam AES_DOUTR = 4'd03; |
localparam AES_KEYR0 = 4'd04; |
localparam AES_KEYR1 = 4'd05; |
localparam AES_KEYR2 = 4'd06; |
localparam AES_KEYR3 = 4'd07; |
localparam AES_IVR0 = 4'd08; |
localparam AES_IVR1 = 4'd09; |
localparam AES_IVR2 = 4'd10; |
localparam AES_IVR3 = 4'd11; |
|
//============================================================================= |
// Operation Modes |
//============================================================================= |
localparam ENCRYPTION = 2'b00; |
localparam KEY_DERIVATION = 2'b01; |
localparam DECRYPTION = 2'b10; |
localparam DECRYP_W_DERIV = 2'b11; |
|
//============================================================================= |
// AES Modes |
//============================================================================= |
localparam ECB = 2'b00; |
localparam CBC = 2'b01; |
localparam CTR = 2'b10; |
|
//============================================================================= |
// Resets Values |
//============================================================================= |
localparam AES_CR_RESET = 13'd0; |
localparam AES_SR_RESET = 3'd0; |
|
//============================================================================= |
// Enable Value (Active High) |
//============================================================================= |
localparam ENABLE = 1'b1; |
localparam DISABLE = 1'b0; |
|
//============================================================================= |
// FSM STATES |
//============================================================================= |
localparam IDLE = 3'd0; |
localparam INPUT = 3'd1; |
localparam START = 3'd2; |
localparam WAIT = 3'd3; |
localparam OUTPUT = 3'd4; |
|
reg [31:0] bus_out; |
reg [31:0] bus_out_mux; |
reg cnt_en; |
reg enable_clear; |
reg access_permission; |
reg first_block_set; |
reg first_block_clear; |
wire [1:0] mode_in; |
wire [1:0] chmod_in; |
wire write_en; |
wire read_en; |
wire dma_out_en; |
wire dma_in_en; |
wire err_ie; |
wire ccf_ie; |
wire errc; |
wire ccfc; |
wire aes_cr_wr_en; |
wire wr_err_en; |
wire rd_err_en; |
wire write_completed; |
wire read_completed; |
wire key_deriv; |
|
|
reg [10:0] aes_cr; |
reg wr_err; |
reg rd_err; |
reg ccf; |
reg [2:0] state, next_state; |
reg [1:0] cnt; |
reg dma_req; |
|
// Write and read enable signals |
assign write_en = PSEL & PENABLE & PWRITE; |
assign read_en = PSEL & ~PWRITE; |
|
// Configuration Register Logic |
assign dma_out_en = aes_cr[10]; |
assign dma_in_en = aes_cr[9]; |
assign err_ie = aes_cr[8]; |
assign ccf_ie = aes_cr[7]; |
assign errc = PWDATA[8]; |
assign ccfc = PWDATA[7]; |
assign chmod = aes_cr[6:5]; |
assign mode = aes_cr[4:3]; |
assign data_type = aes_cr[2:1]; |
assign enable = aes_cr[0]; |
|
assign aes_cr_wr_en = (PADDR == AES_CR) & write_en; |
assign mode_in = PWDATA[4:3]; |
assign chmod_in = PWDATA[6:5]; |
|
always @(posedge PCLK, negedge PRESETn) |
begin |
if(!PRESETn) |
aes_cr <= AES_CR_RESET; |
else |
begin |
if(enable_clear) |
aes_cr[0] <= 1'b0; |
else |
if(aes_cr_wr_en) |
aes_cr[0] <= PWDATA[0]; |
|
if(aes_cr_wr_en && access_permission) |
begin |
aes_cr[2:1] <= PWDATA[2:1]; |
if(mode_in == DECRYP_W_DERIV && chmod_in == CTR) |
aes_cr[4:3] <= DECRYPTION; |
else |
aes_cr[4:3] <= mode_in; |
aes_cr[ 6:5] <= PWDATA[6:5]; |
aes_cr[10:7] <= PWDATA[12:9]; |
end |
end |
end |
|
// Status Register Logic |
assign aes_sr_wr_en = (PADDR == AES_SR) & write_en & access_permission; |
|
always @(posedge PCLK, negedge PRESETn) |
begin |
if(!PRESETn) |
{wr_err, rd_err, ccf} <= AES_SR_RESET; |
else |
begin |
// Write Error Flag |
if(wr_err_en) |
wr_err <= 1'b1; |
else |
if(errc && aes_cr_wr_en && access_permission) |
wr_err <= 1'b0; |
|
//Read Error Flag |
if(rd_err_en) |
rd_err <= 1'b1; |
else |
if(errc && aes_cr_wr_en && access_permission) |
rd_err <= 1'b0; |
|
// Computation Complete Flag |
if(ccf_set) |
ccf <= 1'b1; |
else |
if(ccfc && aes_cr_wr_en)// && access_permission) |
ccf <= 1'b0; |
end |
end |
// Interruption on erros Signals |
assign int_ccf = ccf_ie & ccf_set; |
assign int_err = (wr_err_en | rd_err_en) & err_ie; |
|
// Key Signals Decoding |
assign key_en = (4'b1000 >> PADDR[1:0]) & {4{(~PADDR[3] & PADDR[2] & access_permission & write_en)}}; |
assign key_sel = ~PADDR[1:0] & {2{(PADDR[2] & access_permission)}}; |
|
// IV Signals Decoding |
assign iv_sel = (4'b1000 >> PADDR[1:0]) & {4{(PADDR[3] & ~PADDR[2] & access_permission)}}; |
assign iv_en = iv_sel & {4{write_en}}; |
|
// State Register |
always @(posedge PCLK, negedge PRESETn) |
begin |
if(!PRESETn) |
state <= IDLE; |
else |
if(!enable) |
state <= IDLE; |
else |
state <= next_state; |
end |
|
assign write_completed = (cnt == 2'b11); |
assign read_completed = (cnt == 2'b11); |
assign key_deriv = (mode == KEY_DERIVATION); |
|
// Next State Logic |
always @(*) |
begin |
next_state = state; |
case(state) |
IDLE : |
begin |
if(enable) |
next_state = (key_deriv) ? START : INPUT; |
end |
INPUT : |
next_state = (write_completed && cnt_en) ? START : INPUT; |
START : |
next_state = WAIT; |
WAIT : |
begin |
if(ccf_set) |
next_state = (key_deriv) ? IDLE : OUTPUT; |
end |
OUTPUT: |
next_state = (read_completed && cnt_en) ? INPUT : OUTPUT; |
endcase |
end |
|
// Output Logic |
assign disable_core = ~enable; |
|
always @(*) |
begin |
access_permission = DISABLE; |
start_core = DISABLE; |
cnt_en = DISABLE; |
enable_clear = DISABLE; |
first_block_set = DISABLE; |
first_block_clear = DISABLE; |
case(state) |
IDLE: |
begin |
access_permission = ENABLE; |
first_block_set = ENABLE; |
if(enable && !key_deriv) |
cnt_en = ENABLE; |
end |
INPUT: |
begin |
if(PADDR == AES_DINR && write_en) |
cnt_en = ENABLE; |
end |
START: |
begin |
start_core = ENABLE; |
end |
WAIT: |
begin |
if(ccf_set) |
cnt_en = ENABLE; |
if(ccf_set && key_deriv) |
enable_clear = ENABLE; |
end |
OUTPUT: |
begin |
first_block_clear = ENABLE; |
if(PADDR == AES_DOUTR && read_en && PENABLE )//|| write_completed) |
cnt_en = ENABLE; |
end |
endcase |
end |
|
// First Block Signal indicates when IV register is used |
always @(posedge PCLK, negedge PRESETn) |
begin |
if(!PRESETn) |
first_block <= 1'b1; |
else |
if(first_block_set) |
first_block <= 1'b1; |
else |
if(first_block_clear) |
first_block <= 1'b0; |
end |
|
always @(posedge PCLK, negedge PRESETn) |
begin |
if(!PRESETn) |
cnt <= 2'b11; |
else |
begin |
if(!enable || state == START) |
cnt <= 2'b11; |
else |
if(cnt_en) |
cnt <= cnt + 1'b1; |
end |
end |
|
assign col_addr = cnt; |
assign col_wr_en = (PADDR == AES_DINR && write_en && state == INPUT); |
assign col_rd_en = (PADDR == AES_DOUTR && read_en && state == OUTPUT); |
assign wr_err_en = (PADDR == AES_DINR && write_en && (state != INPUT && state != IDLE)); |
assign rd_err_en = (PADDR == AES_DOUTR && read_en && (state != OUTPUT && state != IDLE)); |
|
// DMA Requests Logic |
always @(posedge PCLK, negedge PRESETn) |
begin |
if(!PRESETn) |
dma_req <= 0; |
else |
dma_req <= cnt[0]; |
end |
|
assign dma_req_wr = (dma_req ^ cnt[0]) & dma_in_en & enable & (state == INPUT || state == IDLE); |
assign dma_req_rd = (dma_req ^ cnt[0]) & dma_out_en & enable & (state == OUTPUT); |
|
// APB Read Signal |
assign PRDATA = bus_out; |
|
// Output Mux |
always @(*) |
begin |
bus_out_mux = 32'd0; |
case(PADDR) |
AES_CR: |
bus_out_mux = {{19{1'b0}}, aes_cr[10:7], 2'b00, aes_cr[6:0]}; |
AES_SR: |
bus_out_mux = {{29{1'b0}}, wr_err, rd_err, ccf}; |
AES_DINR, AES_DOUTR: |
bus_out_mux = col_bus; |
AES_KEYR0, AES_KEYR1, AES_KEYR2, AES_KEYR3: |
bus_out_mux = key_bus; |
AES_IVR0, AES_IVR1, AES_IVR2, AES_IVR3: |
if(!enable) |
bus_out_mux = iv_bus; |
endcase |
end |
|
// The output Bus is registered |
always @(posedge PCLK, negedge PRESETn) |
begin |
if(!PRESETn) |
bus_out <= 32'd0; |
else |
if(read_en) |
bus_out <= bus_out_mux; |
end |
|
endmodule |
/trunk/rtl/mix_columns.v
0,0 → 1,142
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module mix_columns |
( |
// OUTPUTS |
output [31:0] mix_out_enc, |
output [31:0] mix_out_dec, |
// INPUTS |
input [31:0] mix_in |
); |
|
localparam SIZE = 32; |
localparam WORD_SIZE = 8; |
localparam NUM_WORDS = 4; |
|
wire [WORD_SIZE - 1 : 0] col [0 : NUM_WORDS - 1]; |
wire [WORD_SIZE - 1 : 0] sum_p[0 : NUM_WORDS - 1]; |
wire [WORD_SIZE - 1 : 0] y [0 : NUM_WORDS - 2]; |
|
//===================================================================================== |
// Multiplication by 02 in GF(2^8) |
//===================================================================================== |
function [7:0] aes_mult_02; |
input [7:0] data_in; |
begin |
aes_mult_02 = (data_in << 1) ^ {8{data_in[7]}} & 8'h1b; |
end |
endfunction |
|
//===================================================================================== |
// Multiplication by 04 in GF(2^8) |
//===================================================================================== |
function [7:0] aes_mult_04; |
input [7:0] data_in; |
begin |
aes_mult_04 = ((data_in << 2) ^ {8{data_in[6]}} & 8'h1b) ^ {8{data_in[7]}} & 8'h36; |
end |
endfunction |
|
//===================================================================================== |
// Word to Byte transformation |
//===================================================================================== |
generate |
genvar i; |
for(i = 0 ; i < NUM_WORDS; i = i + 1) |
assign col[i] = mix_in[WORD_SIZE*(i + 1) - 1: WORD_SIZE*i]; |
endgenerate |
|
//===================================================================================== |
// Direct Mix Column Operation |
//===================================================================================== |
generate |
genvar j; |
for(j = 0; j < NUM_WORDS; j = j + 1) |
begin |
assign sum_p[j] = col[(j + 1)%NUM_WORDS] ^ col[(j + 2)%NUM_WORDS] ^ col[(j + 3)%NUM_WORDS]; |
assign mix_out_enc[ WORD_SIZE*(j + 1) - 1 : WORD_SIZE*j] = aes_mult_02(col[j] ^ col[(j + NUM_WORDS - 1)%NUM_WORDS]) ^ sum_p[j]; |
end |
endgenerate |
|
//===================================================================================== |
// Inverse Mix Column Operation |
//===================================================================================== |
assign y[0] = aes_mult_04(col[2] ^ col[0]); |
assign y[1] = aes_mult_04(col[3] ^ col[1]); |
assign y[2] = aes_mult_02( y[1] ^ y[0]); |
assign mix_out_dec = mix_out_enc ^ {2{y[2] ^ y[1], y[2] ^ y[0]}}; |
|
endmodule |
/trunk/rtl/key_expander.v
0,0 → 1,175
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module key_expander |
( |
// OUTPUTS |
output [127:0] key_out, |
output [ 31:0] g_in, |
// INPUTS |
input [ 31:0] g_out, |
input [127:0] key_in, |
input [ 3:0] round, |
input add_w_out, |
input enc_dec |
); |
|
localparam KEY_WIDTH = 32; |
localparam KEY_NUM = 4; |
localparam WORD = 8; |
localparam ROUNDS = 10; |
|
wire [KEY_WIDTH - 1 : 0] key [0 : KEY_NUM - 1]; |
wire [ WORD - 1 : 0] rot_in[0 : KEY_NUM - 1]; |
wire [KEY_WIDTH - 1 : 0] g_func; |
reg [ WORD - 1 : 0] rc_dir, rc_inv; |
wire [ WORD - 1 : 0] rc; |
|
//===================================================================================== |
// Key Generation |
//===================================================================================== |
generate |
genvar i; |
for(i = 0; i < KEY_NUM; i = i + 1) |
begin |
assign key[KEY_NUM - 1 - i] = key_in[KEY_WIDTH*(i + 1) - 1 : KEY_WIDTH*i]; |
end |
endgenerate |
|
//===================================================================================== |
// Key Out Generation |
//===================================================================================== |
generate |
genvar j; |
for(j = 0; j < KEY_NUM; j = j + 1) |
begin |
if(j == 0) |
assign key_out[KEY_WIDTH*(KEY_NUM - j) - 1 : KEY_WIDTH*(KEY_NUM - j - 1)] = key[j] ^ g_func; |
else |
if(j == 1) |
assign key_out[KEY_WIDTH*(KEY_NUM - j) - 1 : KEY_WIDTH*(KEY_NUM - j - 1)] = (add_w_out) ? key[j] ^ key[j - 1] ^ g_func : key[j] ^ key[j - 1]; |
else |
assign key_out[KEY_WIDTH*(KEY_NUM - j) - 1 : KEY_WIDTH*(KEY_NUM - j - 1)] = key[j] ^ key[j - 1]; |
end |
endgenerate |
|
//===================================================================================== |
// G Function Input Generation |
//===================================================================================== |
generate |
genvar k; |
for(k = 0; k < KEY_NUM; k = k + 1) |
assign rot_in[k] = (enc_dec) ? key[KEY_NUM - 1][WORD*(k + 1) - 1 : WORD*k] : key[KEY_NUM - 1][WORD*(k + 1) - 1 : WORD*k] ^ key[KEY_NUM - 2][WORD*(k + 1) - 1 : WORD*k]; |
endgenerate |
|
generate |
genvar l; |
for(l = 0; l < KEY_NUM; l = l + 1) |
assign g_in[WORD*(l + 1) - 1 : WORD*l] = rot_in[(KEY_NUM + l - 1)%KEY_NUM]; |
endgenerate |
|
//===================================================================================== |
// G Functin Output Processsing |
//===================================================================================== |
assign g_func = {g_out[KEY_WIDTH - 1 : KEY_WIDTH - WORD] ^ rc, g_out[KEY_WIDTH - WORD - 1 : 0]}; |
|
assign rc = (enc_dec) ? rc_dir : rc_inv; |
|
always @(*) |
begin: RC_DIR |
integer i; |
for(i = 0; i < ROUNDS; i = i + 1) |
if(round == 8) |
rc_dir = 8'h1b; |
else |
if(round == 9) |
rc_dir = 8'h36; |
else |
rc_dir = 8'h01 << round; |
end |
|
always @(*) |
begin: RC_INV |
integer i; |
for(i = 0; i < ROUNDS; i = i + 1) |
if(round == 1) |
rc_inv = 8'h1b; |
else |
if(round == 0) |
rc_inv = 8'h36; |
else |
rc_inv = 8'h80 >> (round - 2); |
end |
endmodule |
/trunk/rtl/control_unit.v
0,0 → 1,573
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module control_unit |
( |
output reg [ 2:0] sbox_sel, |
output reg [ 1:0] rk_sel, |
output reg [ 1:0] key_out_sel, |
output reg [ 1:0] col_sel, |
output reg [ 3:0] key_en, |
output reg [ 3:0] col_en, |
output [ 3:0] round, |
output reg bypass_rk, |
output reg bypass_key_en, |
output reg key_sel, |
output reg iv_cnt_en, |
output reg iv_cnt_sel, |
output reg key_derivation_en, |
output reg end_comp, |
output key_init, |
output key_gen, |
output mode_ctr, |
output mode_cbc, |
output last_round, |
output encrypt_decrypt, |
input [1:0] operation_mode, |
input [1:0] aes_mode, |
input start, |
input disable_core, |
input clk, |
input rst_n |
); |
//`include "include/host_interface.vh" |
//`include "include/control_unit_params.vh" |
|
//===================================================================================== |
// Memory Mapped Registers Address |
//===================================================================================== |
localparam AES_CR = 4'd00; |
localparam AES_SR = 4'd01; |
localparam AES_DINR = 4'd02; |
localparam AES_DOUTR = 4'd03; |
localparam AES_KEYR0 = 4'd04; |
localparam AES_KEYR1 = 4'd05; |
localparam AES_KEYR2 = 4'd06; |
localparam AES_KEYR3 = 4'd07; |
localparam AES_IVR0 = 4'd08; |
localparam AES_IVR1 = 4'd09; |
localparam AES_IVR2 = 4'd10; |
localparam AES_IVR3 = 4'd11; |
|
//============================================================================= |
// Operation Modes |
//============================================================================= |
localparam ENCRYPTION = 2'b00; |
localparam KEY_DERIVATION = 2'b01; |
localparam DECRYPTION = 2'b10; |
localparam DECRYP_W_DERIV = 2'b11; |
|
//============================================================================= |
// AES Modes |
//============================================================================= |
localparam ECB = 2'b00; |
localparam CBC = 2'b01; |
localparam CTR = 2'b10; |
|
//============================================================================= |
// SBOX SEL |
//============================================================================= |
localparam COL_0 = 3'b000; |
localparam COL_1 = 3'b001; |
localparam COL_2 = 3'b010; |
localparam COL_3 = 3'b011; |
localparam G_FUNCTION = 3'b100; |
|
//============================================================================= |
// RK_SEL |
//============================================================================= |
localparam COL = 2'b00; |
localparam MIXCOL_IN = 2'b01; |
localparam MIXCOL_OUT = 2'b10; |
|
//============================================================================= |
// KEY_OUT_SEL |
//============================================================================= |
localparam KEY_0 = 2'b00; |
localparam KEY_1 = 2'b01; |
localparam KEY_2 = 2'b10; |
localparam KEY_3 = 2'b11; |
|
//============================================================================= |
// COL_SEL |
//============================================================================= |
localparam SHIFT_ROWS = 2'b00; |
localparam ADD_RK_OUT = 2'b01; |
localparam INPUT = 2'b10; |
|
//============================================================================= |
// KEY_SEL |
//============================================================================= |
localparam KEY_HOST = 1'b0; |
localparam KEY_OUT = 1'b1; |
|
//============================================================================= |
// KEY_EN |
//============================================================================= |
localparam KEY_DIS = 4'b0000; |
localparam EN_KEY_0 = 4'b0001; |
localparam EN_KEY_1 = 4'b0010; |
localparam EN_KEY_2 = 4'b0100; |
localparam EN_KEY_3 = 4'b1000; |
localparam KEY_ALL = 4'b1111; |
|
//============================================================================= |
// COL_EN |
//============================================================================= |
localparam COL_DIS = 4'b0000; |
localparam EN_COL_0 = 4'b0001; |
localparam EN_COL_1 = 4'b0010; |
localparam EN_COL_2 = 4'b0100; |
localparam EN_COL_3 = 4'b1000; |
localparam COL_ALL = 4'b1111; |
|
//============================================================================= |
// IV_CNT_SEL |
//============================================================================= |
localparam IV_CNT = 1'b1; |
localparam IV_BUS = 1'b0; |
|
//============================================================================= |
// ENABLES |
//============================================================================= |
localparam ENABLE = 1'b1; |
localparam DISABLE = 1'b0; |
|
localparam NUMBER_ROUND = 4'd10; |
localparam NUMBER_ROUND_INC = 4'd11; |
localparam INITIAL_ROUND = 4'd00; |
|
//============================================================================= |
// FSM STATES |
//============================================================================= |
localparam IDLE = 4'd00; |
localparam ROUND0_COL0 = 4'd01; |
localparam ROUND0_COL1 = 4'd02; |
localparam ROUND0_COL2 = 4'd03; |
localparam ROUND0_COL3 = 4'd04; |
localparam ROUND_KEY0 = 4'd05; |
localparam ROUND_COL0 = 4'd06; |
localparam ROUND_COL1 = 4'd07; |
localparam ROUND_COL2 = 4'd08; |
localparam ROUND_COL3 = 4'd09; |
localparam READY = 4'd10; |
localparam GEN_KEY0 = 4'd11; |
localparam GEN_KEY1 = 4'd12; |
localparam GEN_KEY2 = 4'd13; |
localparam GEN_KEY3 = 4'd14; |
localparam NOP = 4'd15; |
|
reg [3:0] state, next_state; |
reg [3:0] rd_count; |
|
reg rd_count_en; |
wire op_key_derivation; |
wire first_round; |
wire [1:0] op_mode; |
|
// State Flops Definition |
always @(posedge clk, negedge rst_n) |
begin |
if(!rst_n) |
state <= IDLE; |
else |
if(disable_core) |
state <= IDLE; |
else |
state <= next_state; |
end |
|
assign encrypt_decrypt = (op_mode == ENCRYPTION || op_mode == KEY_DERIVATION || |
state == GEN_KEY0 || state == GEN_KEY1 || |
state == GEN_KEY2 || state == GEN_KEY3 ); |
|
assign enc_dec = encrypt_decrypt | mode_ctr; |
assign key_gen = (state == ROUND_KEY0); |
|
assign op_key_derivation = (op_mode == KEY_DERIVATION); |
|
assign mode_ctr = (aes_mode == CTR); |
assign mode_cbc = (aes_mode == CBC); |
|
assign key_init = start; |
|
assign op_mode = (mode_ctr) ? ENCRYPTION : operation_mode; |
|
// Next State Logic |
always @(*) |
begin |
next_state = state; |
case(state) |
IDLE: |
begin |
if(!start) |
next_state = IDLE; |
else |
case(op_mode) |
ENCRYPTION : next_state = ROUND0_COL0; |
DECRYPTION : next_state = ROUND0_COL3; |
KEY_DERIVATION: next_state = GEN_KEY0; |
DECRYP_W_DERIV: next_state = GEN_KEY0; |
default : next_state = IDLE; |
endcase |
end |
ROUND0_COL0: |
begin |
next_state = (enc_dec) ? ROUND0_COL1 : ROUND_KEY0; |
end |
ROUND0_COL1: |
begin |
next_state = (enc_dec) ? ROUND0_COL2 : ROUND0_COL0; |
end |
ROUND0_COL2: |
begin |
next_state = (enc_dec) ? ROUND0_COL3 : ROUND0_COL1; |
end |
ROUND0_COL3: |
begin |
next_state = (enc_dec) ? ROUND_KEY0 : ROUND0_COL2; |
end |
ROUND_KEY0 : |
begin |
if(!first_round) |
begin |
next_state = (last_round) ? READY : NOP; |
end |
else |
begin |
next_state = (enc_dec) ? ROUND_COL0 : ROUND_COL3; |
end |
end |
NOP : |
begin |
next_state = (enc_dec) ? ROUND_COL0 : ROUND_COL3; |
end |
ROUND_COL0 : |
begin |
next_state = (enc_dec) ? ROUND_COL1 : ROUND_KEY0; |
end |
ROUND_COL1 : |
begin |
next_state = (enc_dec) ? ROUND_COL2 : ROUND_COL0; |
end |
ROUND_COL2 : |
begin |
next_state = (enc_dec) ? ROUND_COL3 : ROUND_COL1; |
end |
ROUND_COL3 : |
begin |
if(last_round && enc_dec) |
next_state = READY; |
else |
next_state = (enc_dec) ? ROUND_KEY0 : ROUND_COL2; |
end |
GEN_KEY0 : |
begin |
next_state = GEN_KEY1; |
end |
GEN_KEY1 : |
begin |
next_state = GEN_KEY2; |
end |
GEN_KEY2 : |
begin |
next_state = GEN_KEY3; |
end |
GEN_KEY3 : |
begin |
if(last_round) |
next_state = (op_key_derivation) ? READY : ROUND0_COL3; |
else |
next_state = GEN_KEY0; |
end |
READY : |
begin |
next_state = IDLE; |
end |
endcase |
end |
|
|
// Output Logic |
always @(*) |
begin |
sbox_sel = COL_0; |
rk_sel = COL; |
bypass_rk = DISABLE; |
key_out_sel = KEY_0; |
col_sel = INPUT; |
key_sel = KEY_HOST; |
key_en = KEY_DIS; |
col_en = COL_DIS; |
rd_count_en = DISABLE; |
iv_cnt_en = DISABLE; |
iv_cnt_sel = IV_BUS; |
bypass_key_en = DISABLE; |
key_derivation_en = DISABLE; |
end_comp = DISABLE; |
case(state) |
ROUND0_COL0: |
begin |
sbox_sel = COL_0; |
rk_sel = COL; |
bypass_rk = ENABLE; |
bypass_key_en = ENABLE; |
key_out_sel = KEY_0; |
col_sel = (enc_dec) ? ADD_RK_OUT : SHIFT_ROWS; |
col_en = (enc_dec) ? EN_COL_0 : COL_ALL; |
end |
ROUND0_COL1: |
begin |
sbox_sel = COL_1; |
rk_sel = COL; |
bypass_rk = ENABLE; |
bypass_key_en = ENABLE; |
key_out_sel = KEY_1; |
col_sel = ADD_RK_OUT; |
col_en = EN_COL_1; |
if(!enc_dec) |
begin |
key_sel = KEY_OUT; |
key_en = EN_KEY_1; |
end |
end |
ROUND0_COL2: |
begin |
sbox_sel = COL_2; |
rk_sel = COL; |
bypass_rk = ENABLE; |
bypass_key_en = ENABLE; |
key_out_sel = KEY_2; |
col_sel = ADD_RK_OUT; |
col_en = EN_COL_2; |
if(!enc_dec) |
begin |
key_sel = KEY_OUT; |
key_en = EN_KEY_2; |
end |
end |
ROUND0_COL3: |
begin |
sbox_sel = COL_3; |
rk_sel = COL; |
bypass_key_en = ENABLE; |
key_out_sel = KEY_3; |
col_sel = (enc_dec) ? SHIFT_ROWS : ADD_RK_OUT; |
col_en = (enc_dec) ? COL_ALL : EN_COL_3; |
bypass_rk = ENABLE; |
if(!enc_dec) |
begin |
key_sel = KEY_OUT; |
key_en = EN_KEY_3; |
end |
end |
ROUND_KEY0: |
begin |
sbox_sel = G_FUNCTION; |
key_sel = KEY_OUT; |
key_en = EN_KEY_0; |
rd_count_en = ENABLE; |
end |
ROUND_COL0: |
begin |
sbox_sel = COL_0; |
rk_sel = (last_round) ? MIXCOL_IN : MIXCOL_OUT; |
key_out_sel = KEY_0; |
key_sel = KEY_OUT; |
if(enc_dec) |
key_en = EN_KEY_1; |
if((mode_cbc && last_round && !enc_dec) || (mode_ctr && last_round)) |
col_sel = INPUT; |
else |
begin |
if(!enc_dec) |
col_sel = (last_round) ? ADD_RK_OUT : SHIFT_ROWS; |
else |
col_sel = ADD_RK_OUT; |
end |
if(enc_dec) |
col_en = EN_COL_0; |
else |
col_en = (last_round) ? EN_COL_0 : COL_ALL; |
end |
ROUND_COL1: |
begin |
sbox_sel = COL_1; |
rk_sel = (last_round) ? MIXCOL_IN : MIXCOL_OUT; |
key_out_sel = KEY_1; |
key_sel = KEY_OUT; |
if(enc_dec) |
key_en = EN_KEY_2; |
else |
key_en = EN_KEY_1; |
if((mode_cbc && last_round && !enc_dec) || (mode_ctr && last_round)) |
col_sel = INPUT; |
else |
col_sel = ADD_RK_OUT; |
col_en = EN_COL_1; |
end |
ROUND_COL2: |
begin |
sbox_sel = COL_2; |
rk_sel = (last_round) ? MIXCOL_IN : MIXCOL_OUT; |
key_out_sel = KEY_2; |
key_sel = KEY_OUT; |
if(enc_dec) |
key_en = EN_KEY_3; |
else |
key_en = EN_KEY_2; |
if((mode_cbc && last_round && !enc_dec) || (mode_ctr && last_round)) |
col_sel = INPUT; |
else |
col_sel = ADD_RK_OUT; |
col_en = EN_COL_2; |
end |
ROUND_COL3: |
begin |
sbox_sel = COL_3; |
rk_sel = (last_round) ? MIXCOL_IN : MIXCOL_OUT; |
key_out_sel = KEY_3; |
key_sel = KEY_OUT; |
if(!enc_dec) |
key_en = EN_KEY_3; |
if((mode_cbc && last_round && !enc_dec) || (mode_ctr && last_round)) |
col_sel = INPUT; |
else |
begin |
if(enc_dec) |
col_sel = (last_round) ? ADD_RK_OUT : SHIFT_ROWS; |
else |
col_sel = ADD_RK_OUT; |
end |
if(enc_dec) |
col_en = (last_round) ? EN_COL_3 : COL_ALL; |
else |
col_en = EN_COL_3; |
if(mode_ctr && last_round) |
begin |
iv_cnt_en = ENABLE; |
iv_cnt_sel = IV_CNT; |
end |
end |
GEN_KEY0: |
begin |
sbox_sel = G_FUNCTION; |
rd_count_en = ENABLE; |
end |
GEN_KEY1: |
begin |
key_en = EN_KEY_1 | EN_KEY_0; //Enable key 0 AND key 1 |
key_sel = KEY_OUT; |
bypass_key_en = ENABLE; |
end |
GEN_KEY2: |
begin |
key_en = EN_KEY_2; |
key_sel = KEY_OUT; |
bypass_key_en = ENABLE; |
end |
GEN_KEY3: |
begin |
key_en = EN_KEY_3; |
key_sel = KEY_OUT; |
bypass_key_en = ENABLE; |
end |
READY: |
begin |
end_comp = ENABLE; |
if(op_mode == KEY_DERIVATION) |
key_derivation_en = ENABLE; |
end |
endcase |
end |
|
// Round Counter |
always @(posedge clk, negedge rst_n) |
begin |
if(!rst_n) |
rd_count <= INITIAL_ROUND; |
else |
if(state == IDLE || (state == GEN_KEY3 && last_round)) |
rd_count <= INITIAL_ROUND; |
else |
if(rd_count_en) |
rd_count <= rd_count + 1'b1; |
end |
|
assign round = rd_count; |
assign first_round = (rd_count == INITIAL_ROUND); |
assign last_round = (rd_count == NUMBER_ROUND || rd_count == NUMBER_ROUND_INC); |
|
endmodule |
/trunk/rtl/aes_core.v
0,0 → 1,199
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
|
module aes_core |
( |
//OUTPUTS |
output [31:0] col_out, |
output [31:0] key_out, |
output [31:0] iv_out, |
output end_aes, |
//INPUTS |
input [31:0] bus_in, |
input [ 3:0] iv_en, |
input [ 3:0] iv_sel_rd, |
input [ 3:0] key_en, |
input [ 1:0] key_sel_rd, |
input [ 1:0] data_type, |
input [ 1:0] addr, |
input [ 1:0] op_mode, |
input [ 1:0] aes_mode, |
input start, |
input disable_core, |
input write_en, |
input read_en, |
input first_block, |
input rst_n, |
input clk |
); |
|
wire [ 1:0] rk_sel; |
wire [ 1:0] key_out_sel; |
wire [ 3:0] round; |
wire [ 2:0] sbox_sel; |
wire [ 3:0] col_en_host; |
wire [ 3:0] iv_en_host; |
wire [ 3:0] col_en_cnt_unit; |
wire [ 3:0] key_en_host; |
wire [ 3:0] key_en_cnt_unit; |
wire [ 1:0] col_sel; |
wire key_sel; |
wire bypass_rk; |
wire bypass_key_en; |
wire last_round; |
wire iv_cnt_en; |
wire iv_cnt_sel; |
wire mode_ctr; |
wire mode_cbc; |
wire key_init; |
wire key_gen; |
wire [1:0] col_addr_host; |
|
assign col_en_host = (4'b0001 << addr) & {4{write_en}}; |
assign col_addr_host = addr & {2{read_en}}; |
assign iv_en_host = iv_en; |
assign key_en_host = key_en; |
|
datapath AES_CORE_DATAPATH |
( |
.col_bus ( col_out ), |
.key_bus ( key_out ), |
.iv_bus ( iv_out ), |
.bus_in ( bus_in ), |
.end_aes ( end_aes ), |
.data_type ( data_type ), |
.rk_sel ( rk_sel ), |
.key_out_sel ( key_out_sel ), |
.round ( round ), |
.sbox_sel ( sbox_sel ), |
.iv_en ( iv_en_host ), |
.iv_sel_rd ( iv_sel_rd ), |
.col_en_host ( col_en_host ), |
.col_en_cnt_unit ( col_en_cnt_unit ), |
.key_host_en ( key_en_host ), |
.key_en ( key_en_cnt_unit ), |
.key_sel_rd ( key_sel_rd ), |
.col_sel_host ( col_addr_host ), |
.col_sel ( col_sel ), |
.key_sel ( key_sel ), |
.bypass_rk ( bypass_rk ), |
.bypass_key_en ( bypass_key_en ), |
.first_block ( first_block ), |
.last_round ( last_round ), |
.iv_cnt_en ( iv_cnt_en ), |
.iv_cnt_sel ( iv_cnt_sel ), |
.enc_dec ( enc_dec ), |
.mode_ctr ( mode_ctr ), |
.mode_cbc ( mode_cbc ), |
.key_init ( key_init ), |
.key_gen ( key_gen ), |
.key_derivation_en ( key_derivation_en ), |
.end_comp ( end_comp ), |
.rst_n ( rst_n ), |
.clk ( clk ) |
); |
|
control_unit AES_CORE_CONTROL_UNIT |
( |
.end_comp ( end_comp ), |
.sbox_sel ( sbox_sel ), |
.rk_sel ( rk_sel ), |
.key_out_sel ( key_out_sel ), |
.col_sel ( col_sel ), |
.key_en ( key_en_cnt_unit ), |
.col_en ( col_en_cnt_unit ), |
.round ( round ), |
.bypass_rk ( bypass_rk ), |
.bypass_key_en ( bypass_key_en ), |
.key_sel ( key_sel ), |
.last_round ( last_round ), |
.iv_cnt_en ( iv_cnt_en ), |
.iv_cnt_sel ( iv_cnt_sel ), |
.mode_ctr ( mode_ctr ), |
.mode_cbc ( mode_cbc ), |
.key_init ( key_init ), |
.encrypt_decrypt ( enc_dec ), |
.key_gen ( key_gen ), |
.operation_mode ( op_mode ), |
.aes_mode ( aes_mode ), |
.start ( start ), |
.key_derivation_en ( key_derivation_en ), |
.disable_core ( disable_core ), |
.clk ( clk ), |
.rst_n ( rst_n ) |
); |
|
endmodule |
/trunk/rtl/aes_ip.v
0,0 → 1,173
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module aes_ip |
( |
//OUTPUTS |
output int_ccf, |
output int_err, |
output dma_req_wr, |
output dma_req_rd, |
output PREADY, |
output PSLVERR, |
output [31:0] PRDATA, |
//INPUTS |
input [ 3:0] PADDR, |
input [31:0] PWDATA, |
input PWRITE, |
input PENABLE, |
input PSEL, |
input PCLK, |
input PRESETn |
); |
|
wire [31:0] col_out; |
wire [31:0] key_out; |
wire [31:0] iv_out; |
wire end_aes; |
wire [ 3:0] iv_en; |
wire [ 3:0] iv_sel_rd; |
wire [ 3:0] key_en; |
wire [ 1:0] key_sel_rd; |
wire [ 1:0] data_type; |
wire [ 1:0] addr; |
wire [ 1:0] op_mode; |
wire [ 1:0] aes_mode; |
wire start; |
wire disable_core; |
wire write_en; |
wire read_en; |
wire first_block; |
|
assign PREADY = 1'b1; |
assign PSLVERR = 1'b0; |
|
host_interface HOST_INTERFACE |
( |
.key_en ( key_en ), |
.col_addr ( addr ), |
.col_wr_en ( write_en ), |
.col_rd_en ( read_en ), |
.key_sel ( key_sel_rd ), |
.iv_en ( iv_en ), |
.iv_sel ( iv_sel_rd ), |
.int_ccf ( int_ccf ), |
.int_err ( int_err ), |
.chmod ( aes_mode ), |
.mode ( op_mode ), |
.data_type ( data_type ), |
.disable_core ( disable_core ), |
.first_block ( first_block ), |
.dma_req_wr ( dma_req_wr ), |
.dma_req_rd ( dma_req_rd ), |
.start_core ( start ), |
.PRDATA ( PRDATA ), |
.PADDR ( PADDR ), |
.PWDATA ( PWDATA ), |
.PWRITE ( PWRITE ), |
.PENABLE ( PENABLE ), |
.PSEL ( PSEL ), |
.PCLK ( PCLK ), |
.PRESETn ( PRESETn ), |
.key_bus ( key_out ), |
.col_bus ( col_out ), |
.iv_bus ( iv_out ), |
.ccf_set ( end_aes ) |
); |
|
aes_core AES_CORE |
( |
.col_out ( col_out ), |
.key_out ( key_out ), |
.iv_out ( iv_out ), |
.end_aes ( end_aes ), |
.bus_in ( PWDATA ), |
.iv_en ( iv_en ), |
.iv_sel_rd ( iv_sel_rd ), |
.key_en ( key_en ), |
.key_sel_rd ( key_sel_rd ), |
.data_type ( data_type ), |
.addr ( addr ), |
.op_mode ( op_mode ), |
.aes_mode ( aes_mode ), |
.start ( start ), |
.disable_core ( disable_core ), |
.write_en ( write_en ), |
.read_en ( read_en ), |
.first_block ( first_block ), |
.rst_n ( PRESETn ), |
.clk ( PCLK ) |
); |
endmodule |
/trunk/rtl/sBox_8.v
0,0 → 1,329
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
|
//Reference: A Very Compact Rijndael S-box, D. Canright |
|
module sBox_8 |
( |
//OUTPUTS |
output [7:0] sbox_out_enc, // Direct SBOX |
output [7:0] sbox_out_dec, // Inverse SBOX |
//INPUTS |
input [7:0] sbox_in, |
input enc_dec, |
input clk |
); |
//`include "include/sbox_functions.vf" |
|
// Functions used by SBOX Logic |
// For more detail, see "A Very Compact Rijndael S-Box" by D. Canright |
localparam ENC = 1; |
localparam DEC = 0; |
|
function [1:0] gf_sq_2; |
input [1:0] in; |
begin |
gf_sq_2 = {in[0], in[1]}; |
end |
endfunction |
|
function [1:0] gf_sclw_2; |
input [1:0] in; |
begin |
gf_sclw_2 = {^in, in[1]}; |
end |
endfunction |
|
function [1:0] gf_sclw2_2; |
input [1:0] in; |
begin |
gf_sclw2_2 = {in[0], ^in}; |
end |
endfunction |
|
function [1:0] gf_muls_2; |
input [1:0] in1, in2; |
input in3, in4; |
begin |
gf_muls_2 = ( ~(in1 & in2) ) ^ ( {2{~(in3 & in4)}} ); |
end |
endfunction |
|
function [1:0] gf_muls_scl_2; |
input [1:0] in1, in2; |
input in3, in4; |
reg [1:0] nand_in1_in2; |
reg nand_in3_in4; |
begin |
nand_in1_in2 = ~(in1 & in2); |
nand_in3_in4 = ~(in3 & in4); |
gf_muls_scl_2 = {nand_in3_in4 ^ nand_in1_in2[0], ^nand_in1_in2}; |
end |
endfunction |
|
function [3:0] gf_inv_4; |
input [3:0] in; |
reg [1:0] in_hg; |
reg [1:0] in_lw; |
reg [1:0] out_gf_mul_2; |
reg [1:0] out_gf_mul_3; |
reg [1:0] out_gf_sq2_3; |
reg [1:0] in_sq2_3; |
reg xor_in_hg, xor_in_lw; |
begin |
in_hg = in[3:2]; |
in_lw = in[1:0]; |
xor_in_hg = ^in_hg; |
xor_in_lw = ^in_lw; |
in_sq2_3 = {~(in_hg[1] | in_lw[1]) ^ (~(xor_in_hg & xor_in_lw)), ~(xor_in_hg | xor_in_lw) ^ (~(in_hg[0] & in_lw[0]))}; |
|
out_gf_sq2_3 = gf_sq_2(in_sq2_3); |
out_gf_mul_2 = gf_muls_2(out_gf_sq2_3, in_lw, ^out_gf_sq2_3, xor_in_lw); |
out_gf_mul_3 = gf_muls_2(out_gf_sq2_3, in_hg, ^out_gf_sq2_3, xor_in_hg); |
|
gf_inv_4 = {out_gf_mul_2, out_gf_mul_3}; |
end |
endfunction |
|
|
function [3:0] gf_sq_scl_4; |
input [3:0] in; |
reg [1:0] in_hg; |
reg [1:0] in_lw; |
reg [1:0] out_gf_sq2_1; |
reg [1:0] out_gf_sq2_2; |
reg [1:0] out_gf_sclw2_1; |
begin |
in_hg = in[3:2]; |
in_lw = in[1:0]; |
|
out_gf_sq2_1 = gf_sq_2(in_hg ^ in_lw ); |
out_gf_sq2_2 = gf_sq_2(in_lw); |
out_gf_sclw2_1 = gf_sclw_2(out_gf_sq2_2); |
|
gf_sq_scl_4 = {out_gf_sq2_1, out_gf_sclw2_1}; |
end |
endfunction |
|
|
function [3:0] gf_muls_4; |
input [3:0] in1; |
input [3:0] in2; |
reg [1:0] in1_hg; |
reg [1:0] in1_lw; |
reg [1:0] in2_hg; |
reg [1:0] in2_lw; |
reg [1:0] xor_in1_hl; |
reg [1:0] xor_in2_hl; |
reg [1:0] out_gf_mul_1; |
reg [1:0] out_gf_mul_2; |
reg [1:0] out_gf_mul_scl_1; |
begin |
in1_hg = in1[3:2]; |
in1_lw = in1[1:0]; |
in2_hg = in2[3:2]; |
in2_lw = in2[1:0]; |
xor_in1_hl = in1_hg ^ in1_lw; |
xor_in2_hl = in2_hg ^ in2_lw; |
|
out_gf_mul_1 = gf_muls_2(in1_hg, in2_hg, in1[3] ^ in1[2], in2[3] ^ in2[2]); |
out_gf_mul_2 = gf_muls_2(in1_lw, in2_lw, in1[1] ^ in1[0], in2[1] ^ in2[0]); |
out_gf_mul_scl_1 = gf_muls_scl_2(xor_in1_hl, xor_in2_hl, ^xor_in1_hl, ^xor_in2_hl); |
|
gf_muls_4 = {out_gf_mul_1 ^ out_gf_mul_scl_1, out_gf_mul_2 ^ out_gf_mul_scl_1}; |
end |
endfunction |
|
function [3:0] gf_inv_8_stage1; |
input [7:0] in; |
reg [3:0] in_hg; |
reg [3:0] in_lw; |
reg [3:0] out_gf_mul4_2; |
reg [3:0] out_gf_mul4_3; |
reg [3:0] out_gf_inv4_2; |
reg c1, c2, c3; |
begin |
in_hg = in[7:4]; |
in_lw = in[3:0]; |
|
c1 = ~((in_hg[3] ^ in_hg[2]) & (in_lw[3] ^ in_lw[2])); |
c2 = ~((in_hg[2] ^ in_hg[0]) & (in_lw[2] ^ in_lw[0])); |
c3 = ~((^in_hg) & (^in_lw)); |
|
gf_inv_8_stage1 = |
{(~((in_hg[2] ^ in_hg[0]) | (in_lw[2] ^ in_lw[0])) ^ (~(in_hg[3] & in_lw[3]))) ^ c1 ^ c3, |
(~((in_hg[3] ^ in_hg[1]) | (in_lw[3] ^ in_lw[1])) ^ (~(in_hg[2] & in_lw[2]))) ^ c1 ^ c2, |
(~((in_hg[1] ^ in_hg[0]) | (in_lw[1] ^ in_lw[0])) ^ (~(in_hg[1] & in_lw[1]))) ^ c2 ^ c3, |
((~(in_hg[0] | in_lw[0])) ^ (~((in_hg[1] ^ in_hg[0]) & (in_lw[1] ^ in_lw[0])))) ^ (~((in_hg[3] ^ in_hg[1]) & (in_lw[3] ^ in_lw[1]))) ^ c2}; |
end |
endfunction |
|
function [7:0] gf_inv_8_stage2; |
input [7:0] in; |
input [3:0] c; |
reg [3:0] in_hg; |
reg [3:0] in_lw; |
reg [3:0] out_gf_mul4_2; |
reg [3:0] out_gf_mul4_3; |
reg [3:0] out_gf_inv4_2; |
reg c1, c2, c3; |
begin |
in_hg = in[7:4]; |
in_lw = in[3:0]; |
|
out_gf_inv4_2 = gf_inv_4(c); |
out_gf_mul4_2 = gf_muls_4(out_gf_inv4_2, in_lw); |
out_gf_mul4_3 = gf_muls_4(out_gf_inv4_2, in_hg); |
|
gf_inv_8_stage2 = {out_gf_mul4_2, out_gf_mul4_3}; |
end |
endfunction |
|
function [15:0] isomorphism; |
input [7:0] in; |
reg r1, r2, r3, r4, r5, r6, r7, r8, r9; |
reg [7:0] enc, dec; |
begin |
r1 = in[7] ^ in[5]; |
r2 = in[7] ~^ in[4]; |
r3 = in[6] ^ in[0]; |
r4 = in[5] ~^ r3; |
r5 = in[4] ^ r4; |
r6 = in[3] ^ in[0]; |
r7 = in[2] ^ r1; |
r8 = in[1] ^ r3; |
r9 = in[3] ^ r8; |
|
enc = {r7 ~^ r8, r5, in[1] ^ r4, r1 ~^ r3, in[1] ^ r2 ^ r6, ~in[0], r4, in[2] ~^ r9}; |
dec = {r2, in[4] ^ r8, in[6] ^ in[4], r9, in[6] ~^ r2, r7, in[4] ^ r6, in[1] ^ r5}; |
|
isomorphism = {enc, dec}; |
end |
endfunction |
|
function [7:0] isomorphism_inv; |
input [7:0] in; |
input op_type; |
reg r1, r2, r3, r4, r5, r6, r7, r8, r9, r10; |
begin |
r1 = in[7] ^ in[3]; |
r2 = in[6] ^ in[4]; |
r3 = in[6] ^ in[0]; |
r4 = in[5] ~^ in[3]; |
r5 = in[5] ~^ r1; |
r6 = in[5] ~^ in[1]; |
r7 = in[4] ~^ r6; |
r8 = in[2] ^ r4; |
r9 = in[1] ^ r2; |
r10 = r3 ^ r5; |
|
if(op_type == ENC) |
isomorphism_inv = {r4, r1, r3, r5, r2 ^ r5, r3 ^ r8, r7, r9}; |
else |
isomorphism_inv = {in[4] ~^ in[1], in[1] ^ r10, in[2] ^ r10, in[6] ~^ in[1], r8 ^ r9, in[7] ~^ r7, r6, ~in[2]}; |
|
end |
endfunction |
|
|
|
|
wire [7:0] base_new_enc, base_new_dec, base_new; |
wire [7:0] base_enc, base_dec; |
wire [3:0] out_gf_inv8_stage1; |
wire [7:0] out_gf_inv8_1; |
wire [7:0] out_gf_inv8_2; |
|
reg [3:0] out_gf_pp; |
reg [7:0] base_new_pp; |
|
assign {base_new_enc, base_new_dec} = isomorphism(sbox_in); |
|
assign base_new = ~(enc_dec ? base_new_enc : base_new_dec); |
assign out_gf_inv8_stage1 = gf_inv_8_stage1(base_new); |
|
always @(posedge clk) |
begin |
out_gf_pp <= out_gf_inv8_stage1; |
base_new_pp <= base_new; |
end |
|
assign out_gf_inv8_1 = gf_inv_8_stage2(base_new_pp, out_gf_pp); |
|
assign sbox_out_enc = ~isomorphism_inv(out_gf_inv8_1, ENC); |
assign sbox_out_dec = ~isomorphism_inv(out_gf_inv8_1, DEC); |
|
endmodule |
/trunk/rtl/data_swap.v
0,0 → 1,113
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module data_swap |
#( |
parameter WIDTH = 32 |
)( |
//OUTPUTS |
output [WIDTH - 1:0] data_swap, |
//INPUTS |
input [WIDTH - 1:0] data_in, |
input [ 1:0] swap_type |
); |
|
//===================================================================================== |
// Swap Types |
//===================================================================================== |
localparam NO_SWAP = 2'b00; |
localparam HALF_WORD_SWAP = 2'b01; |
localparam BYTE_SWAP = 2'b10; |
localparam BIT_SWAP = 2'b11; |
|
localparam TYPES = 4; |
|
wire [WIDTH - 1 : 0] words[0 : TYPES - 1]; |
|
generate |
genvar i, j; |
for(i = 0; i < TYPES; i = i + 1) |
for(j = 0; j < WIDTH; j = j + 1) |
begin |
if(i != 3) |
assign words[i][j] = data_in[(WIDTH - (WIDTH/2**i)) - 2*(WIDTH/2**i)*(j/(WIDTH/2**i)) + j]; |
else |
assign words[i][j] = data_in[WIDTH - 1 - j]; |
end |
endgenerate |
|
assign data_swap = words[swap_type]; |
|
endmodule |
/trunk/rtl/datapath.v
0,0 → 1,572
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module datapath |
( |
// OUTPUTS |
output [31:0] col_bus, |
output [31:0] key_bus, |
output [31:0] iv_bus, |
output end_aes, |
// INPUTS |
input [31:0] bus_in, |
input [ 1:0] data_type, |
input [ 1:0] rk_sel, |
input [ 1:0] key_out_sel, |
input [ 3:0] round, |
input [ 2:0] sbox_sel, |
input [ 3:0] iv_en, |
input [ 3:0] iv_sel_rd, |
input [ 3:0] col_en_host, |
input [ 3:0] col_en_cnt_unit, |
input [ 3:0] key_host_en, |
input [ 3:0] key_en, |
input [ 1:0] key_sel_rd, |
input [ 1:0] col_sel, |
input [ 1:0] col_sel_host, |
input end_comp, |
input key_sel, |
input key_init, |
input bypass_rk, |
input bypass_key_en, |
input first_block, |
input last_round, |
input iv_cnt_en, |
input iv_cnt_sel, |
input enc_dec, |
input mode_ctr, |
input mode_cbc, |
input key_gen, |
input key_derivation_en, |
input rst_n, |
input clk |
); |
|
//`include "include/control_unit_params.vh" |
//============================================================================= |
// SBOX SEL |
//============================================================================= |
localparam COL_0 = 3'b000; |
localparam COL_1 = 3'b001; |
localparam COL_2 = 3'b010; |
localparam COL_3 = 3'b011; |
localparam G_FUNCTION = 3'b100; |
|
//============================================================================= |
// RK_SEL |
//============================================================================= |
localparam COL = 2'b00; |
localparam MIXCOL_IN = 2'b01; |
localparam MIXCOL_OUT = 2'b10; |
|
//============================================================================= |
// KEY_OUT_SEL |
//============================================================================= |
localparam KEY_0 = 2'b00; |
localparam KEY_1 = 2'b01; |
localparam KEY_2 = 2'b10; |
localparam KEY_3 = 2'b11; |
|
//============================================================================= |
// COL_SEL |
//============================================================================= |
localparam SHIFT_ROWS = 2'b00; |
localparam ADD_RK_OUT = 2'b01; |
localparam INPUT = 2'b10; |
|
//============================================================================= |
// KEY_SEL |
//============================================================================= |
localparam KEY_HOST = 1'b0; |
localparam KEY_OUT = 1'b1; |
|
//============================================================================= |
// KEY_EN |
//============================================================================= |
localparam KEY_DIS = 4'b0000; |
localparam EN_KEY_0 = 4'b0001; |
localparam EN_KEY_1 = 4'b0010; |
localparam EN_KEY_2 = 4'b0100; |
localparam EN_KEY_3 = 4'b1000; |
localparam KEY_ALL = 4'b1111; |
|
//============================================================================= |
// COL_EN |
//============================================================================= |
localparam COL_DIS = 4'b0000; |
localparam EN_COL_0 = 4'b0001; |
localparam EN_COL_1 = 4'b0010; |
localparam EN_COL_2 = 4'b0100; |
localparam EN_COL_3 = 4'b1000; |
localparam COL_ALL = 4'b1111; |
|
//============================================================================= |
// IV_CNT_SEL |
//============================================================================= |
localparam IV_CNT = 1'b1; |
localparam IV_BUS = 1'b0; |
|
//============================================================================= |
// ENABLES |
//============================================================================= |
localparam ENABLE = 1'b1; |
localparam DISABLE = 1'b0; |
|
reg [31 : 0] col [0:3]; |
reg [31 : 0] key [0:3]; |
reg [31 : 0] key_host[0:3]; |
reg [31 : 0] bkp [0:3]; |
reg [31 : 0] bkp_1 [0:3]; |
reg [31 : 0] iv [0:3]; |
|
reg [127 : 0] col_in; |
reg [ 31 : 0] data_in; |
reg [ 31 : 0] add_rd_key_in; |
reg [ 31 : 0] sbox_input; |
reg [ 31 : 0] key_mux_out; |
reg [ 31 : 0] iv_mux_out; |
reg [ 31 : 0] bkp_mux_out; |
|
wire [127 : 0] key_in, key_out; |
wire [127 : 0] sr_input; |
wire [127 : 0] sr_enc, sr_dec; |
wire [ 31 : 0] add_rk_out; |
wire [ 31 : 0] sbox_out_enc; |
wire [ 31 : 0] sbox_out_dec; |
wire [ 31 : 0] g_in; |
wire [ 31 : 0] mix_out_enc; |
wire [ 31 : 0] mix_out_dec; |
wire [ 31 : 0] add_rd; |
wire [ 31 : 0] bus_swap; |
wire [ 31 : 0] iv_bkp_mux; |
wire [ 31 : 0] xor_input_bkp_iv; |
wire [ 31 : 0] sr_input_0; |
wire [ 31 : 0] sr_input_3; |
wire [ 3 : 0] key_en_sel; |
wire [ 3 : 0] bkp_en; |
wire [ 3 : 0] col_en; |
wire [ 1 : 0] key_mux_sel; |
wire [ 1 : 0] rk_sel_mux; |
wire [ 1 : 0] col_sel_w_bypass; |
wire [ 3 : 0] col_en_w_bypass; |
wire rk_out_sel; |
wire add_rk_sel; |
wire key_sel_mux; |
wire key1_mux_cnt; |
wire enc_dec_sbox; |
|
reg [31 : 0] sbox_pp2; |
reg [ 3 : 0] col_en_cnt_unit_pp1; |
reg [ 3 : 0] col_en_cnt_unit_pp2; |
reg [ 3 : 0] key_en_pp1; |
reg [ 3 : 0] round_pp1; |
reg [ 1 : 0] col_sel_pp1; |
reg [ 1 : 0] col_sel_pp2; |
reg [ 1 : 0] key_out_sel_pp1; |
reg [ 1 : 0] key_out_sel_pp2; |
reg [ 1 : 0] rk_sel_pp1; |
reg [ 1 : 0] rk_sel_pp2; |
reg key_sel_pp1; |
reg rk_out_sel_pp1, rk_out_sel_pp2; |
reg last_round_pp1, last_round_pp2; |
reg end_aes_pp1, end_aes_pp2; |
|
assign key_bus = key_mux_out; |
assign iv_bus = iv_mux_out; |
|
// Input Swap Unit |
data_swap SWAP_IN |
( |
.data_swap( bus_swap ), |
.data_in ( bus_in ), |
.swap_type( data_type ) |
); |
|
// Output Swap Unit |
data_swap SWAP_OUT |
( |
.data_swap( col_bus ), |
.data_in ( sbox_input ), |
.swap_type( data_type ) |
); |
|
// IV and BKP Muxs |
always @(*) |
begin: IV_BKP_MUX |
integer i; |
iv_mux_out = {32{1'b0}}; |
bkp_mux_out = {32{1'b0}}; |
for(i = 0; i < 4; i = i + 1) |
begin |
if(col_en[i] | iv_sel_rd[i]) |
begin |
iv_mux_out = iv[i]; |
bkp_mux_out = bkp[i]; |
end |
end |
end |
|
assign iv_bkp_mux = (first_block && !mode_ctr) ? iv_mux_out : bkp_mux_out; |
|
assign xor_input_bkp_iv = ((enc_dec && !mode_ctr) ? bus_swap : add_rk_out) ^ iv_bkp_mux; |
|
always @(*) |
begin |
data_in = {32{1'b0}}; |
case(1'b1) |
mode_cbc: |
data_in = (enc_dec || last_round) ? xor_input_bkp_iv : bus_swap; |
mode_ctr: |
data_in = (last_round) ? xor_input_bkp_iv : iv_mux_out; |
default: |
data_in = bus_swap; |
endcase |
end |
|
assign bkp_en = ( {4{ mode_cbc && last_round && enc_dec}} & col_en_cnt_unit_pp2) | |
( {4{(mode_cbc && !enc_dec) || mode_ctr}} & col_en_host ); |
|
|
// IV and BKP Registers |
generate |
genvar l; |
for(l = 0; l < 4; l = l + 1) |
always @(posedge clk, negedge rst_n) |
begin |
if(!rst_n) |
begin |
iv[l] <= {32{1'b0}}; |
bkp[l] <= {32{1'b0}}; |
bkp_1[l] <= {32{1'b0}}; |
end |
else |
begin |
if(l == 3) |
begin |
if(iv_en[l] || iv_cnt_en) |
iv[l] <= (iv_cnt_sel) ? iv[l] + 1'b1 : bus_in; |
end |
else |
begin |
if(iv_en[l]) |
iv[l] <= bus_in; |
end |
|
if(bkp_en[l]) |
bkp[l] <= (mode_ctr) ? bus_swap : ((mode_cbc && enc_dec) ? col_in : bkp_1[l]); |
|
if(bkp_en[l]) |
bkp_1[l] <= col_in; |
end |
end |
endgenerate |
|
assign col_sel_w_bypass = (bypass_rk) ? col_sel : col_sel_pp2; |
|
// Columns Input Multiplexors |
always @(*) |
begin |
col_in = {128{1'b0}}; |
case(col_sel_w_bypass) |
SHIFT_ROWS: |
col_in = (enc_dec) ? sr_enc : sr_dec; |
ADD_RK_OUT: |
col_in = {4{add_rk_out}}; |
INPUT: |
col_in = {4{data_in}}; |
endcase |
end |
|
assign col_en_w_bypass = (bypass_rk) ? col_en_cnt_unit : col_en_cnt_unit_pp2; |
assign col_en = col_en_host | col_en_w_bypass; |
|
// Columns Definition |
generate |
genvar i; |
for(i = 0; i < 4; i = i + 1) |
always @(posedge clk, negedge rst_n) |
begin |
if(!rst_n) |
col[3 - i] <= {32{1'b0}}; |
else |
if(col_en[3 - i]) |
col[3 - i] <= col_in[32*(i + 1) - 1 : 32*i]; |
end |
endgenerate |
|
// Shift Rows Operation |
assign sr_input_3 = (enc_dec) ? add_rk_out : col[3]; |
assign sr_input_0 = (enc_dec) ? col[0] : add_rk_out; |
assign sr_input = {sr_input_0, col[1], col[2], sr_input_3}; |
|
shift_rows SHIFT_ROW |
( |
.data_out_enc ( sr_enc ), |
.data_out_dec ( sr_dec ), |
.data_in ( sr_input ) |
); |
|
//SBOX Input Multiplexor |
always @(*) |
begin |
sbox_input = {32{1'b0}}; |
case(sbox_sel | col_sel_host) |
COL_0: |
sbox_input = col[0]; |
COL_1: |
sbox_input = col[1]; |
COL_2: |
sbox_input = col[2]; |
COL_3: |
sbox_input = col[3]; |
G_FUNCTION: |
sbox_input = g_in; |
endcase |
end |
|
// 32 bits SBOX |
assign enc_dec_sbox = enc_dec | key_gen; |
sBox SBOX |
( |
.sbox_out_enc ( sbox_out_enc ), |
.sbox_out_dec ( sbox_out_dec ), |
.sbox_in ( sbox_input ), |
.enc_dec ( enc_dec_sbox ), |
.clk ( clk ) |
); |
|
// Second stage of pipeline |
always @(posedge clk) |
begin |
sbox_pp2 <= (enc_dec || mode_ctr) ? sbox_out_enc : sbox_out_dec ^ key_mux_out; |
end |
|
assign key_en_sel = (bypass_key_en) ? key_en : key_en_pp1; |
assign key_sel_mux = (bypass_key_en) ? key_sel : key_sel_pp1; |
|
// Key registers |
generate |
genvar j; |
for(j = 0; j < 4; j = j + 1) |
always @(posedge clk, negedge rst_n) |
begin |
if(!rst_n) |
begin |
key_host[3 - j] <= {32{1'b0}}; |
key[3 - j] <= {32{1'b0}}; |
end |
else |
begin |
if(key_host_en[3 - j] || key_derivation_en) |
key_host[3 - j] <= (key_derivation_en) ? key[3 - j] : bus_in; |
|
if(key_en_sel[3 - j] || key_init || key_host_en[3 - j]) |
key[3 - j] <= (key_sel_mux) ? key_out[32*(j + 1) - 1 : 32*j] : ( (key_host_en[3 - j]) ? bus_in : key_host[3 - j] ); |
end |
end |
endgenerate |
|
assign key_in = {key[0], key[1], key[2], key[3]}; |
|
assign key1_mux_cnt = bypass_key_en & enc_dec; |
|
key_expander KEY_EXPANDER |
( |
.key_out ( key_out ), |
.g_in ( g_in ), |
.g_out ( sbox_out_enc ), |
.key_in ( key_in ), |
.round ( round_pp1 ), |
.add_w_out ( key1_mux_cnt ), |
.enc_dec ( enc_dec | key_gen) |
); |
|
assign key_mux_sel = (bypass_key_en) ? key_out_sel : ( (enc_dec | mode_ctr) ? key_out_sel_pp2 : key_out_sel_pp1 ); |
|
// Key Expander Mux |
always @(*) |
begin |
key_mux_out = {32{1'b0}}; |
case(key_mux_sel | key_sel_rd) |
KEY_0: |
key_mux_out = key[0]; |
KEY_1: |
key_mux_out = key[1]; |
KEY_2: |
key_mux_out = key[2]; |
KEY_3: |
key_mux_out = key[3]; |
endcase |
end |
|
mix_columns MIX_COL |
( |
.mix_out_enc ( mix_out_enc ), |
.mix_out_dec ( mix_out_dec ), |
.mix_in ( sbox_pp2 ) |
); |
|
assign rk_sel_mux = (bypass_rk) ? rk_sel : rk_sel_pp2; |
|
always @(*) |
begin |
add_rd_key_in = {32{1'b0}}; |
case(rk_sel_mux) |
COL: |
add_rd_key_in = sbox_input; |
MIXCOL_IN: |
add_rd_key_in = sbox_pp2; |
MIXCOL_OUT: |
add_rd_key_in = mix_out_enc; |
endcase |
end |
|
// Add Round Key |
assign add_rd = add_rd_key_in ^ key_mux_out; |
|
assign rk_out_sel = (enc_dec | mode_ctr | bypass_rk); |
|
assign add_rk_sel = (bypass_rk) ? rk_out_sel : rk_out_sel_pp2; |
|
assign add_rk_out = (add_rk_sel) ? add_rd : (last_round_pp2 ? sbox_pp2 : mix_out_dec); |
|
assign end_aes = end_aes_pp2; |
|
// Pipeline Registers for Control Signals |
always @(posedge clk, negedge rst_n) |
begin |
if(!rst_n) |
begin |
end_aes_pp1 <= DISABLE; |
end_aes_pp2 <= DISABLE; |
|
col_sel_pp1 <= INPUT; |
col_sel_pp2 <= INPUT; |
|
col_en_cnt_unit_pp1 <= COL_DIS; |
col_en_cnt_unit_pp2 <= COL_DIS; |
|
key_sel_pp1 <= KEY_HOST; |
key_en_pp1 <= KEY_DIS; |
|
round_pp1 <= 4'b0000; |
|
key_out_sel_pp1 <= KEY_0; |
key_out_sel_pp2 <= KEY_0; |
|
rk_sel_pp1 <= COL; |
rk_sel_pp2 <= COL; |
|
rk_out_sel_pp1 <= 1'b1; |
rk_out_sel_pp2 <= 1'b1; |
|
last_round_pp1 <= 1'b1; |
last_round_pp2 <= 1'b0; |
end |
else |
begin |
col_sel_pp1 <= col_sel; |
col_sel_pp2 <= col_sel_pp1; |
|
if(!bypass_rk) |
begin |
col_en_cnt_unit_pp1 <= col_en_cnt_unit; |
col_en_cnt_unit_pp2 <= col_en_cnt_unit_pp1; |
end |
|
key_sel_pp1 <= key_sel; |
|
if(!bypass_key_en) |
key_en_pp1 <= key_en; |
|
round_pp1 <= round; |
|
key_out_sel_pp1 <= key_out_sel; |
key_out_sel_pp2 <= key_out_sel_pp1; |
|
rk_sel_pp1 <= rk_sel; |
rk_sel_pp2 <= rk_sel_pp1; |
|
rk_out_sel_pp1 <= rk_out_sel; |
rk_out_sel_pp2 <= rk_out_sel_pp1; |
|
last_round_pp1 <= last_round; |
last_round_pp2 <= last_round_pp1; |
|
end_aes_pp1 <= end_comp; |
end_aes_pp2 <= end_aes_pp1; |
end |
end |
endmodule |
/trunk/rtl/shift_rows.v
0,0 → 1,129
////////////////////////////////////////////////////////////////// |
//// |
//// |
//// AES CORE BLOCK |
//// |
//// |
//// |
//// This file is part of the APB to I2C project |
//// |
//// http://www.opencores.org/cores/apbi2c/ |
//// |
//// |
//// |
//// Description |
//// |
//// Implementation of APB IP core according to |
//// |
//// aes128_spec IP core specification document. |
//// |
//// |
//// |
//// To Do: Things are right here but always all block can suffer changes |
//// |
//// |
//// |
//// |
//// |
//// Author(s): - Felipe Fernandes Da Costa, fefe2560@gmail.com |
//// Julio Cesar |
//// |
///////////////////////////////////////////////////////////////// |
//// |
//// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG |
//// |
//// |
//// |
//// This source file may be used and distributed without |
//// |
//// restriction provided that this copyright statement is not |
//// |
//// removed from the file and that any derivative work contains |
//// the original copyright notice and the associated disclaimer. |
//// |
//// |
//// This source file is free software; you can redistribute it |
//// |
//// and/or modify it under the terms of the GNU Lesser General |
//// |
//// Public License as published by the Free Software Foundation; |
//// either version 2.1 of the License, or (at your option) any |
//// |
//// later version. |
//// |
//// |
//// |
//// This source is distributed in the hope that it will be |
//// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied |
//// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
//// |
//// PURPOSE. See the GNU Lesser General Public License for more |
//// details. |
//// |
//// |
//// |
//// You should have received a copy of the GNU Lesser General |
//// |
//// Public License along with this source; if not, download it |
//// |
//// from http://www.opencores.org/lgpl.shtml |
//// |
//// |
/////////////////////////////////////////////////////////////////// |
module shift_rows |
( |
//OUTPUTS |
output [127 : 0] data_out_enc, // Result after Shift Rows operation - enc |
output [127 : 0] data_out_dec, // Result after Shift Rows operation - dec |
//INPUTS |
input [127 : 0] data_in // Input Bus |
); |
|
localparam BUS_WIDTH = 128; // Bus Width |
localparam ST_WORD = 8; // Data Size of word in State MAtrix |
localparam ST_LINE = 4; // Number of Lines of State Matrix |
localparam ST_COL = 4; // Number of Columns of State Matrix |
|
wire [ST_WORD - 1 : 0] state[0 : ST_LINE - 1][0 : ST_COL - 1]; |
wire [ST_WORD - 1 : 0] state_sft_l[0 : ST_LINE - 1][0 : ST_COL - 1]; |
wire [ST_WORD - 1 : 0] state_sft_r[0 : ST_LINE - 1][0 : ST_COL - 1]; |
|
//===================================================================================== |
// State Matrix generation |
//===================================================================================== |
generate |
genvar l,c; |
for(l = 0; l < ST_LINE; l = l + 1) |
for(c = 0; c < ST_COL; c = c + 1) |
assign state[l][c] = data_in[ST_WORD*((ST_COL - c)*ST_LINE - l) - 1 : ST_WORD*((ST_COL - c)*ST_LINE - l - 1)]; |
endgenerate |
|
//===================================================================================== |
// Shift Row operation |
//===================================================================================== |
generate |
genvar l1,c1; |
for(l1 = 0; l1 < ST_LINE; l1 = l1 + 1) |
for(c1 = 0; c1 < ST_COL; c1 = c1 + 1) |
begin |
assign state_sft_l[l1][c1] = state[l1][(c1 + l1)%ST_COL]; |
assign state_sft_r[l1][c1] = state[l1][(c1 + (ST_COL - l1))%ST_COL]; |
end |
endgenerate |
|
//===================================================================================== |
// State Matrix to Bus Output Transformation |
//===================================================================================== |
generate |
genvar l2,c2; |
for(l2 = 0; l2 < ST_LINE; l2 = l2 + 1) |
for(c2 = 0; c2 < ST_COL; c2 = c2 + 1) |
begin |
assign data_out_enc[ST_WORD*((ST_COL - c2)*ST_LINE - l2) - 1 : ST_WORD*((ST_COL - c2)*ST_LINE - l2 - 1)] = state_sft_l[l2][c2]; |
assign data_out_dec[ST_WORD*((ST_COL - c2)*ST_LINE - l2) - 1 : ST_WORD*((ST_COL - c2)*ST_LINE - l2 - 1)] = state_sft_r[l2][c2]; |
end |
endgenerate |
endmodule |