Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 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 | // |
Michael Schaffner | bda1d16 | 2020-07-08 14:29:29 -0700 | [diff] [blame] | 5 | // Simple parameterizable gate generator. Used to fill up the netlist with gates that cannot be |
| 6 | // optimized away. |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 7 | // |
Michael Schaffner | bda1d16 | 2020-07-08 14:29:29 -0700 | [diff] [blame] | 8 | // The module leverages 4bit SBoxes from the PRINCE cipher, and interleaves them with registers, |
| 9 | // resulting in a split of around 50/50 between logic and sequential cells. |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 10 | // |
Michael Schaffner | bda1d16 | 2020-07-08 14:29:29 -0700 | [diff] [blame] | 11 | // This generator has been tested with 32bit wide data, and produces the following results: |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 12 | // |
| 13 | // -------------+-----------+---------- |
| 14 | // requested GE | actual GE | GE error |
| 15 | // -------------+-----------+---------- |
Michael Schaffner | bda1d16 | 2020-07-08 14:29:29 -0700 | [diff] [blame] | 16 | // 500 | 483 | -17 |
| 17 | // 1000 | 964 | -36 |
| 18 | // 1500 | 1447 | -53 |
| 19 | // 2500 | 2892 | 392 |
| 20 | // 5000 | 5299 | 299 |
| 21 | // 7500 | 8030 | 530 |
| 22 | // 10000 | 10393 | 393 |
| 23 | // 15000 | 15575 | 575 |
| 24 | // 25000 | 26422 | 1422 |
| 25 | // 50000 | 52859 | 2859 |
| 26 | // 100000 | 105270 | 5270 |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 27 | // |
Michael Schaffner | bda1d16 | 2020-07-08 14:29:29 -0700 | [diff] [blame] | 28 | // Note that the generator is not very accurate for smaller gate counts due to the generate loop |
| 29 | // granularity. Hence, do not use for fever than 500 GE. |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 30 | // |
Michael Schaffner | bda1d16 | 2020-07-08 14:29:29 -0700 | [diff] [blame] | 31 | // If valid_i constantly set to 1'b1, the gate generator produces around 2.5% smaller designs for |
| 32 | // the configurations listed in the table above. |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 33 | |
Dawid Zimonczyk | 684c1bf | 2020-07-07 07:49:51 +0200 | [diff] [blame] | 34 | `include "prim_assert.sv" |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 35 | module prim_gate_gen #( |
| 36 | parameter int DataWidth = 32, |
| 37 | parameter int NumGates = 1000 |
| 38 | ) ( |
| 39 | input clk_i, |
| 40 | input rst_ni, |
| 41 | |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 42 | input valid_i, |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 43 | input [DataWidth-1:0] data_i, |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 44 | output logic [DataWidth-1:0] data_o, |
| 45 | output valid_o |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 46 | ); |
| 47 | |
| 48 | ///////////////////////////////////// |
| 49 | // Local parameters and assertions // |
| 50 | ///////////////////////////////////// |
| 51 | |
| 52 | // technology specific tuning, do not modify. |
| 53 | // an inner round is comprised of a 2bit rotation, followed by a 4bit SBox Layer. |
| 54 | localparam int NumInnerRounds = 2; |
Michael Schaffner | bda1d16 | 2020-07-08 14:29:29 -0700 | [diff] [blame] | 55 | localparam int GatesPerRound = DataWidth * 14; |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 56 | // an outer round consists of NumInnerRounds, followed by a register. |
| 57 | localparam int NumOuterRounds = (NumGates + GatesPerRound / 2) / GatesPerRound; |
| 58 | |
| 59 | // do not use for fewer than 500 GE |
| 60 | `ASSERT(MinimumNumGates_A, NumGates >= 500) |
| 61 | `ASSERT(DataMustBeMultipleOfFour_A, DataWidth % 4 == 0) |
| 62 | |
| 63 | ///////////////////// |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 64 | // Generator Loops // |
| 65 | ///////////////////// |
| 66 | |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 67 | logic [NumOuterRounds-1:0][DataWidth-1:0] regs_d, regs_q; |
| 68 | logic [NumOuterRounds-1:0] valid_d, valid_q; |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 69 | |
| 70 | for (genvar k = 0; k < NumOuterRounds; k++) begin : gen_outer_round |
| 71 | |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 72 | logic [NumInnerRounds:0][DataWidth-1:0] inner_data; |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 73 | |
| 74 | if (k==0) begin : gen_first |
| 75 | assign inner_data[0] = data_i; |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 76 | assign valid_d[0] = valid_i; |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 77 | end else begin : gen_others |
| 78 | assign inner_data[0] = regs_q[k-1]; |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 79 | assign valid_d[k] = valid_q[k-1]; |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 80 | end |
| 81 | |
| 82 | for (genvar l = 0; l < NumInnerRounds; l++) begin : gen_inner |
| 83 | // 2bit rotation + sbox layer |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 84 | assign inner_data[l+1] = prim_cipher_pkg::sbox4_32bit({inner_data[l][1:0], |
| 85 | inner_data[l][DataWidth-1:2]}, |
| 86 | prim_cipher_pkg::PRINCE_SBOX4); |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 87 | end |
| 88 | |
| 89 | assign regs_d[k] = inner_data[NumInnerRounds]; |
| 90 | end |
| 91 | |
| 92 | always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs |
| 93 | if (!rst_ni) begin |
| 94 | regs_q <= '0; |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 95 | valid_q <= '0; |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 96 | end else begin |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 97 | valid_q <= valid_d; |
| 98 | for (int k = 0; k < NumOuterRounds; k++) begin |
| 99 | if (valid_d[k]) begin |
| 100 | regs_q[k] <= regs_d[k]; |
| 101 | end |
| 102 | end |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 103 | end |
| 104 | end |
| 105 | |
| 106 | assign data_o = regs_q[NumOuterRounds-1]; |
Michael Schaffner | eb7f3c7 | 2020-04-10 23:38:29 -0700 | [diff] [blame] | 107 | assign valid_o = valid_q[NumOuterRounds-1]; |
Michael Schaffner | 7bc7223 | 2020-04-03 20:13:27 -0700 | [diff] [blame] | 108 | |
| 109 | endmodule : prim_gate_gen |