aboutsummaryrefslogblamecommitdiff
path: root/src/rtl/modexp.v
blob: 65f4058a50e3ec3dae57180ccfcf1c83ceefb0d4 (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, Assured 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 modexp(
              input wire           clk,
              input wire           reset_n,

              input wire           cs,
              input wire           we,

              input wire  [11 : 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 GENERAL_PREFIX        = 4'h0;
  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
          case (address[11 : 8])
            GENERAL_PREFIX:
              begin
                if (we)
                  begin
                    case (address[7 : 0])
                      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
                else
                  begin
                    case (address[7 : 0])
                      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[7 : 0])
                  end
              end

            default:
              begin

              end
          endcase // case (address[11 : 8])
        end // if (cs)
    end // api

endmodule // modexp

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