@@ -15,7 +15,8 @@ module kmac_msgfifo
1515 // pushing to MsgFIFO
1616 parameter int OutWidth = 64 ,
1717
18- parameter bit EnMasking = 1'b 1 ,
18+ parameter bit EnMasking = 1'b 1 ,
19+ localparam int Share = (EnMasking) ? 2 : 1 , // derived parameter
1920
2021 // Internal MsgFIFO Entry count
2122 parameter int MsgDepth = 9 ,
@@ -25,16 +26,17 @@ module kmac_msgfifo
2526 input rst_ni,
2627
2728 // from REG or KeyMgr Intf input
28- input fifo_valid_i,
29- input [OutWidth- 1 : 0 ] fifo_data_i,
29+ input logic fifo_valid_i,
30+ input [OutWidth- 1 : 0 ] fifo_data_i[Share] ,
3031 input [OutWidth- 1 : 0 ] fifo_strb_i,
31- output fifo_ready_o,
32+ output logic fifo_ready_o,
33+ input logic fifo_bypass_i,
3234
3335 // MSG interface
3436 output logic msg_valid_o,
35- output logic [OutWidth- 1 : 0 ] msg_data_o,
37+ output logic [OutWidth- 1 : 0 ] msg_data_o[Share] ,
3638 output logic [OutWidth/ 8 - 1 : 0 ] msg_strb_o,
37- input msg_ready_i,
39+ input logic msg_ready_i,
3840
3941 output logic fifo_empty_o,
4042 output logic fifo_full_o,
@@ -43,14 +45,52 @@ module kmac_msgfifo
4345 // Control
4446 input prim_mubi_pkg :: mubi4_t clear_i,
4547
46- // process_i --> process_o
47- // process_o asserted after all internal messages are flushed out to MSG interface
48- input process_i,
48+ // When process_i is asserted, packer and FIFO are flushed. Once flushed, process_o is asserted.
49+ // When bypassing, nothing must be flushed.
50+ input logic process_i,
4951 output logic process_o,
5052
5153 err_t err_o
5254);
5355
56+ // ////////////////
57+ // Bypass logic //
58+ // ////////////////
59+ // The packing and FIFO only support one share. These can be bypassed if operating with shares.
60+ logic fifo_valid;
61+ logic fifo_ready;
62+ logic [OutWidth/ 8 - 1 : 0 ] fifo_strb_byte;
63+ logic msg_valid;
64+ logic msg_ready;
65+ logic [OutWidth- 1 : 0 ] msg_data[Share];
66+ logic [OutWidth/ 8 - 1 : 0 ] msg_strb;
67+
68+ // Reduce strobe from bit to byte level as KMAC core operates on byte strobes.
69+ always_comb begin
70+ fifo_strb_byte = '0 ;
71+ for (int i = 0 ; i < $bits (fifo_strb_byte); i++ ) begin
72+ fifo_strb_byte[i] = | fifo_strb_i[8 * i + : 8 ];
73+ end
74+ end
75+
76+ assign fifo_valid = fifo_bypass_i ? '0 : fifo_valid_i;
77+ assign fifo_ready_o = fifo_bypass_i ? msg_ready_i : fifo_ready;
78+ assign msg_valid_o = fifo_bypass_i ? fifo_valid_i : msg_valid;
79+ assign msg_ready = fifo_bypass_i ? '0 : msg_ready_i;
80+ assign msg_strb_o = fifo_bypass_i ? fifo_strb_byte : msg_strb;
81+
82+ for (genvar i = 0 ; i < Share; i++ ) begin : g_msg_data_bypass_mux
83+ assign msg_data_o[i] = fifo_bypass_i ? fifo_data_i[i] : msg_data[i];
84+ end
85+
86+ // If bypassing, packer and FIFO must not be flushed so we can gate the flush signal and
87+ // feed it directly to process_o.
88+ logic process_to_fifo;
89+ logic process_from_fifo;
90+
91+ assign process_to_fifo = fifo_bypass_i ? '0 : process_i;
92+ assign process_o = fifo_bypass_i ? process_i : process_from_fifo;
93+
5494 // ///////////////
5595 // Definitions //
5696 // ///////////////
@@ -99,37 +139,41 @@ module kmac_msgfifo
99139
100140 // packer flush to msg_fifo, then msg_fifo empty out the internals
101141 // then assert msgfifo_flush_done
142+ logic packer_flush;
102143 logic packer_flush_done;
103144 logic msgfifo_flush_done;
104145
105146 logic packer_err;
106147
148+ assign packer_flush = process_to_fifo;
149+
107150 // SEC_CM: PACKER.CTR.REDUN
108151 prim_packer # (
109- .InW (OutWidth),
110- .OutW (OutWidth),
111- .HintByteData (1 ),
152+ .InW (OutWidth),
153+ .OutW (OutWidth),
154+ .HintByteData (1 ),
112155
113156 // Turn on dup counter when EnMasking is set
114- .EnProtection (EnMasking)
157+ .EnProtection (EnMasking)
115158 ) u_packer (
116159 .clk_i,
117160 .rst_ni,
118161
119- .valid_i (fifo_valid_i),
120- .data_i (fifo_data_i),
121- .mask_i (fifo_strb_i),
122- .ready_o (fifo_ready_o),
162+ .valid_i (fifo_valid),
163+ // FIFO operates only on one share
164+ .data_i (fifo_data_i[0 ]),
165+ .mask_i (fifo_strb_i),
166+ .ready_o (fifo_ready),
123167
124- .valid_o (packer_wvalid),
125- .data_o (packer_wdata),
126- .mask_o (packer_wmask),
127- .ready_i (packer_wready),
168+ .valid_o (packer_wvalid),
169+ .data_o (packer_wdata),
170+ .mask_o (packer_wmask),
171+ .ready_i (packer_wready),
128172
129- .flush_i (process_i ),
130- .flush_done_o (packer_flush_done),
173+ .flush_i (packer_flush ),
174+ .flush_done_o (packer_flush_done),
131175
132- .err_o (packer_err)
176+ .err_o (packer_err)
133177 );
134178
135179 // Assign packer wdata and wmask to FIFO struct
@@ -171,10 +215,13 @@ module kmac_msgfifo
171215 assign fifo_wvalid = packer_wvalid;
172216 assign packer_wready = fifo_wready;
173217
174- assign msg_valid_o = fifo_rvalid;
175- assign fifo_rready = msg_ready_i;
176- assign msg_data_o = fifo_rdata.data;
177- assign msg_strb_o = fifo_rdata.strb;
218+ assign msg_valid = fifo_rvalid;
219+ assign fifo_rready = msg_ready;
220+ assign msg_strb = fifo_rdata.strb;
221+ assign msg_data[0 ] = fifo_rdata.data;
222+ for (genvar i = 1 ; i < Share; i++ ) begin : g_msg_data_mask_assignment
223+ assign msg_data[i] = '0 ;
224+ end
178225
179226 assign fifo_empty_o = ! fifo_rvalid;
180227
@@ -196,7 +243,9 @@ module kmac_msgfifo
196243
197244 unique case (flush_st)
198245 FlushIdle: begin
199- if (process_i) begin
246+ // Only enter packer-flush sequence when not in bypass mode.
247+ // In bypass mode, process_o is driven directly from process_i below.
248+ if (packer_flush) begin
200249 flush_st_d = FlushPacker;
201250 end else begin
202251 flush_st_d = FlushIdle;
@@ -235,7 +284,7 @@ module kmac_msgfifo
235284 endcase
236285 end
237286
238- assign process_o = msgfifo_flush_done;
287+ assign process_from_fifo = msgfifo_flush_done;
239288
240289 err_t error;
241290 assign err_o = error;
@@ -273,12 +322,36 @@ module kmac_msgfifo
273322 `ASSERT (FlushStInValid_A, flush_st inside { FlushIdle, FlushPacker, FlushFifo, FlushClear} )
274323
275324 // Packer done signal is asserted at least one cycle later
276- `ASSERT (PackerDoneDelay_A, $onehot0 ({ process_i , packer_flush_done} ))
325+ `ASSERT (PackerDoneDelay_A, $onehot0 ({ packer_flush , packer_flush_done} ))
277326
278327 // process_i not asserted during the flush operation
279- `ASSUME (PackerDoneValid_a, process_i | - > flush_st == FlushIdle)
328+ `ASSUME (PackerDoneValid_a, packer_flush | - > flush_st == FlushIdle)
280329
281330 // No messages in between `process_i` and `clear_i`
282331 `ASSUME (MessageValid_a, fifo_valid_i | - > flush_st == FlushIdle)
283332
333+ `ifdef INC_ASSERT
334+ // INC_ASSERT is used to hide signal definitions that are only used for assertions.
335+ // VCS coverage off
336+ // pragma coverage off
337+
338+ // Assert that fifo_bypass_i remains stable once the first messages was handshaked until the FIFO
339+ // has been flushed or the full message is sent downstream, respectively.
340+ logic first_data_entered;
341+ always_ff @ (posedge clk_i or negedge rst_ni) begin
342+ if (! rst_ni) begin
343+ first_data_entered <= 1'b0 ;
344+ end else if (fifo_valid_i && fifo_ready_o) begin
345+ first_data_entered <= 1'b1 ;
346+ end else if (process_o) begin
347+ first_data_entered <= 1'b0 ;
348+ end
349+ end
350+
351+ `ASSERT (BypassCtrlStable_A,
352+ first_data_entered && ! process_o
353+ | - > fifo_bypass_i == $past (fifo_bypass_i))
354+
355+ `endif
356+
284357endmodule
0 commit comments