Newer
Older
dam1n19
committed
//-----------------------------------------------------------------------------
// SoC Labs Basic SHA-2 Hash Processing Module
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright 2022, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
dam1n19
committed
module hash_process (
input logic clk,
input logic nrst,
input logic en,
// Synchronous, localised reset
input logic sync_rst,
// Data In data and Handshaking
input logic [511:0] data_in,
input logic data_in_last,
input logic data_in_valid,
output logic data_in_ready,
// Data Out data and Handshaking
dam1n19
committed
output logic data_out_last,
output logic data_out_valid,
input logic data_out_ready
);
dam1n19
committed
// Message Chunks
logic [31:0] M [15:0];
// Assign M Variables to 32 bit chunks of the input data
genvar i;
generate
for (i = 0; i < 16; i++) begin
assign M[i] = data_in[(32*((15-i)+1))-1:32*(15-i)];
end
endgenerate
// Hash Value Registers
logic [31:0] H [7:0];
logic [31:0] next_H [7:0];
// Message Schedule Registers
logic [31:0] W [63:0];
logic [31:0] next_W [63:0];
// Working Registers
logic [31:0] a,b,c,d,e,f,g,h;
logic [31:0] next_a,next_b,next_c,next_d,next_e,next_f,next_g,next_h;
logic [31:0] T1, T2;
// State Machine Registers
logic [2:0] state, next_state;
logic next_data_in_ready, next_data_out_valid, next_data_out_last;
logic [5:0] hash_iter, next_hash_iter;
logic last_block, next_last_block;
// // SHA-2 Constants
logic [31:0] K [63:0];
dam1n19
committed
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
assign K[0] = 32'h428a2f98;
assign K[1] = 32'h71374491;
assign K[2] = 32'hb5c0fbcf;
assign K[3] = 32'he9b5dba5;
assign K[4] = 32'h3956c25b;
assign K[5] = 32'h59f111f1;
assign K[6] = 32'h923f82a4;
assign K[7] = 32'hab1c5ed5;
assign K[8] = 32'hd807aa98;
assign K[9] = 32'h12835b01;
assign K[10] = 32'h243185be;
assign K[11] = 32'h550c7dc3;
assign K[12] = 32'h72be5d74;
assign K[13] = 32'h80deb1fe;
assign K[14] = 32'h9bdc06a7;
assign K[15] = 32'hc19bf174;
assign K[16] = 32'he49b69c1;
assign K[17] = 32'hefbe4786;
assign K[18] = 32'h0fc19dc6;
assign K[19] = 32'h240ca1cc;
assign K[20] = 32'h2de92c6f;
assign K[21] = 32'h4a7484aa;
assign K[22] = 32'h5cb0a9dc;
assign K[23] = 32'h76f988da;
assign K[24] = 32'h983e5152;
assign K[25] = 32'ha831c66d;
assign K[26] = 32'hb00327c8;
assign K[27] = 32'hbf597fc7;
assign K[28] = 32'hc6e00bf3;
assign K[29] = 32'hd5a79147;
assign K[30] = 32'h06ca6351;
assign K[31] = 32'h14292967;
assign K[32] = 32'h27b70a85;
assign K[33] = 32'h2e1b2138;
assign K[34] = 32'h4d2c6dfc;
assign K[35] = 32'h53380d13;
assign K[36] = 32'h650a7354;
assign K[37] = 32'h766a0abb;
assign K[38] = 32'h81c2c92e;
assign K[39] = 32'h92722c85;
assign K[40] = 32'ha2bfe8a1;
assign K[41] = 32'ha81a664b;
assign K[42] = 32'hc24b8b70;
assign K[43] = 32'hc76c51a3;
assign K[44] = 32'hd192e819;
assign K[45] = 32'hd6990624;
assign K[46] = 32'hf40e3585;
assign K[47] = 32'h106aa070;
assign K[48] = 32'h19a4c116;
assign K[49] = 32'h1e376c08;
assign K[50] = 32'h2748774c;
assign K[51] = 32'h34b0bcb5;
assign K[52] = 32'h391c0cb3;
assign K[53] = 32'h4ed8aa4a;
assign K[54] = 32'h5b9cca4f;
assign K[55] = 32'h682e6ff3;
assign K[56] = 32'h748f82ee;
assign K[57] = 32'h78a5636f;
assign K[58] = 32'h84c87814;
assign K[59] = 32'h8cc70208;
assign K[60] = 32'h90befffa;
assign K[61] = 32'ha4506ceb;
assign K[62] = 32'hbef9a3f7;
assign K[63] = 32'hc67178f2;
// ssig1 next_W assignments - issues using functions with arrayed objects in ivlog
logic [31:0] ssig1_next_W [63:0];
generate
for (i = 0; i < 64; i ++) begin
assign ssig0_next_W[i] = ((next_W[i] << 25) | (next_W[i] >> 7)) ^ ((next_W[i] << 14) | (next_W[i] >> 18)) ^ (next_W[i] >> 3);
assign ssig1_next_W[i] = ((next_W[i] << 15) | (next_W[i] >> 17)) ^ ((next_W[i] << 13) | (next_W[i] >> 19)) ^ (next_W[i] >> 10);
end
endgenerate
// State Machine Sequential Logic
always_ff @(posedge clk, negedge nrst) begin
if ((!nrst) | sync_rst) begin
state <= 3'd0;
hash_iter <= 6'd0;
last_block <= 1'b0;
data_in_ready <= 1'b0;
data_out_valid <= 1'b0;
data_out_last <= 1'b0;
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// Reset Working Registers
a <= 32'd0;
b <= 32'd0;
c <= 32'd0;
d <= 32'd0;
e <= 32'd0;
f <= 32'd0;
g <= 32'd0;
h <= 32'd0;
// Reset H Registers
for (int i=0; i < 8; i++) begin
H[i] <= 32'd0;
end
// Reset W Registers
for (int i=0; i < 64; i++) begin
W[i] <= 32'd0;
end
end else begin
state <= next_state;
hash_iter <= next_hash_iter;
last_block <= next_last_block;
data_in_ready <= next_data_in_ready;
data_out_valid <= next_data_out_valid;
data_out_last <= next_data_out_last;
data_out <= next_data_out;
// Set Working Registers
a <= next_a;
b <= next_b;
c <= next_c;
d <= next_d;
e <= next_e;
f <= next_f;
g <= next_g;
h <= next_h;
// Set H Registers
for (int i=0; i < 8; i++) begin
H[i] <= next_H[i];
end
// Set W Registers
for (int i=0; i < 64; i++) begin
W[i] <= next_W[i];
end
end
end
// State Machine Combinatorial Logic
always_comb begin
// Default
next_state = state;
next_hash_iter = hash_iter;
next_last_block = last_block;
next_data_in_ready = data_in_ready;
next_data_out_valid = data_out_valid;
next_data_out_last = data_out_last;
next_data_out = data_out;
// Set next Working Registers
next_a = a;
next_b = b;
next_c = c;
next_d = d;
next_e = e;
next_f = f;
next_g = g;
next_h = h;
// Set next H Registers
for (int i=0; i < 8; i++) begin
next_H[i] = H[i];
end
// Set next W Registers
for (int i=0; i < 64; i++) begin
next_W[i] = W[i];
end
// Logic for Temporary Words
T1 = h + bsig1(e) + ch(e,f,g) + K[hash_iter] + W[hash_iter];
T2 = bsig0(a) + maj(a,b,c);
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// Override
case (state)
3'd0: begin // Initialise Hash Registers -- this state may be able to be removed (reset values could be changed to these values)
if (!(data_out_valid && !data_out_ready)) begin
// If data out handshake has been seen, drop valid
next_data_out_valid = 1'b0;
end
// Initialise Hash Value Registers
next_H[0] = 32'h6a09e667;
next_H[1] = 32'hbb67ae85;
next_H[2] = 32'h3c6ef372;
next_H[3] = 32'ha54ff53a;
next_H[4] = 32'h510e527f;
next_H[5] = 32'h9b05688c;
next_H[6] = 32'h1f83d9ab;
next_H[7] = 32'h5be0cd19;
next_data_in_ready = 1'b1;
next_state = 3'd1;
end
3'd1: begin // Perform Hash Initialisation
if (!(data_out_valid && !data_out_ready)) begin
// If data out handshake has been seen, drop valid
next_data_out_valid = 1'b0;
end
if (data_in_valid && data_in_ready) begin
// Valid Handshake and data can be processed
// Use the Message chunks to populate the message schedule
for (logic [31:0] t = 0; t < 64; t++) begin
if (t < 16) begin
next_W[t] = M[t];
end else begin
next_W[t] = ssig1_next_W[t-2] + next_W[t-32'd7] + ssig0_next_W[t-15] + next_W[t-32'd16];
end
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
end
// Set Working Variables
next_a = H[0];
next_b = H[1];
next_c = H[2];
next_d = H[3];
next_e = H[4];
next_f = H[5];
next_g = H[6];
next_h = H[7];
// Move to next state
next_state = 3'd2;
next_hash_iter = 6'd0;
next_last_block = data_in_last;
// Drop Ready Signal to confirm handshake
next_data_in_ready = 1'b0;
end
end
3'd2: begin // Perform the main hash computation
if (!(data_out_valid && !data_out_ready)) begin
// If data out handshake has been seen, drop valid
next_data_out_valid = 1'b0;
end
// Perform Hash Function
next_a = T1 + T2;
next_b = a;
next_c = b;
next_d = c;
next_e = d + T1;
next_f = e;
next_g = f;
next_h = g;
// Decrement Iteration Register
next_hash_iter = hash_iter + 6'd1;
if (hash_iter == 63) begin
next_state = 3'd3;
end
end
3'd3: begin // Compute intermediate hash value
if (!(data_out_valid && !data_out_ready)) begin
// If data out handshake has been seen, drop valid
next_data_out_valid = 1'b0;
end
next_H[0] = a + H[0];
next_H[1] = b + H[1];
next_H[2] = c + H[2];
next_H[3] = d + H[3];
next_H[4] = e + H[4];
next_H[5] = f + H[5];
next_H[6] = g + H[6];
next_H[7] = h + H[7];
if (last_block) begin
if (!data_out_valid) begin // No Data waiting at output
next_data_out = {next_H[0], next_H[1], next_H[2], next_H[3], next_H[4], next_H[5], next_H[6], next_H[7]};
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
next_data_out_last = 1'b1;
next_data_out_valid = 1'b1;
// Next State Logic
next_state = 3'd1;
next_data_in_ready = 1'b1;
// Initialise Hash Value Registers
next_H[0] = 32'h6a09e667;
next_H[1] = 32'hbb67ae85;
next_H[2] = 32'h3c6ef372;
next_H[3] = 32'ha54ff53a;
next_H[4] = 32'h510e527f;
next_H[5] = 32'h9b05688c;
next_H[6] = 32'h1f83d9ab;
next_H[7] = 32'h5be0cd19;
end else begin
// Still Waiting for previous data to be recieved
next_state = 3'd4;
next_data_in_ready = 1'b0;
end
end else begin
// Next State Logic
next_data_in_ready = 1'b1;
next_state = 3'd1;
end
end
3'd4: begin // Output Handling
if (!(data_out_valid && !data_out_ready)) begin
// If data out handshake has been seen, drop valid
next_data_out_valid = 1'b0;
end
if (!data_out_valid) begin // No Data waiting at output
next_data_out = {next_H[0], next_H[1], next_H[2], next_H[3], next_H[4], next_H[5], next_H[6], next_H[7]};
next_data_out_last = 1'b1;
next_data_out_valid = 1'b1;
// Next State Logic
next_state = 3'd1;
next_data_in_ready = 1'b1;
// Initialise Hash Value Registers
next_H[0] = 32'h6a09e667;
next_H[1] = 32'hbb67ae85;
next_H[2] = 32'h3c6ef372;
next_H[3] = 32'ha54ff53a;
next_H[4] = 32'h510e527f;
next_H[5] = 32'h9b05688c;
next_H[6] = 32'h1f83d9ab;
next_H[7] = 32'h5be0cd19;
end else begin
// Still Waiting for previous data to be recieved
next_state = 3'd4;
next_data_in_ready = 1'b0;
end
end