88: // > A[x,y,z]=S[w(5y+x)+z]
89: function automatic box_t bitarray_to_box(logic [Width-1:0] s_in);
90: automatic box_t box;
91: for (int y = 0 ; y < 5 ; y++) begin
92: for (int x = 0 ; x < 5 ; x++) begin
93: for (int z = 0 ; z < W ; z++) begin
94: box[x][y][z] = s_in[W*(5*y+x) + z];
95: end
96: end
97: end
98: return box;
99: endfunction : bitarray_to_box
100:
101: // Convert 3D cube to bitarray
102: function automatic logic [Width-1:0] box_to_bitarray(box_t state);
103: automatic logic [Width-1:0] bitarray;
104: for (int y = 0 ; y < 5 ; y++) begin
105: for (int x = 0 ; x < 5 ; x++) begin
106: for (int z = 0 ; z < W ; z++) begin
107: bitarray[W*(5*y+x)+z] = state[x][y][z];
108: end
109: end
110: end
111: return bitarray;
112: endfunction : box_to_bitarray
113:
114: // Step Mapping =============================================================
115: // theta(θ)
116: // XOR each bit in the state with the parity of two columns
117: // C[x,z] = A[x,0,z] ^ A[x,1,z] ^ A[x,2,z] ^ A[x,3,z] ^ A[x,4,z]
118: // D[x,z] = C[x-1,z] ^ C[x+1,z-1]
119: // theta = A[x,y,z] ^ D[x,z]
120: function automatic box_t theta(box_t state);
121: plane_t c;
122: plane_t d;
123: box_t result;
124: for (int x = 0 ; x < 5 ; x++) begin
125: for (int z = 0 ; z < W ; z++) begin
126: c[x][z] = state[x][0][z] ^ state[x][1][z]
127: ^ state[x][2][z] ^ state[x][3][z] ^ state[x][4][z];
128: end
129: end
130: for (int x = 0 ; x < 5 ; x++) begin
131: int index_x1, index_x2;
132: index_x1 = (x == 0) ? 4 : x-1; // (x-1)%5
133: index_x2 = (x == 4) ? 0 : x+1; // (x+1)%5
134: for (int z = 0 ; z < W ; z++) begin
135: int index_z;
136: index_z = (z == 0) ? W-1 : z-1; // (z+1)%W
137: d[x][z] = c[index_x1][z] ^ c[index_x2][index_z];
138: end
139: end
140: for (int x = 0 ; x < 5 ; x++) begin
141: for (int y = 0 ; y < 5 ; y++) begin
142: for (int z = 0 ; z < W ; z++) begin
143: result[x][y][z] = state[x][y][z] ^ d[x][z];
144: end
145: end
146: end
147: return result;
148: endfunction : theta
149:
150: // rho
151:
152: // Commented out entire rho function due to VCS elaboration error.
153: // (z-RhoOffset[x][y]%W) isn't considered as a constant in VCS.
154: // Even changing it to W-RhoOffset[x][y]%W and assign to ShiftAmt
155: // creates same error.
156:
157: // Offset : Look at Table 2 in FIPS PUB 202
158: //localparam int RhoOffset [5][5] = '{
159: // //y 0 1 2 3 4 x
160: // '{ 0, 36, 3, 105, 210},// 0
161: // '{ 1, 300, 10, 45, 66},// 1
162: // '{ 190, 6, 171, 15, 253},// 2
163: // '{ 28, 55, 153, 21, 120},// 3
164: // '{ 91, 276, 231, 136, 78} // 4
165: //};
166:
167: // rotate bits of each lane by offset
168: // 1. rho[0,0,z] = A[0,0,z]
169: // 2. Offset swap
170: // a. (x,y) := (1,0)
171: // b. for t [0..23]
172: // i. rho[x,y,z] = A[x,y,z-(t+1)(t+2)/2]
173: // ii. (x,y) = (y, (2x+3y))
174: //function automatic box_t rho(box_t state);
175: // box_t result;
176: // for (int x = 0 ; x < 5 ; x++) begin
177: // for (int y = 0 ; y < 5 ; y++) begin
178: // for (int z = 0 ; z < W ; z++) begin
179: // automatic int index_z;
180: // index_z = (z-RhoOffset[x][y])%W;
181: // result[x][y][z] = state[x][y][(z-RhoOffset[x][y])%W];
182: // end
183: // end
184: // end
185: // return result;
186: //endfunction : rho
187:
188: // pi
189: // rearrange the position of lanes
190: // pi[x,y,z] = state[(x+3y),x,z]
191: localparam int PiRotate [5][5] = '{
192: //y 0 1 2 3 4 x
193: '{ 0, 3, 1, 4, 2},// 0
194: '{ 1, 4, 2, 0, 3},// 1
195: '{ 2, 0, 3, 1, 4},// 2
196: '{ 3, 1, 4, 2, 0},// 3
197: '{ 4, 2, 0, 3, 1} // 4
198: };
199: function automatic box_t pi(box_t state);
200: box_t result;
201: for (int x = 0 ; x < 5 ; x++) begin
202: for (int y = 0 ; y < 5 ; y++) begin
203: int index_x;
204: result[x][y][W-1:0] = state[PiRotate[x][y]][x][W-1:0];
205: end
206: end
207: return result;
208: endfunction : pi
209:
210: // chi
211: // chi[x,y,z] = state[x,y,z] ^ ((state[x+1,y,z] ^ 1) & state[x+2,y,z])
212: function automatic box_t chi(box_t state);
213: box_t result;
214: for (int x = 0 ; x < 5 ; x++) begin
215: int index_x1, index_x2;
216: index_x1 = (x == 4) ? 0 : x+1;
217: index_x2 = (x >= 3) ? x-3 : x+2;
218: for (int y = 0 ; y < 5 ; y++) begin
219: for (int z = 0 ; z < W ; z++) begin
220: result[x][y][z] = state[x][y][z] ^
221: ((~state[index_x1][y][z])
222: & state[index_x2][y][z]);
223: end
224: end
225: end
226: return result;
227: endfunction : chi
228:
229: // iota
230: // XOR (x,y) = (0,0) with round constant
231:
232: // RC parameter: Precomputed by util/keccak_rc.py. Only up-to 0..L-1 is used
233: // RC = '0
234: // RC[2**j-1] = rc(j+7*rnd)
235: // rc(t) =
236: // 1. t%255 == 0 -> 1
237: // 2. R[0:7] = 'b10000000
238: // 3. for i = [1..t%255]
239: // a. R = 0 || R
240: // b. R[0] = R[0] ^ R[8]
241: // c. R[4] = R[4] ^ R[8]
242: // d. R[5] = R[5] ^ R[8]
243: // e. R[6] = R[6] ^ R[8]
244: // f. R = R[0:7]
245: // 4. return R[0]
246: // RC has L = [0..6]
247: // for lower L case, only chopping lower part of 64bit RC is sufficient.
248: localparam logic [63:0] RC [24] = '{
249: 64'h 0000_0000_0000_0001, // Round 0
250: 64'h 0000_0000_0000_8082, // Round 1
251: 64'h 8000_0000_0000_808A, // Round 2
252: 64'h 8000_0000_8000_8000, // Round 3
253: 64'h 0000_0000_0000_808B, // Round 4
254: 64'h 0000_0000_8000_0001, // Round 5
255: 64'h 8000_0000_8000_8081, // Round 6
256: 64'h 8000_0000_0000_8009, // Round 7
257: 64'h 0000_0000_0000_008A, // Round 8
258: 64'h 0000_0000_0000_0088, // Round 9
259: 64'h 0000_0000_8000_8009, // Round 10
260: 64'h 0000_0000_8000_000A, // Round 11
261: 64'h 0000_0000_8000_808B, // Round 12
262: 64'h 8000_0000_0000_008B, // Round 13
263: 64'h 8000_0000_0000_8089, // Round 14
264: 64'h 8000_0000_0000_8003, // Round 15
265: 64'h 8000_0000_0000_8002, // Round 16
266: 64'h 8000_0000_0000_0080, // Round 17
267: 64'h 0000_0000_0000_800A, // Round 18
268: 64'h 8000_0000_8000_000A, // Round 19
269: 64'h 8000_0000_8000_8081, // Round 20
270: 64'h 8000_0000_0000_8080, // Round 21
271: 64'h 0000_0000_8000_0001, // Round 22
272: 64'h 8000_0000_8000_8008 // Round 23
273: };
274:
275: // iota: XOR with RC for (x,y) = (0,0)
276: function automatic box_t iota(box_t state, logic [RndW-1:0] rnd);
277: box_t result;
278: result = state;
279: result[0][0][W-1:0] = state[0][0][W-1:0] ^ RC[rnd][W-1:0];
280:
281: return result;
282: endfunction : iota
283:
284: // Round function : Rnd(A,i_r)
285: // Not used due to rho function issue described above.
286:
287: //function automatic box_t keccak_rnd(box_t state, logic [RndW-1:0] rnd);
288: // box_t keccak_state;
289: // keccak_state = iota(chi(pi(rho(theta(state)))), rnd);
290: //
291: // return keccak_state;
292: //endfunction : keccak_rnd
293:
294: endmodule
295:
296: