blob: dced4489142603d11ca55d4e31f3bb61f63b70b0 [file] [log] [blame]
//======================================================================
//
// salsa20_qr.v
// -----------
// Verilog 2001 implementation of the stream cipher Salsa20.
// This is the combinational QR logic as a separade module to allow
// us to build versions of the cipher with 1, 2, 4 and even 8
// parallel qr functions.
//
//
// Copyright (c) 2013 Secworks Sweden AB
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module salsa20_qr(
input wire [31 : 0] y0,
input wire [31 : 0] y1,
input wire [31 : 0] y2,
input wire [31 : 0] y3,
output wire [31 : 0] z0,
output wire [31 : 0] z1,
output wire [31 : 0] z2,
output wire [31 : 0] z3
);
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [31 : 0] tmp_z0;
reg [31 : 0] tmp_z1;
reg [31 : 0] tmp_z2;
reg [31 : 0] tmp_z3;
//----------------------------------------------------------------
// Concurrent connectivity for ports.
//----------------------------------------------------------------
assign z0 = tmp_z0;
assign z1 = tmp_z1;
assign z2 = tmp_z2;
assign z3 = tmp_z3;
//----------------------------------------------------------------
// qr
//
// The actual quarterround function.
//----------------------------------------------------------------
always @*
begin : qr
reg [31 : 0] z0_0;
reg [31 : 0] z1_0;
reg [31 : 0] z2_0;
reg [31 : 0] z3_0;
z1_0 = (y0 + y3);
tmp_z1 = {z1_0[24 : 0], z1_0[31 : 25]} ^ y1;
z2_0 = (tmp_z1 + y0);
tmp_z2 = {z2_0[22 : 0], z2_0[31 : 23]} ^ y2;
z3_0 = (tmp_z2 + tmp_z1);
tmp_z3 = {z3_0[18 : 0], z3_0[31 : 19]} ^ y3;
z0_0 = (tmp_z3 + tmp_z2);
tmp_z0 = {z0_0[13 : 0], z0_0[31 : 14]} ^ y0;
end // qr
endmodule // salsa20_qr
//======================================================================
// EOF salsa20_qr.v
//======================================================================
//======================================================================
//
// salsa20_core.v
// --------------
// Verilog 2001 implementation of the stream cipher Salsa20.
// This is the internal core with wide interfaces.
//
//
// Copyright (c) 2013 Secworks Sweden AB
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module salsa20_core(
input wire clk,
input wire reset_n,
input wire init,
input wire next,
input wire [255 : 0] key,
input wire keylen,
input wire [63 : 0] iv,
input wire [4 : 0] rounds,
input wire [511 : 0] data_in,
output wire ready,
output wire [511 : 0] data_out,
output wire data_out_valid
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
// Datapath quartterround states names.
parameter QR0 = 1'b0;
parameter QR1 = 1'b1;
parameter NUM_ROUNDS = 4'h8;
parameter TAU0 = 32'h61707865;
parameter TAU1 = 32'h3120646e;
parameter TAU2 = 32'h79622d36;
parameter TAU3 = 32'h6b206574;
parameter SIGMA0 = 32'h61707865;
parameter SIGMA1 = 32'h3320646e;
parameter SIGMA2 = 32'h79622d32;
parameter SIGMA3 = 32'h6b206574;
parameter CTRL_IDLE = 3'h0;
parameter CTRL_INIT = 3'h1;
parameter CTRL_ROUNDS = 3'h2;
parameter CTRL_FINALIZE = 3'h3;
parameter CTRL_DONE = 3'h4;
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [31 : 0] key0_reg;
reg [31 : 0] key0_new;
reg [31 : 0] key1_reg;
reg [31 : 0] key1_new;
reg [31 : 0] key2_reg;
reg [31 : 0] key2_new;
reg [31 : 0] key3_reg;
reg [31 : 0] key3_new;
reg [31 : 0] key4_reg;
reg [31 : 0] key4_new;
reg [31 : 0] key5_reg;
reg [31 : 0] key5_new;
reg [31 : 0] key6_reg;
reg [31 : 0] key6_new;
reg [31 : 0] key7_reg;
reg [31 : 0] key7_new;
reg keylen_reg;
reg keylen_new;
reg [31 : 0] iv0_reg;
reg [31 : 0] iv0_new;
reg [31 : 0] iv1_reg;
reg [31 : 0] iv1_new;
reg [31 : 0] state0_reg;
reg [31 : 0] state0_new;
reg [31 : 0] state1_reg;
reg [31 : 0] state1_new;
reg [31 : 0] state2_reg;
reg [31 : 0] state2_new;
reg [31 : 0] state3_reg;
reg [31 : 0] state3_new;
reg [31 : 0] state4_reg;
reg [31 : 0] state4_new;
reg [31 : 0] state5_reg;
reg [31 : 0] state5_new;
reg [31 : 0] state6_reg;
reg [31 : 0] state6_new;
reg [31 : 0] state7_reg;
reg [31 : 0] state7_new;
reg [31 : 0] state8_reg;
reg [31 : 0] state8_new;
reg [31 : 0] state9_reg;
reg [31 : 0] state9_new;
reg [31 : 0] state10_reg;
reg [31 : 0] state10_new;
reg [31 : 0] state11_reg;
reg [31 : 0] state11_new;
reg [31 : 0] state12_reg;
reg [31 : 0] state12_new;
reg [31 : 0] state13_reg;
reg [31 : 0] state13_new;
reg [31 : 0] state14_reg;
reg [31 : 0] state14_new;
reg [31 : 0] state15_reg;
reg [31 : 0] state15_new;
reg state_we;
reg [31 : 0] x0_reg;
reg [31 : 0] x0_new;
reg x0_we;
reg [31 : 0] x1_reg;
reg [31 : 0] x1_new;
reg x1_we;
reg [31 : 0] x2_reg;
reg [31 : 0] x2_new;
reg x2_we;
reg [31 : 0] x3_reg;
reg [31 : 0] x3_new;
reg x3_we;
reg [31 : 0] x4_reg;
reg [31 : 0] x4_new;
reg x4_we;
reg [31 : 0] x5_reg;
reg [31 : 0] x5_new;
reg x5_we;
reg [31 : 0] x6_reg;
reg [31 : 0] x6_new;
reg x6_we;
reg [31 : 0] x7_reg;
reg [31 : 0] x7_new;
reg x7_we;
reg [31 : 0] x8_reg;
reg [31 : 0] x8_new;
reg x8_we;
reg [31 : 0] x9_reg;
reg [31 : 0] x9_new;
reg x9_we;
reg [31 : 0] x10_reg;
reg [31 : 0] x10_new;
reg x10_we;
reg [31 : 0] x11_reg;
reg [31 : 0] x11_new;
reg x11_we;
reg [31 : 0] x12_reg;
reg [31 : 0] x12_new;
reg x12_we;
reg [31 : 0] x13_reg;
reg [31 : 0] x13_new;
reg x13_we;
reg [31 : 0] x14_reg;
reg [31 : 0] x14_new;
reg x14_we;
reg [31 : 0] x15_reg;
reg [31 : 0] x15_new;
reg x15_we;
reg [3 : 0] rounds_reg;
reg [3 : 0] rounds_new;
reg [511 : 0] data_in_reg;
reg data_in_we;
reg [511 : 0] data_out_reg;
reg [511 : 0] data_out_new;
reg data_out_we;
reg data_out_valid_reg;
reg data_out_valid_new;
reg data_out_valid_we;
reg qr_ctr_reg;
reg qr_ctr_new;
reg qr_ctr_we;
reg qr_ctr_inc;
reg qr_ctr_rst;
reg [3 : 0] dr_ctr_reg;
reg [3 : 0] dr_ctr_new;
reg dr_ctr_we;
reg dr_ctr_inc;
reg dr_ctr_rst;
reg [31 : 0] block0_ctr_reg;
reg [31 : 0] block0_ctr_new;
reg block0_ctr_we;
reg [31 : 0] block1_ctr_reg;
reg [31 : 0] block1_ctr_new;
reg block1_ctr_we;
reg block_ctr_inc;
reg block_ctr_rst;
reg [2 : 0] salsa20_ctrl_reg;
reg [2 : 0] salsa20_ctrl_new;
reg salsa20_ctrl_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg sample_params;
reg init_state;
reg update_state;
reg update_output;
reg [31 : 0] qr0_a;
reg [31 : 0] qr0_b;
reg [31 : 0] qr0_c;
reg [31 : 0] qr0_d;
wire [31 : 0] qr0_a_prim;
wire [31 : 0] qr0_b_prim;
wire [31 : 0] qr0_c_prim;
wire [31 : 0] qr0_d_prim;
reg [31 : 0] qr1_a;
reg [31 : 0] qr1_b;
reg [31 : 0] qr1_c;
reg [31 : 0] qr1_d;
wire [31 : 0] qr1_a_prim;
wire [31 : 0] qr1_b_prim;
wire [31 : 0] qr1_c_prim;
wire [31 : 0] qr1_d_prim;
reg [31 : 0] qr2_a;
reg [31 : 0] qr2_b;
reg [31 : 0] qr2_c;
reg [31 : 0] qr2_d;
wire [31 : 0] qr2_a_prim;
wire [31 : 0] qr2_b_prim;
wire [31 : 0] qr2_c_prim;
wire [31 : 0] qr2_d_prim;
reg [31 : 0] qr3_a;
reg [31 : 0] qr3_b;
reg [31 : 0] qr3_c;
reg [31 : 0] qr3_d;
wire [31 : 0] qr3_a_prim;
wire [31 : 0] qr3_b_prim;
wire [31 : 0] qr3_c_prim;
wire [31 : 0] qr3_d_prim;
reg ready_wire;
//----------------------------------------------------------------
// Instantiation of the qr modules.
//----------------------------------------------------------------
salsa20_qr qr0(
.y0(qr0_a),
.y1(qr0_b),
.y2(qr0_c),
.y3(qr0_d),
.z0(qr0_a_prim),
.z1(qr0_b_prim),
.z2(qr0_c_prim),
.z3(qr0_d_prim)
);
salsa20_qr qr1(
.y0(qr1_a),
.y1(qr1_b),
.y2(qr1_c),
.y3(qr1_d),
.z0(qr1_a_prim),
.z1(qr1_b_prim),
.z2(qr1_c_prim),
.z3(qr1_d_prim)
);
salsa20_qr qr2(
.y0(qr2_a),
.y1(qr2_b),
.y2(qr2_c),
.y3(qr2_d),
.z0(qr2_a_prim),
.z1(qr2_b_prim),
.z2(qr2_c_prim),
.z3(qr2_d_prim)
);
salsa20_qr qr3(
.y0(qr3_a),
.y1(qr3_b),
.y2(qr3_c),
.y3(qr3_d),
.z0(qr3_a_prim),
.z1(qr3_b_prim),
.z2(qr3_c_prim),
.z3(qr3_d_prim)
);
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign data_out = data_out_reg;
assign data_out_valid = data_out_valid_reg;
assign ready = ready_wire;
//----------------------------------------------------------------
// reg_update
// Update functionality for all registers in the core.
// All registers are positive edge triggered with synchronous
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk)
begin : reg_update
if (!reset_n)
begin
key0_reg <= 32'h00000000;
key1_reg <= 32'h00000000;
key2_reg <= 32'h00000000;
key3_reg <= 32'h00000000;
key4_reg <= 32'h00000000;
key5_reg <= 32'h00000000;
key6_reg <= 32'h00000000;
key7_reg <= 32'h00000000;
iv0_reg <= 32'h00000000;
iv1_reg <= 32'h00000000;
state0_reg <= 32'h00000000;
state1_reg <= 32'h00000000;
state2_reg <= 32'h00000000;
state3_reg <= 32'h00000000;
state4_reg <= 32'h00000000;
state5_reg <= 32'h00000000;
state6_reg <= 32'h00000000;
state7_reg <= 32'h00000000;
state8_reg <= 32'h00000000;
state9_reg <= 32'h00000000;
state10_reg <= 32'h00000000;
state11_reg <= 32'h00000000;
state12_reg <= 32'h00000000;
state13_reg <= 32'h00000000;
state14_reg <= 32'h00000000;
state15_reg <= 32'h00000000;
x0_reg <= 32'h00000000;
x1_reg <= 32'h00000000;
x2_reg <= 32'h00000000;
x3_reg <= 32'h00000000;
x4_reg <= 32'h00000000;
x5_reg <= 32'h00000000;
x6_reg <= 32'h00000000;
x7_reg <= 32'h00000000;
x8_reg <= 32'h00000000;
x9_reg <= 32'h00000000;
x10_reg <= 32'h00000000;
x11_reg <= 32'h00000000;
x12_reg <= 32'h00000000;
x13_reg <= 32'h00000000;
x14_reg <= 32'h00000000;
x15_reg <= 32'h00000000;
data_in_reg <= 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
data_out_reg <= 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
rounds_reg <= 4'h0;
data_out_valid_reg <= 0;
qr_ctr_reg <= QR0;
dr_ctr_reg <= 0;
block0_ctr_reg <= 32'h00000000;
block1_ctr_reg <= 32'h00000000;
salsa20_ctrl_reg <= CTRL_IDLE;
end
else
begin
if (sample_params)
begin
key0_reg <= key0_new;
key1_reg <= key1_new;
key2_reg <= key2_new;
key3_reg <= key3_new;
key4_reg <= key4_new;
key5_reg <= key5_new;
key6_reg <= key6_new;
key7_reg <= key7_new;
iv0_reg <= iv0_new;
iv1_reg <= iv1_new;
rounds_reg <= rounds_new;
keylen_reg <= keylen_new;
end
if (data_in_we)
begin
data_in_reg <= data_in;
end
if (state_we)
begin
state0_reg <= state0_new;
state1_reg <= state1_new;
state2_reg <= state2_new;
state3_reg <= state3_new;
state4_reg <= state4_new;
state5_reg <= state5_new;
state6_reg <= state6_new;
state7_reg <= state7_new;
state8_reg <= state8_new;
state9_reg <= state9_new;
state10_reg <= state10_new;
state11_reg <= state11_new;
state12_reg <= state12_new;
state13_reg <= state13_new;
state14_reg <= state14_new;
state15_reg <= state15_new;
end
if (x0_we)
begin
x0_reg <= x0_new;
end
if (x1_we)
begin
x1_reg <= x1_new;
end
if (x2_we)
begin
x2_reg <= x2_new;
end
if (x3_we)
begin
x3_reg <= x3_new;
end
if (x4_we)
begin
x4_reg <= x4_new;
end
if (x5_we)
begin
x5_reg <= x5_new;
end
if (x6_we)
begin
x6_reg <= x6_new;
end
if (x7_we)
begin
x7_reg <= x7_new;
end
if (x8_we)
begin
x8_reg <= x8_new;
end
if (x9_we)
begin
x9_reg <= x9_new;
end
if (x10_we)
begin
x10_reg <= x10_new;
end
if (x11_we)
begin
x11_reg <= x11_new;
end
if (x12_we)
begin
x12_reg <= x12_new;
end
if (x13_we)
begin
x13_reg <= x13_new;
end
if (x14_we)
begin
x14_reg <= x14_new;
end
if (x15_we)
begin
x15_reg <= x15_new;
end
if (data_out_we)
begin
data_out_reg <= data_out_new;
end
if (data_out_valid_we)
begin
data_out_valid_reg <= data_out_valid_new;
end
if (qr_ctr_we)
begin
qr_ctr_reg <= qr_ctr_new;
end
if (dr_ctr_we)
begin
dr_ctr_reg <= dr_ctr_new;
end
if (block0_ctr_we)
begin
block0_ctr_reg <= block0_ctr_new;
end
if (block1_ctr_we)
begin
block1_ctr_reg <= block1_ctr_new;
end
if (salsa20_ctrl_we)
begin
salsa20_ctrl_reg <= salsa20_ctrl_new;
end
end
end // reg_update
//----------------------------------------------------------------
// data_out_logic
// Final output logic that combines the result from procceing
// with the input word. This adds a final layer of XOR gates.
//
// Note that we also remap all the words into LSB format.
//----------------------------------------------------------------
always @*
begin : data_out_logic
reg [31 : 0] msb_block_state0;
reg [31 : 0] msb_block_state1;
reg [31 : 0] msb_block_state2;
reg [31 : 0] msb_block_state3;
reg [31 : 0] msb_block_state4;
reg [31 : 0] msb_block_state5;
reg [31 : 0] msb_block_state6;
reg [31 : 0] msb_block_state7;
reg [31 : 0] msb_block_state8;
reg [31 : 0] msb_block_state9;
reg [31 : 0] msb_block_state10;
reg [31 : 0] msb_block_state11;
reg [31 : 0] msb_block_state12;
reg [31 : 0] msb_block_state13;
reg [31 : 0] msb_block_state14;
reg [31 : 0] msb_block_state15;
reg [31 : 0] lsb_block_state0;
reg [31 : 0] lsb_block_state1;
reg [31 : 0] lsb_block_state2;
reg [31 : 0] lsb_block_state3;
reg [31 : 0] lsb_block_state4;
reg [31 : 0] lsb_block_state5;
reg [31 : 0] lsb_block_state6;
reg [31 : 0] lsb_block_state7;
reg [31 : 0] lsb_block_state8;
reg [31 : 0] lsb_block_state9;
reg [31 : 0] lsb_block_state10;
reg [31 : 0] lsb_block_state11;
reg [31 : 0] lsb_block_state12;
reg [31 : 0] lsb_block_state13;
reg [31 : 0] lsb_block_state14;
reg [31 : 0] lsb_block_state15;
reg [511 : 0] lsb_block_state;
lsb_block_state = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
data_out_new = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
data_out_we = 0;
if (update_output)
begin
msb_block_state0 = state0_reg + x0_reg;
msb_block_state1 = state1_reg + x1_reg;
msb_block_state2 = state2_reg + x2_reg;
msb_block_state3 = state3_reg + x3_reg;
msb_block_state4 = state4_reg + x4_reg;
msb_block_state5 = state5_reg + x5_reg;
msb_block_state6 = state6_reg + x6_reg;
msb_block_state7 = state7_reg + x7_reg;
msb_block_state8 = state8_reg + x8_reg;
msb_block_state9 = state9_reg + x9_reg;
msb_block_state10 = state10_reg + x10_reg;
msb_block_state11 = state11_reg + x11_reg;
msb_block_state12 = state12_reg + x12_reg;
msb_block_state13 = state13_reg + x13_reg;
msb_block_state14 = state14_reg + x14_reg;
msb_block_state15 = state15_reg + x15_reg;
lsb_block_state0 = {msb_block_state0[7 : 0],
msb_block_state0[15 : 8],
msb_block_state0[23 : 16],
msb_block_state0[31 : 24]};
lsb_block_state1 = {msb_block_state1[7 : 0],
msb_block_state1[15 : 8],
msb_block_state1[23 : 16],
msb_block_state1[31 : 24]};
lsb_block_state2 = {msb_block_state2[7 : 0],
msb_block_state2[15 : 8],
msb_block_state2[23 : 16],
msb_block_state2[31 : 24]};
lsb_block_state3 = {msb_block_state3[7 : 0],
msb_block_state3[15 : 8],
msb_block_state3[23 : 16],
msb_block_state3[31 : 24]};
lsb_block_state4 = {msb_block_state4[7 : 0],
msb_block_state4[15 : 8],
msb_block_state4[23 : 16],
msb_block_state4[31 : 24]};
lsb_block_state5 = {msb_block_state5[7 : 0],
msb_block_state5[15 : 8],
msb_block_state5[23 : 16],
msb_block_state5[31 : 24]};
lsb_block_state6 = {msb_block_state6[7 : 0],
msb_block_state6[15 : 8],
msb_block_state6[23 : 16],
msb_block_state6[31 : 24]};
lsb_block_state7 = {msb_block_state7[7 : 0],
msb_block_state7[15 : 8],
msb_block_state7[23 : 16],
msb_block_state7[31 : 24]};
lsb_block_state8 = {msb_block_state8[7 : 0],
msb_block_state8[15 : 8],
msb_block_state8[23 : 16],
msb_block_state8[31 : 24]};
lsb_block_state9 = {msb_block_state9[7 : 0],
msb_block_state9[15 : 8],
msb_block_state9[23 : 16],
msb_block_state9[31 : 24]};
lsb_block_state10 = {msb_block_state10[7 : 0],
msb_block_state10[15 : 8],
msb_block_state10[23 : 16],
msb_block_state10[31 : 24]};
lsb_block_state11 = {msb_block_state11[7 : 0],
msb_block_state11[15 : 8],
msb_block_state11[23 : 16],
msb_block_state11[31 : 24]};
lsb_block_state12 = {msb_block_state12[7 : 0],
msb_block_state12[15 : 8],
msb_block_state12[23 : 16],
msb_block_state12[31 : 24]};
lsb_block_state13 = {msb_block_state13[7 : 0],
msb_block_state13[15 : 8],
msb_block_state13[23 : 16],
msb_block_state13[31 : 24]};
lsb_block_state14 = {msb_block_state14[7 : 0],
msb_block_state14[15 : 8],
msb_block_state14[23 : 16],
msb_block_state14[31 : 24]};
lsb_block_state15 = {msb_block_state15[7 : 0],
msb_block_state15[15 : 8],
msb_block_state15[23 : 16],
msb_block_state15[31 : 24]};
lsb_block_state = {lsb_block_state0, lsb_block_state1,
lsb_block_state2, lsb_block_state3,
lsb_block_state4, lsb_block_state5,
lsb_block_state6, lsb_block_state7,
lsb_block_state8, lsb_block_state9,
lsb_block_state10, lsb_block_state11,
lsb_block_state12, lsb_block_state13,
lsb_block_state14, lsb_block_state15};
data_out_new = data_in_reg ^ lsb_block_state;
data_out_we = 1;
end // if (update_output)
end // data_out_logic
//----------------------------------------------------------------
// sample_parameters
// Logic (wires) that convert parameter input to appropriate
// format for processing.
//----------------------------------------------------------------
always @*
begin : sample_parameters
key0_new = 32'h00000000;
key1_new = 32'h00000000;
key2_new = 32'h00000000;
key3_new = 32'h00000000;
key4_new = 32'h00000000;
key5_new = 32'h00000000;
key6_new = 32'h00000000;
key7_new = 32'h00000000;
iv0_new = 32'h00000000;
iv1_new = 32'h00000000;
rounds_new = 4'h0;
keylen_new = 1'b0;
if (sample_params)
begin
key0_new = {key[231 : 224], key[239 : 232],
key[247 : 240], key[255 : 248]};
key1_new = {key[199 : 192], key[207 : 200],
key[215 : 208], key[223 : 216]};
key2_new = {key[167 : 160], key[175 : 168],
key[183 : 176], key[191 : 184]};
key3_new = {key[135 : 128], key[143 : 136],
key[151 : 144], key[159 : 152]};
key4_new = {key[103 : 96], key[111 : 104],
key[119 : 112], key[127 : 120]};
key5_new = {key[71 : 64], key[79 : 72],
key[87 : 80], key[95 : 88]};
key6_new = {key[39 : 32], key[47 : 40],
key[55 : 48], key[63 : 56]};
key7_new = {key[7 : 0], key[15 : 8],
key[23 : 16], key[31 : 24]};
iv0_new = {iv[39 : 32], iv[47 : 40],
iv[55 : 48], iv[63 : 56]};
iv1_new = {iv[7 : 0], iv[15 : 8],
iv[23 : 16], iv[31 : 24]};
// Div by two since we count double rounds.
rounds_new = rounds[4 : 1];
keylen_new = keylen;
end
end
//----------------------------------------------------------------
// state_logic
// Logic to init and update the internal state.
//----------------------------------------------------------------
always @*
begin : state_logic
reg [31 : 0] new_state_word0;
reg [31 : 0] new_state_word1;
reg [31 : 0] new_state_word2;
reg [31 : 0] new_state_word3;
reg [31 : 0] new_state_word4;
reg [31 : 0] new_state_word5;
reg [31 : 0] new_state_word6;
reg [31 : 0] new_state_word7;
reg [31 : 0] new_state_word8;
reg [31 : 0] new_state_word9;
reg [31 : 0] new_state_word10;
reg [31 : 0] new_state_word11;
reg [31 : 0] new_state_word12;
reg [31 : 0] new_state_word13;
reg [31 : 0] new_state_word14;
reg [31 : 0] new_state_word15;
new_state_word0 = 32'h00000000;
new_state_word1 = 32'h00000000;
new_state_word2 = 32'h00000000;
new_state_word3 = 32'h00000000;
new_state_word4 = 32'h00000000;
new_state_word5 = 32'h00000000;
new_state_word6 = 32'h00000000;
new_state_word7 = 32'h00000000;
new_state_word8 = 32'h00000000;
new_state_word9 = 32'h00000000;
new_state_word10 = 32'h00000000;
new_state_word11 = 32'h00000000;
new_state_word12 = 32'h00000000;
new_state_word13 = 32'h00000000;
new_state_word14 = 32'h00000000;
new_state_word15 = 32'h00000000;
x0_new = 32'h00000000;
x1_new = 32'h00000000;
x2_new = 32'h00000000;
x3_new = 32'h00000000;
x4_new = 32'h00000000;
x5_new = 32'h00000000;
x6_new = 32'h00000000;
x7_new = 32'h00000000;
x8_new = 32'h00000000;
x9_new = 32'h00000000;
x10_new = 32'h00000000;
x11_new = 32'h00000000;
x12_new = 32'h00000000;
x13_new = 32'h00000000;
x14_new = 32'h00000000;
x15_new = 32'h00000000;
x0_we = 0;
x1_we = 0;
x2_we = 0;
x3_we = 0;
x4_we = 0;
x5_we = 0;
x6_we = 0;
x7_we = 0;
x8_we = 0;
x9_we = 0;
x10_we = 0;
x11_we = 0;
x12_we = 0;
x13_we = 0;
x14_we = 0;
x15_we = 0;
state0_new = 32'h00000000;
state1_new = 32'h00000000;
state2_new = 32'h00000000;
state3_new = 32'h00000000;
state4_new = 32'h00000000;
state5_new = 32'h00000000;
state6_new = 32'h00000000;
state7_new = 32'h00000000;
state8_new = 32'h00000000;
state9_new = 32'h00000000;
state10_new = 32'h00000000;
state11_new = 32'h00000000;
state12_new = 32'h00000000;
state13_new = 32'h00000000;
state14_new = 32'h00000000;
state15_new = 32'h00000000;
state_we = 0;
if (init_state)
begin
new_state_word4 = key0_reg;
new_state_word5 = key1_reg;
new_state_word6 = key2_reg;
new_state_word7 = key3_reg;
new_state_word12 = block0_ctr_reg;
new_state_word13 = block1_ctr_reg;
new_state_word14 = iv0_reg;
new_state_word15 = iv1_reg;
if (keylen_reg)
begin
// 256 bit key.
new_state_word0 = SIGMA0;
new_state_word1 = SIGMA1;
new_state_word2 = SIGMA2;
new_state_word3 = SIGMA3;
new_state_word8 = key4_reg;
new_state_word9 = key5_reg;
new_state_word10 = key6_reg;
new_state_word11 = key7_reg;
end
else
begin
// 128 bit key.
new_state_word0 = TAU0;
new_state_word1 = TAU1;
new_state_word2 = TAU2;
new_state_word3 = TAU3;
new_state_word8 = key0_reg;
new_state_word9 = key1_reg;
new_state_word10 = key2_reg;
new_state_word11 = key3_reg;
end
x0_new = new_state_word0;
x1_new = new_state_word1;
x2_new = new_state_word2;
x3_new = new_state_word3;
x4_new = new_state_word4;
x5_new = new_state_word5;
x6_new = new_state_word6;
x7_new = new_state_word7;
x8_new = new_state_word8;
x9_new = new_state_word9;
x10_new = new_state_word10;
x11_new = new_state_word11;
x12_new = new_state_word12;
x13_new = new_state_word13;
x14_new = new_state_word14;
x15_new = new_state_word15;
x0_we = 1;
x1_we = 1;
x2_we = 1;
x3_we = 1;
x4_we = 1;
x5_we = 1;
x6_we = 1;
x7_we = 1;
x8_we = 1;
x9_we = 1;
x10_we = 1;
x11_we = 1;
x12_we = 1;
x13_we = 1;
x14_we = 1;
x15_we = 1;
state0_new = new_state_word0;
state1_new = new_state_word1;
state2_new = new_state_word2;
state3_new = new_state_word3;
state4_new = new_state_word4;
state5_new = new_state_word5;
state6_new = new_state_word6;
state7_new = new_state_word7;
state8_new = new_state_word8;
state9_new = new_state_word9;
state10_new = new_state_word10;
state11_new = new_state_word11;
state12_new = new_state_word12;
state13_new = new_state_word13;
state14_new = new_state_word14;
state15_new = new_state_word15;
state_we = 1;
end // if (init_state)
else if (update_state)
begin
case (qr_ctr_reg)
QR0:
begin
x0_new = qr0_a_prim;
x4_new = qr0_b_prim;
x8_new = qr0_c_prim;
x12_new = qr0_d_prim;
x0_we = 1;
x4_we = 1;
x8_we = 1;
x12_we = 1;
x1_new = qr1_a_prim;
x5_new = qr1_b_prim;
x9_new = qr1_c_prim;
x13_new = qr1_d_prim;
x1_we = 1;
x5_we = 1;
x9_we = 1;
x13_we = 1;
x2_new = qr2_a_prim;
x6_new = qr2_b_prim;
x10_new = qr2_c_prim;
x14_new = qr2_d_prim;
x2_we = 1;
x6_we = 1;
x10_we = 1;
x14_we = 1;
x3_new = qr3_a_prim;
x7_new = qr3_b_prim;
x11_new = qr3_c_prim;
x15_new = qr3_d_prim;
x3_we = 1;
x7_we = 1;
x11_we = 1;
x15_we = 1;
end
QR1:
begin
x0_new = qr0_a_prim;
x5_new = qr0_b_prim;
x10_new = qr0_c_prim;
x15_new = qr0_d_prim;
x0_we = 1;
x5_we = 1;
x10_we = 1;
x15_we = 1;
x1_new = qr1_a_prim;
x6_new = qr1_b_prim;
x11_new = qr1_c_prim;
x12_new = qr1_d_prim;
x1_we = 1;
x6_we = 1;
x11_we = 1;
x12_we = 1;
x2_new = qr2_a_prim;
x7_new = qr2_b_prim;
x8_new = qr2_c_prim;
x13_new = qr2_d_prim;
x2_we = 1;
x7_we = 1;
x8_we = 1;
x13_we = 1;
x3_new = qr3_a_prim;
x4_new = qr3_b_prim;
x9_new = qr3_c_prim;
x14_new = qr3_d_prim;
x3_we = 1;
x4_we = 1;
x9_we = 1;
x14_we = 1;
end
endcase // case (quarterround_select)
end // if (update_state)
end // state_logic
//----------------------------------------------------------------
// quarterround_mux
// Quarterround muxes that selects operands for quarterrounds.
//----------------------------------------------------------------
always @*
begin : quarterround_mux
case (qr_ctr_reg)
QR0:
begin
qr0_a = x0_reg;
qr0_b = x4_reg;
qr0_c = x8_reg;
qr0_d = x12_reg;
qr1_a = x1_reg;
qr1_b = x5_reg;
qr1_c = x9_reg;
qr1_d = x13_reg;
qr2_a = x2_reg;
qr2_b = x6_reg;
qr2_c = x10_reg;
qr2_d = x14_reg;
qr3_a = x3_reg;
qr3_b = x7_reg;
qr3_c = x11_reg;
qr3_d = x15_reg;
end
QR1:
begin
qr0_a = x0_reg;
qr0_b = x5_reg;
qr0_c = x10_reg;
qr0_d = x15_reg;
qr1_a = x1_reg;
qr1_b = x6_reg;
qr1_c = x11_reg;
qr1_d = x12_reg;
qr2_a = x2_reg;
qr2_b = x7_reg;
qr2_c = x8_reg;
qr2_d = x13_reg;
qr3_a = x3_reg;
qr3_b = x4_reg;
qr3_c = x9_reg;
qr3_d = x14_reg;
end
endcase // case (quarterround_select)
end // quarterround_mux
//----------------------------------------------------------------
// qr_ctr
// Update logic for the quarterround counter, a monotonically
// increasing counter with reset.
//----------------------------------------------------------------
always @*
begin : qr_ctr
qr_ctr_new = 0;
qr_ctr_we = 0;
if (qr_ctr_rst)
begin
qr_ctr_new = 0;
qr_ctr_we = 1;
end
if (qr_ctr_inc)
begin
qr_ctr_new = qr_ctr_reg + 1'b1;
qr_ctr_we = 1;
end
end // qr_ctr
//----------------------------------------------------------------
// dr_ctr
// Update logic for the round counter, a monotonically
// increasing counter with reset.
//----------------------------------------------------------------
always @*
begin : dr_ctr
dr_ctr_new = 0;
dr_ctr_we = 0;
if (dr_ctr_rst)
begin
dr_ctr_new = 0;
dr_ctr_we = 1;
end
if (dr_ctr_inc)
begin
dr_ctr_new = dr_ctr_reg + 1'b1;
dr_ctr_we = 1;
end
end // dr_ctr
//----------------------------------------------------------------
// block_ctr
// Update logic for the 64-bit block counter, a monotonically
// increasing counter with reset.
//----------------------------------------------------------------
always @*
begin : block_ctr
// Defult assignments
block0_ctr_new = 32'h00000000;
block1_ctr_new = 32'h00000000;
block0_ctr_we = 0;
block1_ctr_we = 0;
if (block_ctr_rst)
begin
block0_ctr_we = 1;
block1_ctr_we = 1;
end
if (block_ctr_inc)
begin
block0_ctr_new = block0_ctr_reg + 1;
block0_ctr_we = 1;
// Avoid chaining the 32-bit adders.
if (block0_ctr_reg == 32'hffffffff)
begin
block1_ctr_new = block1_ctr_reg + 1;
block1_ctr_we = 1;
end
end
end // block_ctr
//----------------------------------------------------------------
// salsa20_ctrl_fsm
// Logic for the state machine controlling the core behaviour.
//----------------------------------------------------------------
always @*
begin : salsa20_ctrl_fsm
init_state = 0;
update_state = 0;
sample_params = 0;
update_output = 0;
qr_ctr_inc = 0;
qr_ctr_rst = 0;
dr_ctr_inc = 0;
dr_ctr_rst = 0;
block_ctr_inc = 0;
block_ctr_rst = 0;
data_in_we = 0;
ready_wire = 0;
data_out_valid_new = 0;
data_out_valid_we = 0;
salsa20_ctrl_new = CTRL_IDLE;
salsa20_ctrl_we = 0;
case (salsa20_ctrl_reg)
CTRL_IDLE:
begin
ready_wire = 1;
if (init)
begin
data_in_we = 1;
sample_params = 1;
block_ctr_rst = 1;
salsa20_ctrl_new = CTRL_INIT;
salsa20_ctrl_we = 1;
end
end
CTRL_INIT:
begin
init_state = 1;
qr_ctr_rst = 1;
dr_ctr_rst = 1;
salsa20_ctrl_new = CTRL_ROUNDS;
salsa20_ctrl_we = 1;
end
CTRL_ROUNDS:
begin
update_state = 1;
qr_ctr_inc = 1;
if (qr_ctr_reg == QR1)
begin
dr_ctr_inc = 1;
if (dr_ctr_reg == (rounds_reg - 1))
begin
salsa20_ctrl_new = CTRL_FINALIZE;
salsa20_ctrl_we = 1;
end
end
end
CTRL_FINALIZE:
begin
update_output = 1;
data_out_valid_new = 1;
data_out_valid_we = 1;
salsa20_ctrl_new = CTRL_DONE;
salsa20_ctrl_we = 1;
end
CTRL_DONE:
begin
ready_wire = 1;
if (init)
begin
data_out_valid_new = 0;
data_out_valid_we = 1;
data_in_we = 1;
sample_params = 1;
block_ctr_rst = 1;
salsa20_ctrl_new = CTRL_INIT;
salsa20_ctrl_we = 1;
end
else if (next)
begin
data_out_valid_new = 0;
data_out_valid_we = 1;
data_in_we = 1;
block_ctr_inc = 1;
salsa20_ctrl_new = CTRL_INIT;
salsa20_ctrl_we = 1;
end
end
endcase // case (salsa20_ctrl_reg)
end // salsa20_ctrl_fsm
endmodule // salsa20_core
//======================================================================
// EOF salsa20_core.v
//======================================================================
//======================================================================
//
// salsa20.v
// --------
// Top level wrapper for the Salsa20 stream, cipher core providing
// a simple memory like interface with 32 bit data access.
//
//
// Copyright (c) 2013 Secworks Sweden AB
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module salsa20(
// Clock and reset.
input wire clk,
input wire reset_n,
// Control.
input wire cs,
input wire we,
// Data ports.
input wire [7 : 0] address,
input wire [31 : 0] write_data,
output wire [31 : 0] read_data,
output wire error
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
parameter ADDR_CTRL = 8'h00;
parameter CTRL_INIT_BIT = 0;
parameter CTRL_NEXT_BIT = 1;
parameter ADDR_STATUS = 8'h01;
parameter STATUS_READY_BIT = 0;
parameter ADDR_KEYLEN = 8'h08;
parameter KEYLEN_BIT = 0;
parameter ADDR_ROUNDS = 8'h09;
parameter ROUNDS_HIGH_BIT = 4;
parameter ROUNDS_LOW_BIT = 0;
parameter ADDR_KEY0 = 8'h10;
parameter ADDR_KEY1 = 8'h11;
parameter ADDR_KEY2 = 8'h12;
parameter ADDR_KEY3 = 8'h13;
parameter ADDR_KEY4 = 8'h14;
parameter ADDR_KEY5 = 8'h15;
parameter ADDR_KEY6 = 8'h16;
parameter ADDR_KEY7 = 8'h17;
parameter ADDR_IV0 = 8'h20;
parameter ADDR_IV1 = 8'h21;
parameter ADDR_DATA_IN0 = 8'h40;
parameter ADDR_DATA_IN1 = 8'h41;
parameter ADDR_DATA_IN2 = 8'h42;
parameter ADDR_DATA_IN3 = 8'h43;
parameter ADDR_DATA_IN4 = 8'h44;
parameter ADDR_DATA_IN5 = 8'h45;
parameter ADDR_DATA_IN6 = 8'h46;
parameter ADDR_DATA_IN7 = 8'h47;
parameter ADDR_DATA_IN8 = 8'h48;
parameter ADDR_DATA_IN9 = 8'h49;
parameter ADDR_DATA_IN10 = 8'h4a;
parameter ADDR_DATA_IN11 = 8'h4b;
parameter ADDR_DATA_IN12 = 8'h4c;
parameter ADDR_DATA_IN13 = 8'h4d;
parameter ADDR_DATA_IN14 = 8'h4e;
parameter ADDR_DATA_IN15 = 8'h4f;
parameter ADDR_DATA_OUT0 = 8'h80;
parameter ADDR_DATA_OUT1 = 8'h81;
parameter ADDR_DATA_OUT2 = 8'h82;
parameter ADDR_DATA_OUT3 = 8'h83;
parameter ADDR_DATA_OUT4 = 8'h84;
parameter ADDR_DATA_OUT5 = 8'h85;
parameter ADDR_DATA_OUT6 = 8'h86;
parameter ADDR_DATA_OUT7 = 8'h87;
parameter ADDR_DATA_OUT8 = 8'h88;
parameter ADDR_DATA_OUT9 = 8'h89;
parameter ADDR_DATA_OUT10 = 8'h8a;
parameter ADDR_DATA_OUT11 = 8'h8b;
parameter ADDR_DATA_OUT12 = 8'h8c;
parameter ADDR_DATA_OUT13 = 8'h8d;
parameter ADDR_DATA_OUT14 = 8'h8e;
parameter ADDR_DATA_OUT15 = 8'h8f;
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg init_reg;
reg next_reg;
reg ctrl_we;
reg ready_reg;
reg keylen_reg;
reg keylen_we;
reg [4 : 0] rounds_reg;
reg rounds_we;
reg data_out_valid_reg;
reg [31 : 0] key0_reg;
reg key0_we;
reg [31 : 0] key1_reg;
reg key1_we;
reg [31 : 0] key2_reg;
reg key2_we;
reg [31 : 0] key3_reg;
reg key3_we;
reg [31 : 0] key4_reg;
reg key4_we;
reg [31 : 0] key5_reg;
reg key5_we;
reg [31 : 0] key6_reg;
reg key6_we;
reg [31 : 0] key7_reg;
reg key7_we;
reg [31 : 0] iv0_reg;
reg iv0_we;
reg [31 : 0] iv1_reg;
reg iv1_we;
reg [31 : 0] data_in0_reg;
reg data_in0_we;
reg [31 : 0] data_in1_reg;
reg data_in1_we;
reg [31 : 0] data_in2_reg;
reg data_in2_we;
reg [31 : 0] data_in3_reg;
reg data_in3_we;
reg [31 : 0] data_in4_reg;
reg data_in4_we;
reg [31 : 0] data_in5_reg;
reg data_in5_we;
reg [31 : 0] data_in6_reg;
reg data_in6_we;
reg [31 : 0] data_in7_reg;
reg data_in7_we;
reg [31 : 0] data_in8_reg;
reg data_in8_we;
reg [31 : 0] data_in9_reg;
reg data_in9_we;
reg [31 : 0] data_in10_reg;
reg data_in10_we;
reg [31 : 0] data_in11_reg;
reg data_in11_we;
reg [31 : 0] data_in12_reg;
reg data_in12_we;
reg [31 : 0] data_in13_reg;
reg data_in13_we;
reg [31 : 0] data_in14_reg;
reg data_in14_we;
reg [31 : 0] data_in15_reg;
reg data_in15_we;
reg [31 : 0] data_out0_reg;
reg [31 : 0] data_out0_new;
reg [31 : 0] data_out1_reg;
reg [31 : 0] data_out1_new;
reg [31 : 0] data_out2_reg;
reg [31 : 0] data_out2_new;
reg [31 : 0] data_out3_reg;
reg [31 : 0] data_out3_new;
reg [31 : 0] data_out4_reg;
reg [31 : 0] data_out4_new;
reg [31 : 0] data_out5_reg;
reg [31 : 0] data_out5_new;
reg [31 : 0] data_out6_reg;
reg [31 : 0] data_out6_new;
reg [31 : 0] data_out7_reg;
reg [31 : 0] data_out7_new;
reg [31 : 0] data_out8_reg;
reg [31 : 0] data_out8_new;
reg [31 : 0] data_out9_reg;
reg [31 : 0] data_out9_new;
reg [31 : 0] data_out10_reg;
reg [31 : 0] data_out10_new;
reg [31 : 0] data_out11_reg;
reg [31 : 0] data_out11_new;
reg [31 : 0] data_out12_reg;
reg [31 : 0] data_out12_new;
reg [31 : 0] data_out13_reg;
reg [31 : 0] data_out13_new;
reg [31 : 0] data_out14_reg;
reg [31 : 0] data_out14_new;
reg [31 : 0] data_out15_reg;
reg [31 : 0] data_out15_new;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
wire core_init;
wire core_next;
wire [255 : 0] core_key;
wire core_keylen;
wire [4 : 0] core_rounds;
wire [63 : 0] core_iv;
wire core_ready;
wire [511 : 0] core_data_in;
wire [511 : 0] core_data_out;
wire core_data_out_valid;
reg [31 : 0] tmp_read_data;
reg tmp_error;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign core_init = init_reg;
assign core_next = next_reg;
assign core_keylen = keylen_reg;
assign core_rounds = rounds_reg;
assign core_key = {key0_reg, key1_reg, key2_reg, key3_reg,
key4_reg, key5_reg, key6_reg, key7_reg};
assign core_iv = {iv0_reg, iv1_reg};
assign core_data_in = {data_in0_reg, data_in1_reg, data_in2_reg, data_in3_reg,
data_in4_reg, data_in5_reg, data_in6_reg, data_in7_reg,
data_in8_reg, data_in9_reg, data_in10_reg, data_in11_reg,
data_in12_reg, data_in13_reg, data_in14_reg, data_in15_reg};
assign read_data = tmp_read_data;
assign error = tmp_error;
//----------------------------------------------------------------
// core instantiation.
//----------------------------------------------------------------
salsa20_core core (
.clk(clk),
.reset_n(reset_n),
.init(core_init),
.next(core_next),
.key(core_key),
.keylen(core_keylen),
.iv(core_iv),
.rounds(core_rounds),
.data_in(core_data_in),
.ready(core_ready),
.data_out(core_data_out),
.data_out_valid(core_data_out_valid)
);
//----------------------------------------------------------------
// reg_update
// Update functionality for all registers in the core.
// All registers are positive edge triggered with synchronous
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk)
begin
if (!reset_n)
begin
init_reg <= 0;
next_reg <= 0;
ready_reg <= 0;
keylen_reg <= 0;
rounds_reg <= 5'b00000;
data_out_valid_reg <= 0;
key0_reg <= 32'h00000000;
key1_reg <= 32'h00000000;
key2_reg <= 32'h00000000;
key3_reg <= 32'h00000000;
key4_reg <= 32'h00000000;
key5_reg <= 32'h00000000;
key6_reg <= 32'h00000000;
key7_reg <= 32'h00000000;
iv0_reg <= 32'h00000000;
iv1_reg <= 32'h00000000;
data_in0_reg <= 32'h00000000;
data_in1_reg <= 32'h00000000;
data_in2_reg <= 32'h00000000;
data_in3_reg <= 32'h00000000;
data_in4_reg <= 32'h00000000;
data_in5_reg <= 32'h00000000;
data_in6_reg <= 32'h00000000;
data_in7_reg <= 32'h00000000;
data_in8_reg <= 32'h00000000;
data_in9_reg <= 32'h00000000;
data_in10_reg <= 32'h00000000;
data_in11_reg <= 32'h00000000;
data_in12_reg <= 32'h00000000;
data_in13_reg <= 32'h00000000;
data_in14_reg <= 32'h00000000;
data_in15_reg <= 32'h00000000;
data_out0_reg <= 32'h00000000;
data_out1_reg <= 32'h00000000;
data_out2_reg <= 32'h00000000;
data_out3_reg <= 32'h00000000;
data_out4_reg <= 32'h00000000;
data_out5_reg <= 32'h00000000;
data_out6_reg <= 32'h00000000;
data_out7_reg <= 32'h00000000;
data_out8_reg <= 32'h00000000;
data_out9_reg <= 32'h00000000;
data_out10_reg <= 32'h00000000;
data_out11_reg <= 32'h00000000;
data_out12_reg <= 32'h00000000;
data_out13_reg <= 32'h00000000;
data_out14_reg <= 32'h00000000;
data_out15_reg <= 32'h00000000;
end
else
begin
ready_reg <= core_ready;
data_out_valid_reg <= core_data_out_valid;
if (ctrl_we)
begin
init_reg <= write_data[CTRL_INIT_BIT];
next_reg <= write_data[CTRL_NEXT_BIT];
end
if (keylen_we)
begin
keylen_reg <= write_data[KEYLEN_BIT];
end
if (rounds_we)
begin
rounds_reg <= write_data[ROUNDS_HIGH_BIT : ROUNDS_LOW_BIT];
end
if (key0_we)
begin
key0_reg <= write_data;
end
if (key1_we)
begin
key1_reg <= write_data;
end
if (key2_we)
begin
key2_reg <= write_data;
end
if (key3_we)
begin
key3_reg <= write_data;
end
if (key4_we)
begin
key4_reg <= write_data;
end
if (key5_we)
begin
key5_reg <= write_data;
end
if (key6_we)
begin
key6_reg <= write_data;
end
if (key7_we)
begin
key7_reg <= write_data;
end
if (iv0_we)
begin
iv0_reg <= write_data;
end
if (iv1_we)
begin
iv1_reg <= write_data;
end
if (data_in0_we)
begin
data_in0_reg <= write_data;
end
if (data_in1_we)
begin
data_in1_reg <= write_data;
end
if (data_in2_we)
begin
data_in2_reg <= write_data;
end
if (data_in3_we)
begin
data_in3_reg <= write_data;
end
if (data_in4_we)
begin
data_in4_reg <= write_data;
end
if (data_in5_we)
begin
data_in5_reg <= write_data;
end
if (data_in6_we)
begin
data_in6_reg <= write_data;
end
if (data_in7_we)
begin
data_in7_reg <= write_data;
end
if (data_in8_we)
begin
data_in8_reg <= write_data;
end
if (data_in9_we)
begin
data_in9_reg <= write_data;
end
if (data_in10_we)
begin
data_in10_reg <= write_data;
end
if (data_in11_we)
begin
data_in11_reg <= write_data;
end
if (data_in12_we)
begin
data_in12_reg <= write_data;
end
if (data_in13_we)
begin
data_in13_reg <= write_data;
end
if (data_in14_we)
begin
data_in14_reg <= write_data;
end
if (data_in15_we)
begin
data_in15_reg <= write_data;
end
if (core_data_out_valid)
begin
data_out0_reg <= core_data_out[511 : 480];
data_out1_reg <= core_data_out[479 : 448];
data_out2_reg <= core_data_out[447 : 416];
data_out3_reg <= core_data_out[415 : 384];
data_out4_reg <= core_data_out[383 : 352];
data_out5_reg <= core_data_out[351 : 320];
data_out6_reg <= core_data_out[319 : 288];
data_out7_reg <= core_data_out[287 : 256];
data_out8_reg <= core_data_out[255 : 224];
data_out9_reg <= core_data_out[223 : 192];
data_out10_reg <= core_data_out[191 : 160];
data_out11_reg <= core_data_out[159 : 128];
data_out12_reg <= core_data_out[127 : 96];
data_out13_reg <= core_data_out[95 : 64];
data_out14_reg <= core_data_out[63 : 32];
data_out15_reg <= core_data_out[31 : 0];
end
end
end // reg_update
//----------------------------------------------------------------
// Address decoder logic.
//----------------------------------------------------------------
always @*
begin : addr_decoder
ctrl_we = 0;
keylen_we = 0;
rounds_we = 0;
key0_we = 0;
key1_we = 0;
key2_we = 0;
key3_we = 0;
key4_we = 0;
key5_we = 0;
key6_we = 0;
key7_we = 0;
iv0_we = 0;
iv1_we = 0;
data_in0_we = 0;
data_in1_we = 0;
data_in2_we = 0;
data_in3_we = 0;
data_in4_we = 0;
data_in5_we = 0;
data_in6_we = 0;
data_in7_we = 0;
data_in8_we = 0;
data_in9_we = 0;
data_in10_we = 0;
data_in11_we = 0;
data_in12_we = 0;
data_in13_we = 0;
data_in14_we = 0;
data_in15_we = 0;
tmp_read_data = 32'h00000000;
tmp_error = 0;
if (cs)
begin
if (we)
begin
case (address)
ADDR_CTRL:
begin
ctrl_we = 1;
end
ADDR_KEYLEN:
begin
keylen_we = 1;
end
ADDR_ROUNDS:
begin
rounds_we = 1;
end
ADDR_KEY0:
begin
key0_we = 1;
end
ADDR_KEY1:
begin
key1_we = 1;
end
ADDR_KEY2:
begin
key2_we = 1;
end
ADDR_KEY3:
begin
key3_we = 1;
end
ADDR_KEY4:
begin
key4_we = 1;
end
ADDR_KEY5:
begin
key5_we = 1;
end
ADDR_KEY6:
begin
key6_we = 1;
end
ADDR_KEY7:
begin
key7_we = 1;
end
ADDR_IV0:
begin
iv0_we = 1;
end
ADDR_IV1:
begin
iv1_we = 1;
end
ADDR_DATA_IN0:
begin
data_in0_we = 1;
end
ADDR_DATA_IN1:
begin
data_in1_we = 1;
end
ADDR_DATA_IN2:
begin
data_in2_we = 1;
end
ADDR_DATA_IN3:
begin
data_in3_we = 1;
end
ADDR_DATA_IN4:
begin
data_in4_we = 1;
end
ADDR_DATA_IN5:
begin
data_in5_we = 1;
end
ADDR_DATA_IN6:
begin
data_in6_we = 1;
end
ADDR_DATA_IN7:
begin
data_in7_we = 1;
end
ADDR_DATA_IN8:
begin
data_in8_we = 1;
end
ADDR_DATA_IN9:
begin
data_in9_we = 1;
end
ADDR_DATA_IN10:
begin
data_in10_we = 1;
end
ADDR_DATA_IN11:
begin
data_in11_we = 1;
end
ADDR_DATA_IN12:
begin
data_in12_we = 1;
end
ADDR_DATA_IN13:
begin
data_in13_we = 1;
end
ADDR_DATA_IN14:
begin
data_in14_we = 1;
end
ADDR_DATA_IN15:
begin
data_in15_we = 1;
end
default:
begin
tmp_error = 1;
end
endcase // case (address)
end // if (we)
else
begin
case (address)
ADDR_CTRL:
begin
tmp_read_data = {28'h0000000, 2'b00, next_reg, init_reg};
end
ADDR_STATUS:
begin
tmp_read_data = {28'h0000000, 2'b00,
{data_out_valid_reg, ready_reg}};
end
ADDR_KEYLEN:
begin
tmp_read_data = {28'h0000000, 3'b000, keylen_reg};
end
ADDR_ROUNDS:
begin
tmp_read_data = {24'h000000, 3'b000, rounds_reg};
end
ADDR_KEY0:
begin
tmp_read_data = key0_reg;
end
ADDR_KEY1:
begin
tmp_read_data = key1_reg;
end
ADDR_KEY2:
begin
tmp_read_data = key2_reg;
end
ADDR_KEY3:
begin
tmp_read_data = key3_reg;
end
ADDR_KEY4:
begin
tmp_read_data = key4_reg;
end
ADDR_KEY5:
begin
tmp_read_data = key5_reg;
end
ADDR_KEY6:
begin
tmp_read_data = key6_reg;
end
ADDR_KEY7:
begin
tmp_read_data = key7_reg;
end
ADDR_IV0:
begin
tmp_read_data = iv0_reg;
end
ADDR_IV1:
begin
tmp_read_data = iv1_reg;
end
ADDR_DATA_OUT0:
begin
tmp_read_data = data_out0_reg;
end
ADDR_DATA_OUT1:
begin
tmp_read_data = data_out1_reg;
end
ADDR_DATA_OUT2:
begin
tmp_read_data = data_out2_reg;
end
ADDR_DATA_OUT3:
begin
tmp_read_data = data_out3_reg;
end
ADDR_DATA_OUT4:
begin
tmp_read_data = data_out4_reg;
end
ADDR_DATA_OUT5:
begin
tmp_read_data = data_out5_reg;
end
ADDR_DATA_OUT6:
begin
tmp_read_data = data_out6_reg;
end
ADDR_DATA_OUT7:
begin
tmp_read_data = data_out7_reg;
end
ADDR_DATA_OUT8:
begin
tmp_read_data = data_out8_reg;
end
ADDR_DATA_OUT9:
begin
tmp_read_data = data_out9_reg;
end
ADDR_DATA_OUT10:
begin
tmp_read_data = data_out10_reg;
end
ADDR_DATA_OUT11:
begin
tmp_read_data = data_out11_reg;
end
ADDR_DATA_OUT12:
begin
tmp_read_data = data_out12_reg;
end
ADDR_DATA_OUT13:
begin
tmp_read_data = data_out13_reg;
end
ADDR_DATA_OUT14:
begin
tmp_read_data = data_out14_reg;
end
ADDR_DATA_OUT15:
begin
tmp_read_data = data_out15_reg;
end
default:
begin
tmp_error = 1;
end
endcase // case (address)
end
end
end // addr_decoder
endmodule // salsa20
//======================================================================
// EOF salsa20.v
//======================================================================