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

Subversion Repositories aes_highthroughput_lowarea

[/] [aes_highthroughput_lowarea/] [trunk/] [verilog/] [rtl/] [aes.v] - Rev 11

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

//---------------------------------------------------------------------------------------
// 
//	AES core top module 
// 
//	Description: 
//		AES core top module with direct interface to key and data buses. 
// 
//	To Do: 
//		- done 
//
//	Author(s):
//		- Luo Dongjun,   dongjun_luo@hotmail.com 
//
//---------------------------------------------------------------------------------------
 
// uncomment the following define to enable use of distributed RAM implementation 
// for XILINX FPGAs instead of block memory.
// NOTE: when commenting the following define, core size is slightly smaller but maximum 
// achievable clock frequency is also slightly lower. 
`define XILINX		1 
 
module aes (
	clk, reset,
	i_start, i_enable,
	i_ende, i_key,
	i_key_mode, i_data,
	i_data_valid, o_ready, 
	o_data, o_data_valid, 
	o_key_ready
);
 
//---------------------------------------------------------------------------------------
// module interfaces 
input			clk;		// core global clock 
input			reset;		// core global async reset control 
input			i_start;	// key expansion start pulse 
input			i_enable;	// enable encryption / decryption core operation 
input	[1:0]	i_key_mode; // key length: 0 => 128; 1 => 192; 2 => 256
input	[255:0]	i_key; 		// if key size is 128/192, upper bits are the inputs 
input	[127:0]	i_data;		// plain/cipher text data input 
input			i_data_valid;	// data input valid 
input			i_ende;		// core mode of operation: 0 => encryption; 1 => decryption
output			o_ready;	// indicates core is ready for new input data at the next clock cycle 
output	[127:0]	o_data;		// data output 
output			o_data_valid;	// data output valid 
output			o_key_ready;	// key expansion procedure done 
 
//---------------------------------------------------------------------------------------
// module registers and signals 
genvar i;
wire           final_round;
reg   [3:0]    max_round;
wire  [127:0]  en_sb_data,de_sb_data,sr_data,mc_data,imc_data,ark_data;
reg   [127:0]  sb_data,o_data,i_data_L;
reg            i_data_valid_L;
reg            round_valid;
reg   [2:0]    sb_valid;
reg            o_data_valid;
reg   [3:0]    round_cnt,sb_round_cnt1,sb_round_cnt2,sb_round_cnt3;
wire  [127:0]  round_key;
wire  [63:0]   rd_data0,rd_data1;
wire           wr;
wire  [4:0]    wr_addr;
wire  [63:0]   wr_data;
wire  [127:0]  imc_round_key,en_ark_data,de_ark_data,ark_data_final,ark_data_init;
 
//---------------------------------------------------------------------------------------
// module implementation 
assign final_round = sb_round_cnt3[3:0] == max_round[3:0];
//assign o_ready = ~sb_valid[1]; // if ready is asserted, user can input data for the same cycle
assign o_ready = ~sb_valid[0]; // if ready is asserted, user can input data for the next cycle
 
// round count is Nr - 1
always @ (*)
begin
   case (i_key_mode)
      2'b00: max_round[3:0] = 4'd10;
      2'b01: max_round[3:0] = 4'd12;
      default: max_round[3:0] = 4'd14;
   endcase
end
 
//---------------------------------------------------------------------------------------
// Sub Bytes
//
//
generate
for (i=0;i<16;i=i+1)
begin : sbox_block
   sbox u_sbox (
      .clk(clk),
      .reset(reset),
      .enable(i_enable),
      .ende(i_ende),
      .din(o_data[i*8+7:i*8]),
      .en_dout(en_sb_data[i*8+7:i*8]),
      .de_dout(de_sb_data[i*8+7:i*8])
   );
end
endgenerate
 
always @ (posedge clk or posedge reset)
begin
   if (reset)
      sb_data[127:0] <= 128'b0;
   else if (i_enable)
      sb_data[127:0] <= i_ende ? de_sb_data[127:0] : en_sb_data[127:0];
end
 
//---------------------------------------------------------------------------------------
// Shift Rows
//
//
wire [127:0] shrows, ishrows;
 
shift_rows u_shrows (.si(sb_data[127:0]), .so(shrows));
inv_shift_rows u_ishrows (.si(sb_data[127:0]), .so(ishrows));
 
assign sr_data[127:0] = i_ende ? ishrows : shrows;
 
//---------------------------------------------------------------------------------------
// Mix Columns
//
//
mix_columns mxc_u (.in(sr_data), .out(mc_data));
 
always @ (posedge clk or posedge reset)
begin
   if (reset)
   begin
      i_data_valid_L  <= 1'b0;
      i_data_L[127:0] <= 128'b0;
   end
   else
   begin
      i_data_valid_L  <= i_data_valid;
      i_data_L[127:0] <=i_data[127:0];
   end
end
 
//---------------------------------------------------------------------------------------
// Inverse Mix Columns
//
//
inv_mix_columns imxc_u (.in(sr_data), .out(imc_data));
 
//---------------------------------------------------------------------------------------
// add round key for decryption
//
inv_mix_columns imxk_u (.in(round_key), .out(imc_round_key));
 
assign ark_data_final[127:0] = sr_data[127:0] ^ round_key[127:0];
assign ark_data_init[127:0] = i_data_L[127:0] ^ round_key[127:0];
assign en_ark_data[127:0] = mc_data[127:0] ^ round_key[127:0];
assign de_ark_data[127:0] = imc_data[127:0] ^ imc_round_key[127:0];
assign ark_data[127:0] = i_data_valid_L ? ark_data_init[127:0] : 
                           (final_round ? ark_data_final[127:0] : 
                                (i_ende ? de_ark_data[127:0] : en_ark_data[127:0]));
 
//---------------------------------------------------------------------------------------
// Data outputs after each round
//
always @ (posedge clk or posedge reset)
begin
   if (reset)
      o_data[127:0] <= 128'b0;
   else if (i_enable && (i_data_valid_L || sb_valid[2]))
      o_data[127:0] <= ark_data[127:0];
end
 
//---------------------------------------------------------------------------------------
// in sbox, we have 3 stages (sb_valid),
// before the end of each round, we have another stage (round_valid)
//
always @ (posedge clk or posedge reset)
begin
   if (reset)
   begin
      round_valid  <= 1'b0;
      sb_valid[2:0] <= 3'b0;
      o_data_valid  <= 1'b0;
   end
   else if (i_enable)
   begin
      o_data_valid  <= sb_valid[2] && final_round;
      round_valid   <= (sb_valid[2] && !final_round) || i_data_valid_L;
      sb_valid[2:0] <= {sb_valid[1:0],round_valid};
   end
end
 
always @ (posedge clk or posedge reset)
begin
   if (reset)                      round_cnt[3:0] <= 4'd0;
   else if (i_data_valid_L) round_cnt[3:0] <= 4'd1;
   else if (i_enable && sb_valid[2])  round_cnt[3:0] <= sb_round_cnt3[3:0] + 1'b1;
end
 
always @ (posedge clk or posedge reset)
begin
   if (reset)
   begin
      sb_round_cnt1[3:0] <= 4'd0;
      sb_round_cnt2[3:0] <= 4'd0;
      sb_round_cnt3[3:0] <= 4'd0;
   end
   else if (i_enable)
   begin
      if (round_valid) sb_round_cnt1[3:0] <= round_cnt[3:0];
      if (sb_valid[0]) sb_round_cnt2[3:0] <= sb_round_cnt1[3:0];
      if (sb_valid[1]) sb_round_cnt3[3:0] <= sb_round_cnt2[3:0];
   end
end
 
//---------------------------------------------------------------------------------------
// round key generation: the expansion keys are stored in 4 16*32 rams or 
// 2 16*64 rams or 1 16*128 rams
//
//assign rd_addr[3:0] = i_ende ? (max_round[3:0] - sb_round_cnt2[3:0]) : sb_round_cnt2[3:0];
 
assign round_key[127:0] = {rd_data0[63:0],rd_data1[63:0]};
 
`ifdef XILINX 
reg [3:0] rd_addr;
 
always @ (posedge clk or posedge reset)
begin 
	if (reset)
		rd_addr <= 4'b0;
	else if (sb_valid[1] | i_data_valid) 
	begin 
		if (i_ende) 
		begin 
			if (i_data_valid)
				rd_addr <= max_round[3:0];
			else 
				rd_addr <= max_round[3:0] - sb_round_cnt2[3:0];
		end 
		else 
		begin 
			if (i_data_valid) 
				rd_addr <= 4'b0;
			else 
				rd_addr <= sb_round_cnt2[3:0];
		end 
	end 
end 
 
xram_16x64 u_ram_0 
(
	.clk(clk),
	.wr(wr & ~wr_addr[0]),
	.wr_addr(wr_addr[4:1]),
	.wr_data(wr_data[63:0]),
	.rd_addr(rd_addr[3:0]),
	.rd_data(rd_data0[63:0])
);
xram_16x64 u_ram_1 
(
	.clk(clk),
	.wr(wr & wr_addr[0]),
	.wr_addr(wr_addr[4:1]),
	.wr_data(wr_data[63:0]),
	.rd_addr(rd_addr[3:0]),
	.rd_data(rd_data1[63:0])
);
`else 
wire [3:0] rd_addr;
 
assign rd_addr[3:0] = i_ende ? (i_data_valid ? max_round[3:0] : (max_round[3:0] - sb_round_cnt2[3:0])) : 
                               (i_data_valid ? 4'b0 : sb_round_cnt2[3:0]);
 
ram_16x64 u_ram_0 
(
	.clk(clk),
	.wr(wr & ~wr_addr[0]),
	.wr_addr(wr_addr[4:1]),
	.wr_data(wr_data[63:0]),
	.rd_addr(rd_addr[3:0]),
	.rd_data(rd_data0[63:0]),
	.rd(sb_valid[1] | i_data_valid)
);
ram_16x64 u_ram_1 
(
	.clk(clk),
	.wr(wr & wr_addr[0]),
	.wr_addr(wr_addr[4:1]),
	.wr_data(wr_data[63:0]),
	.rd_addr(rd_addr[3:0]),
	.rd_data(rd_data1[63:0]),
	.rd(sb_valid[1] | i_data_valid)
);
`endif 
//---------------------------------------------------------------------------------------
// Key Expansion module
//
//
key_exp u_key_exp (
   .clk(clk),
   .reset(reset),
   .key_in(i_key[255:0]),
   .key_mode(i_key_mode[1:0]),
   .key_start(i_start),
   .wr(wr),
   .wr_addr(wr_addr[4:0]),
   .wr_data(wr_data[63:0]),
   .key_ready(o_key_ready)
);
 
endmodule
//---------------------------------------------------------------------------------------
 

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

powered by: WebSVN 2.1.0

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