aboutsummaryrefslogblamecommitdiff
path: root/src/rtl/modexp.v
blob: e3554c481641eba64c1926cd0dcb9b25a349981c (plain) (tree)
1
2
3
4
5
6
7



                                                                        


                                                                 





                                              
                                              
                                              



                                                            



                                                             
                                                               

  
                                                
                                   
                       
  




                                                                           
  


                                                                         
  


                                                                           
  










                                                                           
  









                                                                        
                                           







                                                                    
 







                                                                   


                                           
 


                                           
 

                                           
 




                                           
 

                                           
 

                                           
 

                                           
 

                                           
 

                                                         
 


                                                            




                                                                    


                                   
 


                                  
 
                         
                         
 
 


                                                                    



                                           
 


                                    
                                          



                                    
                                          


                                   





                                         

 








                                                                    


































                                                                    












                                                                    
                                      

                                                   


             
                                 

                                 
                 
                                                       
               

                                
                 
                                                      
               










                                                                    


                                  
 














                                  
                                          
 

             























































































































                                                                        
                      
                     
 




                                                                        
//======================================================================
//
// modexp.v
// --------
// Top level wrapper for the modula exponentiation core. The core
// is used to implement public key algorithms such as RSA,
// DH, ElGamal etc.
//
// The core calculates the following function:
//
//   C = M ** e mod N
//
//   M is a message with a length of n bits
//   e is the exponent with a length of m bits
//   N is the modulus  with a length of n bits
//
//   n can be 32 and up to and including 8192 bits in steps
//   of 32 bits.
//   m can be one and up to and including 8192 bits in steps
//   of 32 bits.
//
// The core has a 32-bit memory like interface, but provides
// status signals to inform the system that a given operation
// has is done. Additionally, any errors will also be asserted.
//
//
// Author: Joachim Strombergson, Peter Magnusson
// Copyright (c) 2015, 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 modexp(
              input wire           clk,
              input wire           reset_n,

              input wire           cs,
              input wire           we,

              input wire  [ 7 : 0] address,
              input wire  [31 : 0] write_data,
              output wire [31 : 0] read_data
             );


  //----------------------------------------------------------------
  // Internal constant and parameter definitions.
  //----------------------------------------------------------------

  // The operand width is the internal operand width in bits.
  // The address width is the size of the address space used. This
  // value must be balances with OPERAND_WIDTH to allow a total
  // of 8192 bits of data. OPERAND_WIDTH * (ADDRESS_WIDTH ** 2)
  // is the formula. Note that the API data with is always 32 bits.
  localparam OPERAND_WIDTH         = 32;
  localparam ADDRESS_WIDTH         = 8;

  localparam ADDR_NAME0            = 8'h00;
  localparam ADDR_NAME1            = 8'h01;
  localparam ADDR_VERSION          = 8'h02;

  localparam ADDR_CTRL             = 8'h08;
  localparam CTRL_INIT_BIT         = 0;
  localparam CTRL_NEXT_BIT         = 1;

  localparam ADDR_STATUS           = 8'h09;
  localparam STATUS_READY_BIT      = 0;

  localparam ADDR_CYCLES_HIGH      = 8'h10;
  localparam ADDR_CYCLES_LOW       = 8'h11;

  localparam ADDR_MODULUS_LENGTH   = 8'h20;
  localparam ADDR_EXPONENT_LENGTH  = 8'h21;

  localparam ADDR_MODULUS_PTR_RST  = 8'h30;
  localparam ADDR_MODULUS_DATA     = 8'h31;

  localparam ADDR_EXPONENT_PTR_RST = 8'h40;
  localparam ADDR_EXPONENT_DATA    = 8'h41;

  localparam ADDR_MESSAGE_PTR_RST  = 8'h50;
  localparam ADDR_MESSAGE_DATA     = 8'h51;

  localparam ADDR_RESULT_PTR_RST   = 8'h60;
  localparam ADDR_RESULT_DATA      = 8'h61;

  localparam DEFAULT_MODLENGTH     = 8'h80; // 2048 bits.
  localparam DEFAULT_EXPLENGTH     = 8'h80;

  localparam CORE_NAME0            = 32'h6d6f6465; // "mode"
  localparam CORE_NAME1            = 32'h78702020; // "xp  "
  localparam CORE_VERSION          = 32'h302e3532; // "0.52"


  //----------------------------------------------------------------
  // Registers including update variables and write enable.
  //----------------------------------------------------------------
  reg [07 : 0] exponent_length_reg;
  reg [07 : 0] exponent_length_new;
  reg          exponent_length_we;

  reg [07 : 0] modulus_length_reg;
  reg [07 : 0] modulus_length_new;
  reg          modulus_length_we;

  reg          start_reg;
  reg          start_new;


  //----------------------------------------------------------------
  // Wires.
  //----------------------------------------------------------------
  reg           exponent_mem_api_rst;
  reg           exponent_mem_api_cs;
  reg           exponent_mem_api_wr;
  wire [31 : 0] exponent_mem_api_read_data;

  reg           modulus_mem_api_rst;
  reg           modulus_mem_api_cs;
  reg           modulus_mem_api_wr;
  wire [31 : 0] modulus_mem_api_read_data;

  reg           message_mem_api_rst;
  reg           message_mem_api_cs;
  reg           message_mem_api_wr;
  wire [31 : 0] message_mem_api_read_data;

  reg           result_mem_api_rst;
  reg           result_mem_api_cs;
  wire [31 : 0] result_mem_api_read_data;

  wire          ready;
  wire [63 : 0] cycles;

  reg [31 : 0]  tmp_read_data;


  //----------------------------------------------------------------
  // Concurrent connectivity for ports etc.
  //----------------------------------------------------------------
  assign read_data = tmp_read_data;


  //----------------------------------------------------------------
  // core instantiations.
  //----------------------------------------------------------------
  modexp_core #(.OPW(OPERAND_WIDTH), .ADW(ADDRESS_WIDTH))
  core_inst(
            .clk(clk),
            .reset_n(reset_n),

            .start(start_reg),
            .ready(ready),

            .exponent_length(exponent_length_reg),
            .modulus_length(modulus_length_reg),

            .cycles(cycles),

            .exponent_mem_api_cs(exponent_mem_api_cs),
            .exponent_mem_api_wr(exponent_mem_api_wr),
            .exponent_mem_api_rst(exponent_mem_api_rst),
            .exponent_mem_api_write_data(write_data),
            .exponent_mem_api_read_data(exponent_mem_api_read_data),

            .modulus_mem_api_cs(modulus_mem_api_cs),
            .modulus_mem_api_wr(modulus_mem_api_wr),
            .modulus_mem_api_rst(modulus_mem_api_rst),
            .modulus_mem_api_write_data(write_data),
            .modulus_mem_api_read_data(modulus_mem_api_read_data),

            .message_mem_api_cs(message_mem_api_cs),
            .message_mem_api_wr(message_mem_api_wr),
            .message_mem_api_rst(message_mem_api_rst),
            .message_mem_api_write_data(write_data),
            .message_mem_api_read_data(message_mem_api_read_data),

            .result_mem_api_cs(result_mem_api_cs),
            .result_mem_api_rst(result_mem_api_rst),
            .result_mem_api_read_data(result_mem_api_read_data)
           );


  //----------------------------------------------------------------
  // reg_update
  //
  // Update functionality for all registers in the core.
  // All registers are positive edge triggered with asynchronous
  // active low reset. All registers have write enable.
  //----------------------------------------------------------------
  always @ (posedge clk or negedge reset_n)
    begin
      if (!reset_n)
        begin
          start_reg           <= 1'b0;
          exponent_length_reg <= DEFAULT_EXPLENGTH;
          modulus_length_reg  <= DEFAULT_MODLENGTH;
        end
      else
        begin
          start_reg <= start_new;

          if (exponent_length_we)
            begin
              exponent_length_reg <= write_data[7 : 0];
            end

          if (modulus_length_we)
            begin
              modulus_length_reg <= write_data[7 : 0];
            end
        end
    end // reg_update


  //----------------------------------------------------------------
  // api
  //
  // The interface command decoding logic.
  //----------------------------------------------------------------
  always @*
    begin : api
      modulus_length_we    = 1'b0;
      exponent_length_we   = 1'b0;
      start_new            = 1'b0;

      modulus_mem_api_rst  = 1'b0;
      modulus_mem_api_cs   = 1'b0;
      modulus_mem_api_wr   = 1'b0;

      exponent_mem_api_rst = 1'b0;
      exponent_mem_api_cs  = 1'b0;
      exponent_mem_api_wr  = 1'b0;

      message_mem_api_rst  = 1'b0;
      message_mem_api_cs   = 1'b0;
      message_mem_api_wr   = 1'b0;

      result_mem_api_rst   = 1'b0;
      result_mem_api_cs    = 1'b0;

      tmp_read_data        = 32'h00000000;

      if (cs)
        begin
           if (we)
             begin
                case (address)
                  ADDR_CTRL:
                    begin
                       start_new = write_data[0];
                    end

                  ADDR_MODULUS_LENGTH:
                    begin
                       modulus_length_we = 1'b1;
                    end

                  ADDR_EXPONENT_LENGTH:
                    begin
                       exponent_length_we = 1'b1;
                    end

                  ADDR_MODULUS_PTR_RST:
                    begin
                       modulus_mem_api_rst = 1'b1;
                    end

                  ADDR_MODULUS_DATA:
                    begin
                       modulus_mem_api_cs = 1'b1;
                       modulus_mem_api_wr = 1'b1;
                    end

                  ADDR_EXPONENT_PTR_RST:
                    begin
                       exponent_mem_api_rst = 1'b1;
                    end

                  ADDR_EXPONENT_DATA:
                    begin
                       exponent_mem_api_cs = 1'b1;
                       exponent_mem_api_wr = 1'b1;
                    end

                  ADDR_MESSAGE_PTR_RST:
                    begin
                       message_mem_api_rst = 1'b1;
                    end

                  ADDR_MESSAGE_DATA:
                    begin
                       message_mem_api_cs = 1'b1;
                       message_mem_api_wr = 1'b1;
                    end

                  ADDR_RESULT_PTR_RST:
                    begin
                       result_mem_api_rst = 1'b1;
                    end

                  default:
                    begin
                    end
                endcase // case (address[7 : 0])
             end // if (we)
           else
             begin
                case (address)
                  ADDR_NAME0:
                    tmp_read_data = CORE_NAME0;

                  ADDR_NAME1:
                    tmp_read_data = CORE_NAME1;

                  ADDR_VERSION:
                    tmp_read_data = CORE_VERSION;

                  ADDR_CTRL:
                    tmp_read_data = {31'h00000000, start_reg};

                  ADDR_STATUS:
                    tmp_read_data = {31'h00000000, ready};

                  ADDR_CYCLES_HIGH:
                    tmp_read_data = cycles[63 : 32];

                  ADDR_CYCLES_LOW:
                    tmp_read_data = cycles[31 : 0];

                  ADDR_MODULUS_LENGTH:
                    tmp_read_data = {24'h000000, modulus_length_reg};

                  ADDR_EXPONENT_LENGTH:
                    tmp_read_data = {24'h000000, exponent_length_reg};

                  ADDR_MODULUS_DATA:
                    begin
                       modulus_mem_api_cs = 1'b1;
                       tmp_read_data      = modulus_mem_api_read_data;
                    end

                  ADDR_EXPONENT_DATA:
                    begin
                       exponent_mem_api_cs = 1'b1;
                       tmp_read_data       = exponent_mem_api_read_data;
                    end

                  ADDR_MESSAGE_DATA:
                    begin
                       message_mem_api_cs = 1'b1;
                       tmp_read_data      = message_mem_api_read_data;
                    end

                  ADDR_RESULT_DATA:
                    begin
                       result_mem_api_cs = 1'b1;
                       tmp_read_data     = result_mem_api_read_data;
                    end

                  default:
                    begin
                    end
                endcase // case (address)
             end // else: !if(we)
        end // if (cs)
    end // block: api

endmodule // modexp

//======================================================================
// EOF modexp.v
//======================================================================