blob: dac761fd9d364dc26a8d5afdec8b0e1ef057e9da [file] [log] [blame]
Michael Schaffner7bc72232020-04-03 20:13:27 -07001// 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 Schaffnerbda1d162020-07-08 14:29:29 -07005// Simple parameterizable gate generator. Used to fill up the netlist with gates that cannot be
6// optimized away.
Michael Schaffner7bc72232020-04-03 20:13:27 -07007//
Michael Schaffnerbda1d162020-07-08 14:29:29 -07008// 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 Schaffner7bc72232020-04-03 20:13:27 -070010//
Michael Schaffnerbda1d162020-07-08 14:29:29 -070011// This generator has been tested with 32bit wide data, and produces the following results:
Michael Schaffner7bc72232020-04-03 20:13:27 -070012//
13// -------------+-----------+----------
14// requested GE | actual GE | GE error
15// -------------+-----------+----------
Michael Schaffnerbda1d162020-07-08 14:29:29 -070016// 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 Schaffner7bc72232020-04-03 20:13:27 -070027//
Michael Schaffnerbda1d162020-07-08 14:29:29 -070028// 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 Schaffnereb7f3c72020-04-10 23:38:29 -070030//
Michael Schaffnerbda1d162020-07-08 14:29:29 -070031// 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 Schaffnereb7f3c72020-04-10 23:38:29 -070033
Dawid Zimonczyk684c1bf2020-07-07 07:49:51 +020034`include "prim_assert.sv"
Michael Schaffner7bc72232020-04-03 20:13:27 -070035module prim_gate_gen #(
36 parameter int DataWidth = 32,
37 parameter int NumGates = 1000
38) (
39 input clk_i,
40 input rst_ni,
41
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070042 input valid_i,
Michael Schaffner7bc72232020-04-03 20:13:27 -070043 input [DataWidth-1:0] data_i,
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070044 output logic [DataWidth-1:0] data_o,
45 output valid_o
Michael Schaffner7bc72232020-04-03 20:13:27 -070046);
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 Schaffnerbda1d162020-07-08 14:29:29 -070055 localparam int GatesPerRound = DataWidth * 14;
Michael Schaffner7bc72232020-04-03 20:13:27 -070056 // 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 Schaffner7bc72232020-04-03 20:13:27 -070064 // Generator Loops //
65 /////////////////////
66
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070067 logic [NumOuterRounds-1:0][DataWidth-1:0] regs_d, regs_q;
68 logic [NumOuterRounds-1:0] valid_d, valid_q;
Michael Schaffner7bc72232020-04-03 20:13:27 -070069
70 for (genvar k = 0; k < NumOuterRounds; k++) begin : gen_outer_round
71
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070072 logic [NumInnerRounds:0][DataWidth-1:0] inner_data;
Michael Schaffner7bc72232020-04-03 20:13:27 -070073
74 if (k==0) begin : gen_first
75 assign inner_data[0] = data_i;
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070076 assign valid_d[0] = valid_i;
Michael Schaffner7bc72232020-04-03 20:13:27 -070077 end else begin : gen_others
78 assign inner_data[0] = regs_q[k-1];
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070079 assign valid_d[k] = valid_q[k-1];
Michael Schaffner7bc72232020-04-03 20:13:27 -070080 end
81
82 for (genvar l = 0; l < NumInnerRounds; l++) begin : gen_inner
83 // 2bit rotation + sbox layer
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070084 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 Schaffner7bc72232020-04-03 20:13:27 -070087 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 Schaffnereb7f3c72020-04-10 23:38:29 -070095 valid_q <= '0;
Michael Schaffner7bc72232020-04-03 20:13:27 -070096 end else begin
Michael Schaffnereb7f3c72020-04-10 23:38:29 -070097 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 Schaffner7bc72232020-04-03 20:13:27 -0700103 end
104 end
105
106 assign data_o = regs_q[NumOuterRounds-1];
Michael Schaffnereb7f3c72020-04-10 23:38:29 -0700107 assign valid_o = valid_q[NumOuterRounds-1];
Michael Schaffner7bc72232020-04-03 20:13:27 -0700108
109endmodule : prim_gate_gen