../src/lowrisc_prim_all_0.1/rtl/prim_gate_gen.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: //
   5: // Simple parameterizable gate generator. Used to fill up the netlist
   6: // with gates that cannot be optimized away.
   7: //
   8: // The module leverages 4bit SBoxes from the PRINCE cipher, and interleaves
   9: // them with registers, resulting in a split of around 50/50 between logic and
  10: // sequential cells.
  11: //
  12: // This generator has been tested with 32bit wide data, and produces
  13: // the following results:
  14: //
  15: // if valid_i constantly set to 1'b1:
  16: // -------------+-----------+----------
  17: // requested GE | actual GE | GE error
  18: // -------------+-----------+----------
  19: // 500          |   679     |   179
  20: // 1000         |   1018    |   18
  21: // 1500         |   1696    |   196
  22: // 2500         |   2714    |   214
  23: // 5000         |   5210    |   210
  24: // 7500         |   7456    |   -44
  25: // 10000        |   10015   |   15
  26: // 15000        |   15191   |   191
  27: // 25000        |   25228   |   228
  28: // 50000        |   50485   |   485
  29: //
  30: // otherwise, with clock gating enabled:
  31: // -------------+-----------+----------
  32: // requested GE | actual GE | GE error
  33: // -------------+-----------+----------
  34: // 500          |   696     |   196
  35: // 1000         |   1043    |   43
  36: // 1500         |   1737    |   237
  37: // 2500         |   2779    |   279
  38: // 5000         |   5340    |   340
  39: // 7500         |   7634    |   134
  40: // 10000        |   10284   |   284
  41: // 15000        |   15585   |   585
  42: // 25000        |   25855   |   855
  43: // 50000        |   51732   |   1732
  44: //
  45: // Note that the generator is not very accurate for smaller gate counts due
  46: // to the generate loop granularity. Hence, do not use for fever than 500 GE.
  47: 
  48: 
  49: module prim_gate_gen #(
  50:   parameter int DataWidth = 32,
  51:   parameter int NumGates = 1000
  52: ) (
  53:   input                        clk_i,
  54:   input                        rst_ni,
  55: 
  56:   input                        valid_i,
  57:   input        [DataWidth-1:0] data_i,
  58:   output logic [DataWidth-1:0] data_o,
  59:   output                       valid_o
  60: );
  61: 
  62:   /////////////////////////////////////
  63:   // Local parameters and assertions //
  64:   /////////////////////////////////////
  65: 
  66:   // technology specific tuning, do not modify.
  67:   // an inner round is comprised of a 2bit rotation, followed by a 4bit SBox Layer.
  68:   localparam int NumInnerRounds = 2;
  69:   localparam int GatesPerRound  = DataWidth * 10;
  70:   // an outer round consists of NumInnerRounds, followed by a register.
  71:   localparam int NumOuterRounds = (NumGates + GatesPerRound / 2) / GatesPerRound;
  72: 
  73:   // do not use for fewer than 500 GE
  74:   `ASSERT(MinimumNumGates_A, NumGates >= 500)
  75:   `ASSERT(DataMustBeMultipleOfFour_A, DataWidth % 4 == 0)
  76: 
  77:   /////////////////////
  78:   // Generator Loops //
  79:   /////////////////////
  80: 
  81:   logic [NumOuterRounds-1:0][DataWidth-1:0] regs_d, regs_q;
  82:   logic [NumOuterRounds-1:0] valid_d, valid_q;
  83: 
  84:   for (genvar k = 0; k < NumOuterRounds; k++) begin : gen_outer_round
  85: 
  86:     logic [NumInnerRounds:0][DataWidth-1:0] inner_data;
  87: 
  88:     if (k==0) begin : gen_first
  89:       assign inner_data[0] = data_i;
  90:       assign valid_d[0]    = valid_i;
  91:     end else begin : gen_others
  92:       assign inner_data[0] = regs_q[k-1];
  93:       assign valid_d[k]    = valid_q[k-1];
  94:     end
  95: 
  96:     for (genvar l = 0; l < NumInnerRounds; l++) begin : gen_inner
  97:       // 2bit rotation + sbox layer
  98:       assign inner_data[l+1] = prim_cipher_pkg::sbox4_32bit({inner_data[l][1:0],
  99:                                                              inner_data[l][DataWidth-1:2]},
 100:                                                              prim_cipher_pkg::PRINCE_SBOX4);
 101:     end
 102: 
 103:     assign regs_d[k] = inner_data[NumInnerRounds];
 104:   end
 105: 
 106:   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
 107:     if (!rst_ni) begin
 108:       regs_q <= '0;
 109:       valid_q <= '0;
 110:     end else begin
 111:       valid_q <= valid_d;
 112:       for (int k = 0; k < NumOuterRounds; k++) begin
 113:         if (valid_d[k]) begin
 114:           regs_q[k] <= regs_d[k];
 115:         end
 116:       end
 117:     end
 118:   end
 119: 
 120:   assign data_o = regs_q[NumOuterRounds-1];
 121:   assign valid_o = valid_q[NumOuterRounds-1];
 122: 
 123: endmodule : prim_gate_gen
 124: