From 9e7c659fb59877c00f8f3761e57b1e8918ddec0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Wed, 3 Sep 2014 15:49:00 +0200 Subject: Adding RTL code for the ChaCha stream cipher. --- src/rtl/chacha.v | 896 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 896 insertions(+) create mode 100644 src/rtl/chacha.v (limited to 'src/rtl/chacha.v') diff --git a/src/rtl/chacha.v b/src/rtl/chacha.v new file mode 100644 index 0000000..c83710d --- /dev/null +++ b/src/rtl/chacha.v @@ -0,0 +1,896 @@ +//====================================================================== +// +// chacha.v +// -------- +// Top level wrapper for the ChaCha stream, cipher core providing +// a simple memory like interface with 32 bit data access. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2011, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module chacha( + // 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; + + parameter DEFAULT_CTR_INIT = 64'h0000000000000000; + + + //---------------------------------------------------------------- + // 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. + //---------------------------------------------------------------- + chacha_core core ( + .clk(clk), + .reset_n(reset_n), + + .init(core_init), + .next(core_next), + + .key(core_key), + .keylen(core_keylen), + .iv(core_iv), + .ctr(DEFAULT_CTR_INIT), + .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 // chacha + +//====================================================================== +// EOF chacha.v +//====================================================================== -- cgit v1.2.3