../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: