| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // Simple parameterizable gate generator. Used to fill up the netlist |
| // with gates that cannot be optimized away. |
| // |
| // The module leverages 4bit SBoxes from the PRINCE cipher, and interleaves |
| // them with registers, resulting in a split of around 50/50 between logic and |
| // sequential cells. |
| // |
| // This generator has been tested with 32bit wide data, and produces |
| // the following results: |
| // |
| // if valid_i constantly set to 1'b1: |
| // -------------+-----------+---------- |
| // requested GE | actual GE | GE error |
| // -------------+-----------+---------- |
| // 500 | 679 | 179 |
| // 1000 | 1018 | 18 |
| // 1500 | 1696 | 196 |
| // 2500 | 2714 | 214 |
| // 5000 | 5210 | 210 |
| // 7500 | 7456 | -44 |
| // 10000 | 10015 | 15 |
| // 15000 | 15191 | 191 |
| // 25000 | 25228 | 228 |
| // 50000 | 50485 | 485 |
| // |
| // otherwise, with clock gating enabled: |
| // -------------+-----------+---------- |
| // requested GE | actual GE | GE error |
| // -------------+-----------+---------- |
| // 500 | 696 | 196 |
| // 1000 | 1043 | 43 |
| // 1500 | 1737 | 237 |
| // 2500 | 2779 | 279 |
| // 5000 | 5340 | 340 |
| // 7500 | 7634 | 134 |
| // 10000 | 10284 | 284 |
| // 15000 | 15585 | 585 |
| // 25000 | 25855 | 855 |
| // 50000 | 51732 | 1732 |
| // |
| // Note that the generator is not very accurate for smaller gate counts due |
| // to the generate loop granularity. Hence, do not use for fever than 500 GE. |
| |
| |
| module prim_gate_gen #( |
| parameter int DataWidth = 32, |
| parameter int NumGates = 1000 |
| ) ( |
| input clk_i, |
| input rst_ni, |
| |
| input valid_i, |
| input [DataWidth-1:0] data_i, |
| output logic [DataWidth-1:0] data_o, |
| output valid_o |
| ); |
| |
| ///////////////////////////////////// |
| // Local parameters and assertions // |
| ///////////////////////////////////// |
| |
| // technology specific tuning, do not modify. |
| // an inner round is comprised of a 2bit rotation, followed by a 4bit SBox Layer. |
| localparam int NumInnerRounds = 2; |
| localparam int GatesPerRound = DataWidth * 10; |
| // an outer round consists of NumInnerRounds, followed by a register. |
| localparam int NumOuterRounds = (NumGates + GatesPerRound / 2) / GatesPerRound; |
| |
| // do not use for fewer than 500 GE |
| `ASSERT(MinimumNumGates_A, NumGates >= 500) |
| `ASSERT(DataMustBeMultipleOfFour_A, DataWidth % 4 == 0) |
| |
| ///////////////////// |
| // Generator Loops // |
| ///////////////////// |
| |
| logic [NumOuterRounds-1:0][DataWidth-1:0] regs_d, regs_q; |
| logic [NumOuterRounds-1:0] valid_d, valid_q; |
| |
| for (genvar k = 0; k < NumOuterRounds; k++) begin : gen_outer_round |
| |
| logic [NumInnerRounds:0][DataWidth-1:0] inner_data; |
| |
| if (k==0) begin : gen_first |
| assign inner_data[0] = data_i; |
| assign valid_d[0] = valid_i; |
| end else begin : gen_others |
| assign inner_data[0] = regs_q[k-1]; |
| assign valid_d[k] = valid_q[k-1]; |
| end |
| |
| for (genvar l = 0; l < NumInnerRounds; l++) begin : gen_inner |
| // 2bit rotation + sbox layer |
| assign inner_data[l+1] = prim_cipher_pkg::sbox4_32bit({inner_data[l][1:0], |
| inner_data[l][DataWidth-1:2]}, |
| prim_cipher_pkg::PRINCE_SBOX4); |
| end |
| |
| assign regs_d[k] = inner_data[NumInnerRounds]; |
| end |
| |
| always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs |
| if (!rst_ni) begin |
| regs_q <= '0; |
| valid_q <= '0; |
| end else begin |
| valid_q <= valid_d; |
| for (int k = 0; k < NumOuterRounds; k++) begin |
| if (valid_d[k]) begin |
| regs_q[k] <= regs_d[k]; |
| end |
| end |
| end |
| end |
| |
| assign data_o = regs_q[NumOuterRounds-1]; |
| assign valid_o = valid_q[NumOuterRounds-1]; |
| |
| endmodule : prim_gate_gen |