../src/lowrisc_ip_hmac_0.1/rtl/sha2_pad.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: // SHA-256 Padding logic
6: //
7:
8: `include "prim_assert.sv"
9:
10: module sha2_pad import hmac_pkg::*; (
11: input clk_i,
12: input rst_ni,
13:
14: input wipe_secret,
15: input sha_word_t wipe_v,
16:
17: // To actual FIFO
18: input fifo_rvalid,
19: input sha_fifo_t fifo_rdata,
20: output logic fifo_rready,
21:
22: // from SHA2 compress engine
23: output logic shaf_rvalid,
24: output sha_word_t shaf_rdata,
25: input shaf_rready,
26:
27: input sha_en,
28: input hash_start,
29: input hash_process,
30: input hash_done,
31:
32: input [63:0] message_length, // # of bytes in bits (8 bits granularity)
33: output logic msg_feed_complete // Indicates, all message is feeded
34: );
35:
36: //logic [8:0] length_added;
37:
38: logic [63:0] tx_count; // fin received data count.
39:
40: logic inc_txcount;
41: logic fifo_partial;
42: logic txcnt_eq_1a0;
43: logic hash_process_flag; // Set by hash_process, clear by hash_done
44:
45: assign fifo_partial = ~&fifo_rdata.mask;
46:
47: // tx_count[8:0] == 'h1c0 --> should send LenHi
48: assign txcnt_eq_1a0 = (tx_count[8:0] == 9'h1a0);
49:
50: always_ff @(posedge clk_i or negedge rst_ni) begin
51: if (!rst_ni) begin
52: hash_process_flag <= 1'b0;
53: end else if (hash_process) begin
54: hash_process_flag <= 1'b1;
55: end else if (hash_done || hash_start) begin
56: hash_process_flag <= 1'b0;
57: end
58: end
59:
60: // Data path: fout_wdata
61: typedef enum logic [2:0] {
62: FifoIn, // fin_wdata, fin_wstrb
63: Pad80, // {8'h80, 8'h00} , strb (calc based on len[4:3])
64: Pad00, // 32'h0, full strb
65: LenHi, // len[63:32], full strb
66: LenLo // len[31:0], full strb
67: } sel_data_e;
68: sel_data_e sel_data;
69:
70: always_comb begin
71: unique case (sel_data)
72: FifoIn: begin
73: shaf_rdata = fifo_rdata.data;
74: end
75:
76: Pad80: begin
77: // {a[7:0], b[7:0], c[7:0], d[7:0]}
78: // msglen[4:3] == 00 |-> {'h80, 'h00, 'h00, 'h00}
79: // msglen[4:3] == 01 |-> {msg, 'h80, 'h00, 'h00}
80: // msglen[4:3] == 10 |-> {msg[15:0], 'h80, 'h00}
81: // msglen[4:3] == 11 |-> {msg[23:0], 'h80}
82: unique case (message_length[4:3])
83: 2'b 00: shaf_rdata = 32'h 8000_0000;
84: 2'b 01: shaf_rdata = {fifo_rdata.data[31:24], 24'h 8000_00};
85: 2'b 10: shaf_rdata = {fifo_rdata.data[31:16], 16'h 8000};
86: 2'b 11: shaf_rdata = {fifo_rdata.data[31: 8], 8'h 80};
87: default: shaf_rdata = 32'h0;
88: endcase
89: end
90:
91: Pad00: begin
92: shaf_rdata = '0;
93: end
94:
95: LenHi: begin
96: shaf_rdata = message_length[63:32];
97: end
98:
99: LenLo: begin
100: shaf_rdata = message_length[31:0];
101: end
102:
103: default: begin
104: shaf_rdata = '0;
105: end
106: endcase
107: end
108:
109: // Padded length
110: // $ceil(message_length + 8 + 64, 512) -> message_length [8:0] + 440 and ignore carry
111: //assign length_added = (message_length[8:0] + 9'h1b8) ;
112:
113: // fifo control
114: // add 8'h 80 , N 8'h00, 64'h message_length
115:
116: // Steps
117: // 1. `hash_start` from CPU (or DMA?)
118: // 2. calculate `padded_length` from `message_length`
119: // 3. Check if tx_count == message_length, then go to 5
120: // 4. Receiving FIFO input (hand over to fifo output)
121: // 5. Padding bit 1 (8'h80) followed by 8'h00 if needed
122: // 6. Padding with length (high -> low)
123:
124: // State Machine
125: typedef enum logic [2:0] {
126: StIdle, // fin_full to prevent unwanted FIFO write
127: StFifoReceive, // Check tx_count == message_length
128: StPad80, // 8'h 80 + 8'h 00 X N
129: StPad00,
130: StLenHi,
131: StLenLo
132: } pad_st_e;
133:
134: pad_st_e st_q, st_d;
135:
136: always_ff @(posedge clk_i or negedge rst_ni) begin
137: if (!rst_ni) begin
138: st_q <= StIdle;
139: end else begin
140: st_q <= st_d;
141: end
142: end
143:
144: // Next state
145: always_comb begin
146: shaf_rvalid = 1'b0;
147: inc_txcount = 1'b0;
148: sel_data = FifoIn;
149: fifo_rready = 1'b0;
150:
151: st_d = StIdle;
152:
153: unique case (st_q)
154: StIdle: begin
155: sel_data = FifoIn;
156: shaf_rvalid = 1'b0;
157:
158: if (sha_en && hash_start) begin
159: inc_txcount = 1'b0;
160:
161: st_d = StFifoReceive;
162: end else begin
163: st_d = StIdle;
164: end
165: end
166:
167: StFifoReceive: begin
168: sel_data = FifoIn;
169:
170: if (fifo_partial && fifo_rvalid) begin
171: // End of the message, assume hash_process_flag is set
172: shaf_rvalid = 1'b0; // Update entry at StPad80
173: inc_txcount = 1'b0;
174: fifo_rready = 1'b0;
175:
176: st_d = StPad80;
177: end else if (!hash_process_flag) begin
178: fifo_rready = shaf_rready;
179: shaf_rvalid = fifo_rvalid;
180: inc_txcount = shaf_rready;
181:
182: st_d = StFifoReceive;
183: end else if (tx_count == message_length) begin
184: // already received all msg and was waiting process flag
185: shaf_rvalid = 1'b0;
186: inc_txcount = 1'b0;
187: fifo_rready = 1'b0;
188:
189: st_d = StPad80;
190: end else begin
191: shaf_rvalid = fifo_rvalid;
192: fifo_rready = shaf_rready; // 0 always
193: inc_txcount = shaf_rready; // 0 always
194:
195: st_d = StFifoReceive;
196: end
197: end
198:
199: StPad80: begin
200: sel_data = Pad80;
201:
202: shaf_rvalid = 1'b1;
203: fifo_rready = shaf_rready && |message_length[4:3]; // Only when partial
204:
205: // exactly 96 bits left, do not need to pad00's
206: if (shaf_rready && txcnt_eq_1a0) begin
207: st_d = StLenHi;
208: inc_txcount = 1'b1;
209: // it does not matter if value is < or > than 416 bits. If it's the former, 00 pad until
210: // length field. If >, then the next chunk will contain the length field with appropriate
211: // 0 padding.
212: end else if (shaf_rready && !txcnt_eq_1a0) begin
213: st_d = StPad00;
214: inc_txcount = 1'b1;
215: end else begin
216: st_d = StPad80;
217: inc_txcount = 1'b0;
218: end
219:
220: // # Below part is temporal code to speed up the SHA by 16 clocks per chunk
221: // # (80 clk --> 64 clk)
222: // # leaving this as a reference but needs to verify it.
223: //if (shaf_rready && !txcnt_eq_1a0) begin
224: // st_d = StPad00;
225: //
226: // inc_txcount = 1'b1;
227: // shaf_rvalid = (msg_word_aligned) ? 1'b1 : fifo_rvalid;
228: // fifo_rready = (msg_word_aligned) ? 1'b0 : 1'b1;
229: //end else if (!shaf_rready && !txcnt_eq_1a0) begin
230: // st_d = StPad80;
231: //
232: // inc_txcount = 1'b0;
233: // shaf_rvalid = (msg_word_aligned) ? 1'b1 : fifo_rvalid;
234: //
235: //end else if (shaf_rready && txcnt_eq_1a0) begin
236: // st_d = StLenHi;
237: // inc_txcount = 1'b1;
238: //end else begin
239: // // !shaf_rready && txcnt_eq_1a0 , just wait until fifo_rready asserted
240: // st_d = StPad80;
241: // inc_txcount = 1'b0;
242: //end
243: end
244:
245: StPad00: begin
246: sel_data = Pad00;
247: shaf_rvalid = 1'b1;
248:
249: if (shaf_rready) begin
250: inc_txcount = 1'b1;
251:
252: if (txcnt_eq_1a0) begin
253: st_d = StLenHi;
254: end else begin
255: st_d = StPad00;
256: end
257: end else begin
258: st_d = StPad00;
259: end
260: end
261:
262: StLenHi: begin
263: sel_data = LenHi;
264: shaf_rvalid = 1'b1;
265:
266: if (shaf_rready) begin
267: st_d = StLenLo;
268:
269: inc_txcount = 1'b1;
270: end else begin
271: st_d = StLenHi;
272:
273: inc_txcount = 1'b0;
274: end
275: end
276:
277: StLenLo: begin
278: sel_data = LenLo;
279: shaf_rvalid = 1'b1;
280:
281: if (shaf_rready) begin
282: st_d = StIdle;
283:
284: inc_txcount = 1'b1;
285: end else begin
286: st_d = StLenLo;
287:
288: inc_txcount = 1'b0;
289: end
290: end
291:
292: default: begin
293: st_d = StIdle;
294: end
295: endcase
296: end
297:
298: // tx_count
299: always_ff @(posedge clk_i or negedge rst_ni) begin
300: if (!rst_ni) begin
301: tx_count <= '0;
302: end else if (hash_start) begin
303: tx_count <= '0;
304: end else if (inc_txcount) begin
305: tx_count[63:5] <= tx_count[63:5] + 1'b1;
306: end
307: end
308:
309: // State machine is in Idle only when it meets tx_count == message length
310: assign msg_feed_complete = hash_process_flag && (st_q == StIdle);
311:
312: // When fifo_partial, fifo shouldn't be empty and hash_process was set
313: `ASSERT(ValidPartialConditionAssert,
314: fifo_partial && fifo_rvalid |-> hash_process_flag)
315:
316: endmodule
317: