blob: 7709d19e964c977aad37642f2d4511c28b810410 [file] [log] [blame]
Timothy Chenff4a7702020-10-27 15:08:53 -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//
5// Flash Controller Module
6//
7//
8
9`include "prim_assert.sv"
10
Timothy Chenf52a4612020-12-04 20:37:49 -080011module flash_ctrl import flash_ctrl_pkg::*; #(
Timothy Chenaeffadc2020-12-11 15:03:07 -080012 parameter flash_key_t RndCnstAddrKey = RndCnstAddrKeyDefault,
13 parameter flash_key_t RndCnstDataKey = RndCnstDataKeyDefault,
14 parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
15 parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault
Timothy Chenf52a4612020-12-04 20:37:49 -080016) (
Timothy Chenff4a7702020-10-27 15:08:53 -070017 input clk_i,
18 input rst_ni,
19
Timothy Chenf52a4612020-12-04 20:37:49 -080020 input clk_otp_i,
21 input rst_otp_ni,
22
Timothy Chen8ea1b412020-11-18 18:32:08 -080023 // life cycle interface
Timothy Chen99f3e3a2020-12-09 18:30:19 -080024 input lc_ctrl_pkg::lc_tx_t lc_creator_seed_sw_rw_en_i,
25 input lc_ctrl_pkg::lc_tx_t lc_owner_seed_sw_rw_en_i,
26 input lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_rd_en_i,
27 input lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_wr_en_i,
28 input lc_ctrl_pkg::lc_tx_t lc_seed_hw_rd_en_i,
Timothy Chen8ea1b412020-11-18 18:32:08 -080029
Timothy Chenff4a7702020-10-27 15:08:53 -070030 // Bus Interface
31 input tlul_pkg::tl_h2d_t tl_i,
32 output tlul_pkg::tl_d2h_t tl_o,
33
34 // Flash Interface
35 input flash_rsp_t flash_i,
36 output flash_req_t flash_o,
37
38 // otp/lc/pwrmgr/keymgr Interface
Timothy Chenf52a4612020-12-04 20:37:49 -080039 output otp_ctrl_pkg::flash_otp_key_req_t otp_o,
40 input otp_ctrl_pkg::flash_otp_key_rsp_t otp_i,
Timothy Chenff4a7702020-10-27 15:08:53 -070041 input lc_flash_req_t lc_i,
42 output lc_flash_rsp_t lc_o,
43 input pwrmgr_pkg::pwr_flash_req_t pwrmgr_i,
44 output pwrmgr_pkg::pwr_flash_rsp_t pwrmgr_o,
Timothy Chenaeffadc2020-12-11 15:03:07 -080045 output edn_pkg::edn_req_t edn_o,
46 input edn_pkg::edn_rsp_t edn_i,
Timothy Chenff4a7702020-10-27 15:08:53 -070047 output keymgr_flash_t keymgr_o,
48
49 // Interrupts
50 output logic intr_prog_empty_o, // Program fifo is empty
51 output logic intr_prog_lvl_o, // Program fifo is empty
52 output logic intr_rd_full_o, // Read fifo is full
53 output logic intr_rd_lvl_o, // Read fifo is full
54 output logic intr_op_done_o, // Requested flash operation (wr/erase) done
55 output logic intr_op_error_o // Requested flash operation (wr/erase) done
56);
57
58 import flash_ctrl_reg_pkg::*;
59
60 flash_ctrl_reg2hw_t reg2hw;
61 flash_ctrl_hw2reg_t hw2reg;
62
63 tlul_pkg::tl_h2d_t tl_fifo_h2d [2];
64 tlul_pkg::tl_d2h_t tl_fifo_d2h [2];
65
66 // Register module
67 flash_ctrl_reg_top u_reg (
68 .clk_i,
69 .rst_ni,
70
71 .tl_i,
72 .tl_o,
73
74 .tl_win_o (tl_fifo_h2d),
75 .tl_win_i (tl_fifo_d2h),
76
77 .reg2hw,
78 .hw2reg,
79
80 .devmode_i (1'b1)
81 );
82
83 // FIFO Connections
84 logic prog_fifo_wvalid;
85 logic prog_fifo_wready;
86 logic prog_fifo_rvalid;
87 logic prog_fifo_ren;
88 logic [BusWidth-1:0] prog_fifo_wdata;
89 logic [BusWidth-1:0] prog_fifo_rdata;
90 logic [FifoDepthW-1:0] prog_fifo_depth;
91 logic rd_fifo_wready;
92 logic rd_fifo_rvalid;
93 logic rd_fifo_rready;
94 logic rd_fifo_wen;
95 logic rd_fifo_ren;
96 logic [BusWidth-1:0] rd_fifo_wdata;
97 logic [BusWidth-1:0] rd_fifo_rdata;
98 logic [FifoDepthW-1:0] rd_fifo_depth;
99
100 // Program Control Connections
101 logic prog_flash_req;
102 logic prog_flash_ovfl;
103 logic [BusAddrW-1:0] prog_flash_addr;
104 logic prog_op_valid;
105
106 // Read Control Connections
107 logic rd_flash_req;
108 logic rd_flash_ovfl;
109 logic [BusAddrW-1:0] rd_flash_addr;
110
111 // Erase Control Connections
112 logic erase_flash_req;
113 logic [BusAddrW-1:0] erase_flash_addr;
114 flash_erase_e erase_flash_type;
115
116 // Done / Error signaling from ctrl modules
117 logic prog_done, rd_done, erase_done;
118 logic prog_err, rd_err, erase_err;
119
Timothy Chend5323562020-12-02 16:10:44 -0800120 // Flash Memory Properties Connections
Timothy Chenff4a7702020-10-27 15:08:53 -0700121 logic [BusAddrW-1:0] flash_addr;
122 logic flash_req;
123 logic flash_rd_done, flash_prog_done, flash_erase_done;
124 logic flash_mp_error;
125 logic [BusWidth-1:0] flash_prog_data;
126 logic flash_prog_last;
127 flash_prog_e flash_prog_type;
128 logic [BusWidth-1:0] flash_rd_data;
129 logic flash_rd_err;
130 logic flash_phy_busy;
131 logic rd_op;
132 logic prog_op;
133 logic erase_op;
134 logic [AllPagesW-1:0] err_addr;
135 flash_lcmgr_phase_e phase;
136
137 // Flash control arbitration connections to hardware interface
Timothy Chenf52a4612020-12-04 20:37:49 -0800138 flash_key_t addr_key;
139 flash_key_t data_key;
Timothy Chenff4a7702020-10-27 15:08:53 -0700140 flash_ctrl_reg2hw_control_reg_t hw_ctrl;
141 logic hw_req;
142 logic [top_pkg::TL_AW-1:0] hw_addr;
143 logic hw_done;
144 logic hw_err;
145 logic hw_rvalid;
146 logic hw_rready;
147 flash_sel_e if_sel;
148 logic sw_sel;
149 flash_lcmgr_phase_e hw_phase;
150 logic creator_seed_priv;
151 logic owner_seed_priv;
152
153 // Flash control arbitration connections to software interface
154 logic sw_ctrl_done;
155 logic sw_ctrl_err;
156
157 // Flash control muxed connections
158 flash_ctrl_reg2hw_control_reg_t muxed_ctrl;
159 logic [top_pkg::TL_AW-1:0] muxed_addr;
160 logic op_start;
161 logic [11:0] op_num_words;
162 logic [BusAddrW-1:0] op_addr;
163 flash_op_e op_type;
164 flash_part_e op_part;
165 logic [InfoTypesWidth-1:0] op_info_sel;
166 flash_erase_e op_erase_type;
167 flash_prog_e op_prog_type;
168
169 logic ctrl_init_busy;
170 logic fifo_clr;
171
172 // software tlul to flash control aribration
173 logic sw_rvalid;
174 logic adapter_rvalid;
175 logic sw_wvalid;
176 logic sw_wen;
177 logic sw_wready;
178
179 // lfsr for local entropy usage
180 logic [31:0] rand_val;
181 logic lfsr_en;
182
Timothy Chen8ea1b412020-11-18 18:32:08 -0800183 // life cycle connections
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800184 lc_ctrl_pkg::lc_tx_t lc_creator_seed_sw_rw_en;
185 lc_ctrl_pkg::lc_tx_t lc_owner_seed_sw_rw_en;
186 lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_rd_en;
187 lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_wr_en;
188 lc_ctrl_pkg::lc_tx_t lc_seed_hw_rd_en;
Timothy Chen8ea1b412020-11-18 18:32:08 -0800189
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800190 // synchronize enables into local domain
Timothy Chen8d923152020-12-02 18:01:28 -0800191 prim_lc_sync #(
192 .NumCopies(1)
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800193 ) u_lc_creator_seed_sw_rw_en_sync (
Timothy Chen8d923152020-12-02 18:01:28 -0800194 .clk_i,
195 .rst_ni,
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800196 .lc_en_i(lc_creator_seed_sw_rw_en_i),
197 .lc_en_o(lc_creator_seed_sw_rw_en)
Timothy Chen8d923152020-12-02 18:01:28 -0800198 );
199
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800200 prim_lc_sync #(
201 .NumCopies(1)
202 ) u_lc_owner_seed_sw_rw_en_sync (
203 .clk_i,
204 .rst_ni,
205 .lc_en_i(lc_owner_seed_sw_rw_en_i),
206 .lc_en_o(lc_owner_seed_sw_rw_en)
207 );
208
209 prim_lc_sync #(
210 .NumCopies(1)
211 ) u_lc_iso_part_sw_rd_en_sync (
212 .clk_i,
213 .rst_ni,
214 .lc_en_i(lc_iso_part_sw_rd_en_i),
215 .lc_en_o(lc_iso_part_sw_rd_en)
216 );
217
218 prim_lc_sync #(
219 .NumCopies(1)
220 ) u_lc_iso_part_sw_wr_en_sync (
221 .clk_i,
222 .rst_ni,
223 .lc_en_i(lc_iso_part_sw_wr_en_i),
224 .lc_en_o(lc_iso_part_sw_wr_en)
225 );
226
227 prim_lc_sync #(
228 .NumCopies(1)
229 ) u_lc_seed_hw_rd_en_sync (
230 .clk_i,
231 .rst_ni,
232 .lc_en_i(lc_seed_hw_rd_en_i),
233 .lc_en_o(lc_seed_hw_rd_en)
234 );
Timothy Chen8d923152020-12-02 18:01:28 -0800235
Timothy Chenff4a7702020-10-27 15:08:53 -0700236 prim_lfsr #(
Timothy Chenaeffadc2020-12-11 15:03:07 -0800237 .EntropyDw(EdnWidth),
Timothy Chenf52a4612020-12-04 20:37:49 -0800238 .LfsrDw(LfsrWidth),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800239 .StateOutDw(LfsrWidth),
240 .DefaultSeed(RndCnstLfsrSeed),
241 .StatePermEn(1),
242 .StatePerm(RndCnstLfsrPerm)
Timothy Chenff4a7702020-10-27 15:08:53 -0700243 ) u_lfsr (
244 .clk_i,
245 .rst_ni,
Timothy Chenaeffadc2020-12-11 15:03:07 -0800246 .seed_en_i(edn_i.edn_ack),
247 .seed_i(edn_i.edn_bus),
Timothy Chenff4a7702020-10-27 15:08:53 -0700248 .lfsr_en_i(lfsr_en),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800249 .entropy_i('0),
Timothy Chenff4a7702020-10-27 15:08:53 -0700250 .state_o(rand_val)
251 );
252
253 // flash control arbitration between softawre / harware interfaces
254 flash_ctrl_arb u_ctrl_arb (
255 .clk_i,
256 .rst_ni,
257
258 // software interface to rd_ctrl / erase_ctrl
259 .sw_ctrl_i(reg2hw.control),
260 .sw_addr_i(reg2hw.addr.q),
261 .sw_ack_o(sw_ctrl_done),
262 .sw_err_o(sw_ctrl_err),
263
264 // software interface to rd_fifo
265 .sw_rvalid_o(sw_rvalid),
266 .sw_rready_i(adapter_rvalid),
267
268 // software interface to prog_fifo
269 .sw_wvalid_i(sw_wvalid & sw_wen),
270 .sw_wready_o(sw_wready),
271
272 // hardware interface to rd_ctrl / erase_ctrl
273 .hw_req_i(hw_req),
274 .hw_ctrl_i(hw_ctrl),
275
276 // hardware interface indicating operation phase
277 .hw_phase_i(hw_phase),
278
279 // hardware works on word address, however software expects byte address
280 .hw_addr_i(hw_addr),
281 .hw_ack_o(hw_done),
282 .hw_err_o(hw_err),
283
284 // hardware interface to rd_fifo
285 .hw_rvalid_o(hw_rvalid),
286 .hw_rready_i(hw_rready),
287
288 // hardware interface does not talk to prog_fifo
289
290 // muxed interface to rd_ctrl / erase_ctrl
291 .muxed_ctrl_o(muxed_ctrl),
292 .muxed_addr_o(muxed_addr),
293 .prog_ack_i(prog_done),
294 .prog_err_i(prog_err),
295 .rd_ack_i(rd_done),
296 .rd_err_i(rd_err),
297 .erase_ack_i(erase_done),
298 .erase_err_i(erase_err),
299
300 // muxed interface to rd_fifo
301 .rd_fifo_rvalid_i(rd_fifo_rvalid),
302 .rd_fifo_rready_o(rd_fifo_rready),
303
304 // muxed interface to prog_fifo
305 .prog_fifo_wvalid_o(prog_fifo_wvalid),
306 .prog_fifo_wready_i(prog_fifo_wready),
307
308 // flash phy initilization ongoing
309 .flash_phy_busy_i(flash_phy_busy),
310
311 // clear fifos
312 .fifo_clr_o(fifo_clr),
313
314 // phase indication
315 .phase_o(phase),
316
317 // indication that sw has been selected
Timothy Chenaeffadc2020-12-11 15:03:07 -0800318 .sel_o(if_sel)
Timothy Chenff4a7702020-10-27 15:08:53 -0700319 );
320
321 assign op_start = muxed_ctrl.start.q;
322 assign op_num_words = muxed_ctrl.num.q;
323 assign op_erase_type = flash_erase_e'(muxed_ctrl.erase_sel.q);
324 assign op_prog_type = flash_prog_e'(muxed_ctrl.prog_sel.q);
325 assign op_addr = muxed_addr[BusByteWidth +: BusAddrW];
326 assign op_type = flash_op_e'(muxed_ctrl.op.q);
327 assign op_part = flash_part_e'(muxed_ctrl.partition_sel.q);
328 assign op_info_sel = muxed_ctrl.info_sel.q;
329 assign rd_op = op_type == FlashOpRead;
330 assign prog_op = op_type == FlashOpProgram;
331 assign erase_op = op_type == FlashOpErase;
332 assign sw_sel = if_sel == SwSel;
333
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800334 // software privilege to creator seed
335 assign creator_seed_priv = lc_creator_seed_sw_rw_en == lc_ctrl_pkg::On;
336
337 // software privilege to owner seed
338 assign owner_seed_priv = lc_owner_seed_sw_rw_en == lc_ctrl_pkg::On;
339
Timothy Chenff4a7702020-10-27 15:08:53 -0700340 // hardware interface
Timothy Chenf52a4612020-12-04 20:37:49 -0800341 flash_ctrl_lcmgr #(
342 .RndCnstAddrKey(RndCnstAddrKey),
343 .RndCnstDataKey(RndCnstDataKey)
344 ) u_flash_hw_if (
Timothy Chenff4a7702020-10-27 15:08:53 -0700345 .clk_i,
346 .rst_ni,
Timothy Chenf52a4612020-12-04 20:37:49 -0800347 .clk_otp_i,
348 .rst_otp_ni,
Timothy Chenff4a7702020-10-27 15:08:53 -0700349
350 .init_i(pwrmgr_i.flash_init),
351 .init_done_o(pwrmgr_o.flash_done),
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800352 .provision_en_i(lc_seed_hw_rd_en == lc_ctrl_pkg::On),
Timothy Chenff4a7702020-10-27 15:08:53 -0700353
354 // interface to ctrl arb control ports
355 .ctrl_o(hw_ctrl),
356 .req_o(hw_req),
357 .addr_o(hw_addr),
358 .done_i(hw_done),
359 .err_i(hw_err),
360
361 // interface to ctrl_arb data ports
362 .rready_o(hw_rready),
363 .rvalid_i(hw_rvalid),
364
365 // direct form rd_fifo
366 .rdata_i(rd_fifo_rdata),
367
368 // external rma request
369 .rma_i(lc_i.rma_req),
370 .rma_token_i(lc_i.rma_req_token),
371 .rma_token_o(lc_o.rma_ack_token),
372 .rma_rsp_o(lc_o.rma_ack),
373
Timothy Chenff4a7702020-10-27 15:08:53 -0700374 // outgoing seeds
375 .seeds_o(keymgr_o.seeds),
376 .seed_err_o(), // TBD hook-up to Err code register
377
378 // phase indication
379 .phase_o(hw_phase),
380
Timothy Chen6b241b32020-11-13 15:15:45 -0800381 // phy read buffer enable
382 .rd_buf_en_o(flash_o.rd_buf_en),
383
Timothy Chenf52a4612020-12-04 20:37:49 -0800384 // connection to otp
385 .otp_key_req_o(otp_o),
386 .otp_key_rsp_i(otp_i),
387 .addr_key_o(addr_key),
388 .data_key_o(data_key),
389
Timothy Chenaeffadc2020-12-11 15:03:07 -0800390 // entropy interface
391 .edn_req_o(edn_o.edn_req),
392 .edn_ack_i(edn_i.edn_ack),
393 .lfsr_en_o(lfsr_en),
394 .rand_i(rand_val),
395
Timothy Chenff4a7702020-10-27 15:08:53 -0700396 // init ongoing
397 .init_busy_o(ctrl_init_busy)
398 );
399
Timothy Chenaeffadc2020-12-11 15:03:07 -0800400 logic unused_edn_fips;
401 assign unused_edn_fips = edn_i.edn_fips;
402
Timothy Chenff4a7702020-10-27 15:08:53 -0700403 // Program FIFO
404 // Since the program and read FIFOs are never used at the same time, it should really be one
405 // FIFO with muxed inputs and outputs. This should be addressed once the flash integration
406 // strategy has been identified
407 assign prog_op_valid = op_start & prog_op;
408
409 tlul_adapter_sram #(
410 .SramAw(1), //address unused
411 .SramDw(BusWidth),
412 .ByteAccess(0), //flash may not support byte access
413 .ErrOnRead(1) //reads not supported
414 ) u_to_prog_fifo (
415 .clk_i,
416 .rst_ni,
417 .tl_i (tl_fifo_h2d[0]),
418 .tl_o (tl_fifo_d2h[0]),
419 .req_o (sw_wvalid),
420 .gnt_i (sw_wready),
421 .we_o (sw_wen),
422 .addr_o (),
423 .wmask_o (),
424 .wdata_o (prog_fifo_wdata),
425 .rdata_i (BusWidth'(0)),
426 .rvalid_i (1'b0),
427 .rerror_i (2'b0)
428 );
429
430 prim_fifo_sync #(
431 .Width(BusWidth),
432 .Depth(FifoDepth)
433 ) u_prog_fifo (
434 .clk_i,
435 .rst_ni,
436 .clr_i (reg2hw.fifo_rst.q | fifo_clr),
437 .wvalid_i(prog_fifo_wvalid & prog_op_valid),
438 .wready_o(prog_fifo_wready),
439 .wdata_i (prog_fifo_wdata),
440 .depth_o (prog_fifo_depth),
441 .rvalid_o(prog_fifo_rvalid),
442 .rready_i(prog_fifo_ren),
443 .rdata_o (prog_fifo_rdata)
444 );
445
446 // Program handler is consumer of prog_fifo
Timothy Chenf52a4612020-12-04 20:37:49 -0800447 logic [1:0] prog_type_en;
448 assign prog_type_en[FlashProgNormal] = flash_i.prog_type_avail[FlashProgNormal] &
449 reg2hw.prog_type_en.normal.q;
450 assign prog_type_en[FlashProgRepair] = flash_i.prog_type_avail[FlashProgRepair] &
451 reg2hw.prog_type_en.repair.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700452 flash_ctrl_prog u_flash_ctrl_prog (
453 .clk_i,
454 .rst_ni,
455
456 // Control interface
457 .op_start_i (prog_op_valid),
458 .op_num_words_i (op_num_words),
459 .op_done_o (prog_done),
460 .op_err_o (prog_err),
461 .op_addr_i (op_addr),
462 .op_type_i (op_prog_type),
Timothy Chenf52a4612020-12-04 20:37:49 -0800463 .type_avail_i (prog_type_en),
Timothy Chenff4a7702020-10-27 15:08:53 -0700464
465 // FIFO Interface
466 .data_i (prog_fifo_rdata),
467 .data_rdy_i (prog_fifo_rvalid),
468 .data_rd_o (prog_fifo_ren),
469
470 // Flash Macro Interface
471 .flash_req_o (prog_flash_req),
472 .flash_addr_o (prog_flash_addr),
473 .flash_ovfl_o (prog_flash_ovfl),
474 .flash_data_o (flash_prog_data),
475 .flash_last_o (flash_prog_last),
476 .flash_type_o (flash_prog_type),
477 .flash_done_i (flash_prog_done),
478 .flash_error_i (flash_mp_error)
479 );
480
481 always_ff @(posedge clk_i or negedge rst_ni) begin
482 if (!rst_ni) begin
483 adapter_rvalid <= 1'b0;
484 end else begin
485 adapter_rvalid <= rd_fifo_ren && sw_rvalid;
486 end
487 end
488
489 // tlul adapter represents software's access interface to flash
490 tlul_adapter_sram #(
491 .SramAw(1), //address unused
492 .SramDw(BusWidth),
493 .ByteAccess(0), //flash may not support byte access
494 .ErrOnWrite(1) //writes not supported
495 ) u_to_rd_fifo (
496 .clk_i,
497 .rst_ni,
498 .tl_i (tl_fifo_h2d[1]),
499 .tl_o (tl_fifo_d2h[1]),
500 .req_o (rd_fifo_ren),
501 .gnt_i (rd_fifo_rvalid),
502 .we_o (),
503 .addr_o (),
504 .wmask_o (),
505 .wdata_o (),
506 .rdata_i (rd_fifo_rdata),
507 .rvalid_i (adapter_rvalid),
508 .rerror_i (2'b0)
509 );
510
511 prim_fifo_sync #(
512 .Width(BusWidth),
513 .Depth(FifoDepth)
514 ) u_rd_fifo (
515 .clk_i,
516 .rst_ni,
517 .clr_i (reg2hw.fifo_rst.q | fifo_clr),
518 .wvalid_i(rd_fifo_wen),
519 .wready_o(rd_fifo_wready),
520 .wdata_i (rd_fifo_wdata),
521 .depth_o (rd_fifo_depth),
522 .rvalid_o(rd_fifo_rvalid),
523 .rready_i(rd_fifo_rready),
524 .rdata_o (rd_fifo_rdata)
525 );
526
527 // Read handler is consumer of rd_fifo
528 flash_ctrl_rd u_flash_ctrl_rd (
529 .clk_i,
530 .rst_ni,
531
532 // To arbiter Interface
533 .op_start_i (op_start & rd_op),
534 .op_num_words_i (op_num_words),
535 .op_done_o (rd_done),
536 .op_err_o (rd_err),
537 .op_addr_i (op_addr),
538
539 // FIFO Interface
540 .data_rdy_i (rd_fifo_wready),
541 .data_o (rd_fifo_wdata),
542 .data_wr_o (rd_fifo_wen),
543
544 // Flash Macro Interface
545 .flash_req_o (rd_flash_req),
546 .flash_addr_o (rd_flash_addr),
547 .flash_ovfl_o (rd_flash_ovfl),
548 .flash_data_i (flash_rd_data),
549 .flash_done_i (flash_rd_done),
550 .flash_error_i (flash_mp_error | flash_rd_err)
551 );
552
553 // Erase handler does not consume fifo
554 flash_ctrl_erase u_flash_ctrl_erase (
555 // Software Interface
556 .op_start_i (op_start & erase_op),
557 .op_type_i (op_erase_type),
558 .op_done_o (erase_done),
559 .op_err_o (erase_err),
560 .op_addr_i (op_addr),
561
562 // Flash Macro Interface
563 .flash_req_o (erase_flash_req),
564 .flash_addr_o (erase_flash_addr),
565 .flash_op_o (erase_flash_type),
566 .flash_done_i (flash_erase_done),
567 .flash_error_i (flash_mp_error)
568 );
569
570 // Final muxing to flash macro module
571 always_comb begin
572 unique case (op_type)
573 FlashOpRead: begin
574 flash_req = rd_flash_req;
575 flash_addr = rd_flash_addr;
576 end
577 FlashOpProgram: begin
578 flash_req = prog_flash_req;
579 flash_addr = prog_flash_addr;
580 end
581 FlashOpErase: begin
582 flash_req = erase_flash_req;
583 flash_addr = erase_flash_addr;
584 end
585 default: begin
586 flash_req = 1'b0;
587 flash_addr = '0;
588 end
589 endcase // unique case (op_type)
590 end
591
592 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800593 // Data partition properties configuration
Timothy Chenff4a7702020-10-27 15:08:53 -0700594 //////////////////////////////////////
595 // extra region is the default region
596 mp_region_cfg_t [MpRegions:0] region_cfgs;
597 assign region_cfgs[MpRegions-1:0] = reg2hw.mp_region_cfg[MpRegions-1:0];
598
599 //default region
600 assign region_cfgs[MpRegions].base.q = '0;
601 assign region_cfgs[MpRegions].size.q = NumBanks * PagesPerBank;
602 assign region_cfgs[MpRegions].en.q = 1'b1;
603 assign region_cfgs[MpRegions].rd_en.q = reg2hw.default_region.rd_en.q;
604 assign region_cfgs[MpRegions].prog_en.q = reg2hw.default_region.prog_en.q;
605 assign region_cfgs[MpRegions].erase_en.q = reg2hw.default_region.erase_en.q;
606 assign region_cfgs[MpRegions].scramble_en.q = reg2hw.default_region.scramble_en.q;
Timothy Chena2db9332020-11-13 18:47:54 -0800607 assign region_cfgs[MpRegions].ecc_en.q = reg2hw.default_region.ecc_en.q;
Timothy Chend5323562020-12-02 16:10:44 -0800608 assign region_cfgs[MpRegions].he_en.q = reg2hw.default_region.he_en.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700609
610 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800611 // Info partition properties configuration
Timothy Chenff4a7702020-10-27 15:08:53 -0700612 //////////////////////////////////////
613 info_page_cfg_t [NumBanks-1:0][InfoTypes-1:0][InfosPerBank-1:0] reg2hw_info_page_cfgs;
614 info_page_cfg_t [NumBanks-1:0][InfoTypes-1:0][InfosPerBank-1:0] info_page_cfgs;
615
616 // transform from reg output to structure
617 % for bank in range(cfg['banks']):
618 % for idx in range(cfg['info_types']):
619 assign reg2hw_info_page_cfgs[${bank}][${idx}] = reg2hw.bank${bank}_info${idx}_page_cfg;
620 % endfor
621 % endfor
622
623 // qualify reg2hw settings with creator / owner privileges
624 for(genvar i = 0; i < NumBanks; i++) begin : gen_info_priv_bank
625 for (genvar j = 0; j < InfoTypes; j++) begin : gen_info_priv_type
626 flash_ctrl_info_cfg # (
627 .Bank(i),
628 .InfoSel(j)
629 ) u_info_cfg (
630 .cfgs_i(reg2hw_info_page_cfgs[i][j]),
631 .creator_seed_priv_i(creator_seed_priv),
632 .owner_seed_priv_i(owner_seed_priv),
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800633 .iso_flash_wr_en_i(lc_iso_part_sw_wr_en == lc_ctrl_pkg::On),
634 .iso_flash_rd_en_i(lc_iso_part_sw_rd_en == lc_ctrl_pkg::On),
Timothy Chenff4a7702020-10-27 15:08:53 -0700635 .cfgs_o(info_page_cfgs[i][j])
636 );
637 end
638 end
639
640 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800641 // flash memory properties
Timothy Chenff4a7702020-10-27 15:08:53 -0700642 //////////////////////////////////////
643 // direct assignment since prog/rd/erase_ctrl do not make use of op_part
644 flash_part_e flash_part_sel;
645 logic [InfoTypesWidth-1:0] flash_info_sel;
646 assign flash_part_sel = op_part;
647 assign flash_info_sel = op_info_sel;
648
Timothy Chen7d051eb2020-12-11 14:06:43 -0800649 // tie off hardware clear path
650 assign hw2reg.erase_suspend.d = 1'b0;
651
Timothy Chend5323562020-12-02 16:10:44 -0800652 // Flash memory Properties
653 // Memory property is page based and thus should use phy addressing
Timothy Chenff4a7702020-10-27 15:08:53 -0700654 // This should move to flash_phy long term
655 flash_mp u_flash_mp (
656 .clk_i,
657 .rst_ni,
658
659 // arbiter interface selection
660 .if_sel_i(if_sel),
661
662 // sw configuration for data partition
663 .region_cfgs_i(region_cfgs),
664 .bank_cfgs_i(reg2hw.mp_bank_cfg),
665
666 // sw configuration for info partition
667 .info_page_cfgs_i(info_page_cfgs),
668
669 // read / prog / erase controls
670 .req_i(flash_req),
671 .phase_i(phase),
672 .req_addr_i(flash_addr[BusAddrW-1 -: AllPagesW]),
673 .req_part_i(flash_part_sel),
674 .info_sel_i(flash_info_sel),
675 .addr_ovfl_i(rd_flash_ovfl | prog_flash_ovfl),
676 .rd_i(rd_op),
677 .prog_i(prog_op),
678 .pg_erase_i(erase_op & (erase_flash_type == FlashErasePage)),
679 .bk_erase_i(erase_op & (erase_flash_type == FlashEraseBank)),
Timothy Chen7d051eb2020-12-11 14:06:43 -0800680 .erase_suspend_i(reg2hw.erase_suspend),
681 .erase_suspend_done_o(hw2reg.erase_suspend.de),
Timothy Chenff4a7702020-10-27 15:08:53 -0700682 .rd_done_o(flash_rd_done),
683 .prog_done_o(flash_prog_done),
684 .erase_done_o(flash_erase_done),
685 .error_o(flash_mp_error),
686 .err_addr_o(err_addr),
687
688 // flash phy interface
689 .req_o(flash_o.req),
690 .scramble_en_o(flash_o.scramble_en),
Timothy Chena2db9332020-11-13 18:47:54 -0800691 .ecc_en_o(flash_o.ecc_en),
Timothy Chend5323562020-12-02 16:10:44 -0800692 .he_en_o(flash_o.he_en),
Timothy Chenff4a7702020-10-27 15:08:53 -0700693 .rd_o(flash_o.rd),
694 .prog_o(flash_o.prog),
695 .pg_erase_o(flash_o.pg_erase),
696 .bk_erase_o(flash_o.bk_erase),
Timothy Chen7d051eb2020-12-11 14:06:43 -0800697 .erase_suspend_o(flash_o.erase_suspend),
698 .erase_suspend_done_i(flash_i.erase_suspend_done),
Timothy Chenff4a7702020-10-27 15:08:53 -0700699 .rd_done_i(flash_i.rd_done),
700 .prog_done_i(flash_i.prog_done),
701 .erase_done_i(flash_i.erase_done)
702 );
703
704
705 // software interface feedback
706 // most values (other than flash_phy_busy) should only update when software operations
707 // are actually selected
708 assign hw2reg.op_status.done.d = 1'b1;
709 assign hw2reg.op_status.done.de = sw_ctrl_done;
710 assign hw2reg.op_status.err.d = 1'b1;
711 assign hw2reg.op_status.err.de = sw_ctrl_err;
712 assign hw2reg.status.rd_full.d = ~rd_fifo_wready;
713 assign hw2reg.status.rd_full.de = sw_sel;
714 assign hw2reg.status.rd_empty.d = ~rd_fifo_rvalid;
715 assign hw2reg.status.rd_empty.de = sw_sel;
716 assign hw2reg.status.prog_full.d = ~prog_fifo_wready;
717 assign hw2reg.status.prog_full.de = sw_sel;
718 assign hw2reg.status.prog_empty.d = ~prog_fifo_rvalid;
719 assign hw2reg.status.prog_empty.de = sw_sel;
720 assign hw2reg.status.init_wip.d = flash_phy_busy | ctrl_init_busy;
721 assign hw2reg.status.init_wip.de = 1'b1;
722 assign hw2reg.status.error_addr.d = err_addr;
723 assign hw2reg.status.error_addr.de = sw_sel;
724 assign hw2reg.control.start.d = 1'b0;
725 assign hw2reg.control.start.de = sw_ctrl_done;
726 // if software operation selected, based on transaction start
727 // if software operation not selected, software is free to change contents
728 assign hw2reg.ctrl_regwen.d = sw_sel ? !op_start : 1'b1;
729
730 // phy status
731 assign hw2reg.phy_status.init_wip.d = flash_phy_busy;
732 assign hw2reg.phy_status.init_wip.de = 1'b1;
733 assign hw2reg.phy_status.prog_normal_avail.d = flash_i.prog_type_avail[FlashProgNormal];
734 assign hw2reg.phy_status.prog_normal_avail.de = 1'b1;
735 assign hw2reg.phy_status.prog_repair_avail.d = flash_i.prog_type_avail[FlashProgRepair];
736 assign hw2reg.phy_status.prog_repair_avail.de = 1'b1;
737
738 // Flash Interface
739 assign flash_o.addr = flash_addr;
740 assign flash_o.part = flash_part_sel;
Timothy Chena0a550a2020-12-03 13:11:03 -0800741 assign flash_o.info_sel = flash_info_sel;
Timothy Chenff4a7702020-10-27 15:08:53 -0700742 assign flash_o.prog_type = flash_prog_type;
743 assign flash_o.prog_data = flash_prog_data;
744 assign flash_o.prog_last = flash_prog_last;
745 assign flash_o.region_cfgs = region_cfgs;
Timothy Chenf52a4612020-12-04 20:37:49 -0800746 assign flash_o.addr_key = addr_key;
747 assign flash_o.data_key = data_key;
Timothy Chenff4a7702020-10-27 15:08:53 -0700748 assign flash_rd_err = flash_i.rd_err;
749 assign flash_rd_data = flash_i.rd_data;
750 assign flash_phy_busy = flash_i.init_busy;
751
752 // Interface to pwrmgr
753 // flash is not idle as long as there is a stateful operation ongoing
754 logic flash_idle_d;
755 assign flash_idle_d = ~(flash_o.req &
756 (flash_o.prog | flash_o.pg_erase | flash_o.bk_erase));
757
758 prim_flop #(
759 .Width(1),
760 .ResetValue(1'b1)
761 ) u_reg_idle (
762 .clk_i,
763 .rst_ni,
764 .d_i(flash_idle_d),
765 .q_o(pwrmgr_o.flash_idle)
766 );
767
768
769 // Interrupts
770 // Generate edge triggered signals for sources that are level
771 logic [3:0] intr_src;
772 logic [3:0] intr_src_q;
773 logic [3:0] intr_assert;
774
775 assign intr_src = { ~prog_fifo_rvalid,
776 reg2hw.fifo_lvl.prog.q == prog_fifo_depth,
777 ~rd_fifo_wready,
778 reg2hw.fifo_lvl.rd.q == rd_fifo_depth
779 };
780
781 always_ff @(posedge clk_i or negedge rst_ni) begin
782 if (!rst_ni) begin
783 intr_src_q <= 4'h8; //prog_fifo is empty by default
784 end else if (sw_sel) begin
785 intr_src_q <= intr_src;
786 end
787 end
788
789 assign intr_assert = ~intr_src_q & intr_src;
790
791
792 assign intr_prog_empty_o = reg2hw.intr_enable.prog_empty.q & reg2hw.intr_state.prog_empty.q;
793 assign intr_prog_lvl_o = reg2hw.intr_enable.prog_lvl.q & reg2hw.intr_state.prog_lvl.q;
794 assign intr_rd_full_o = reg2hw.intr_enable.rd_full.q & reg2hw.intr_state.rd_full.q;
795 assign intr_rd_lvl_o = reg2hw.intr_enable.rd_lvl.q & reg2hw.intr_state.rd_lvl.q;
796 assign intr_op_done_o = reg2hw.intr_enable.op_done.q & reg2hw.intr_state.op_done.q;
797 assign intr_op_error_o = reg2hw.intr_enable.op_error.q & reg2hw.intr_state.op_error.q;
798
799 assign hw2reg.intr_state.prog_empty.d = 1'b1;
800 assign hw2reg.intr_state.prog_empty.de = intr_assert[3] |
801 (reg2hw.intr_test.prog_empty.qe &
802 reg2hw.intr_test.prog_empty.q);
803
804 assign hw2reg.intr_state.prog_lvl.d = 1'b1;
805 assign hw2reg.intr_state.prog_lvl.de = intr_assert[2] |
806 (reg2hw.intr_test.prog_lvl.qe &
807 reg2hw.intr_test.prog_lvl.q);
808
809 assign hw2reg.intr_state.rd_full.d = 1'b1;
810 assign hw2reg.intr_state.rd_full.de = intr_assert[1] |
811 (reg2hw.intr_test.rd_full.qe &
812 reg2hw.intr_test.rd_full.q);
813
814 assign hw2reg.intr_state.rd_lvl.d = 1'b1;
815 assign hw2reg.intr_state.rd_lvl.de = intr_assert[0] |
816 (reg2hw.intr_test.rd_lvl.qe &
817 reg2hw.intr_test.rd_lvl.q);
818
819
820 assign hw2reg.intr_state.op_done.d = 1'b1;
821 assign hw2reg.intr_state.op_done.de = sw_ctrl_done |
822 (reg2hw.intr_test.op_done.qe &
823 reg2hw.intr_test.op_done.q);
824
825 assign hw2reg.intr_state.op_error.d = 1'b1;
826 assign hw2reg.intr_state.op_error.de = sw_ctrl_err |
827 (reg2hw.intr_test.op_error.qe &
828 reg2hw.intr_test.op_error.q);
829
830
831
832 // Unused bits
833 logic [BusByteWidth-1:0] unused_byte_sel;
834 logic [top_pkg::TL_AW-1-BusAddrW:0] unused_higher_addr_bits;
835 logic [top_pkg::TL_AW-1:0] unused_scratch;
836
837
838 // Unused signals
839 assign unused_byte_sel = muxed_addr[BusByteWidth-1:0];
840 assign unused_higher_addr_bits = muxed_addr[top_pkg::TL_AW-1:BusAddrW];
841 assign unused_scratch = reg2hw.scratch;
842
843
844 // Assertions
845 `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid )
846 `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready )
847 `ASSERT_KNOWN(FlashKnownO_A, {flash_o.req, flash_o.rd, flash_o.prog, flash_o.pg_erase,
848 flash_o.bk_erase})
849 `ASSERT_KNOWN_IF(FlashAddrKnown_A, flash_o.addr, flash_o.req)
850 `ASSERT_KNOWN_IF(FlashProgKnown_A, flash_o.prog_data, flash_o.prog & flash_o.req)
851 `ASSERT_KNOWN(IntrProgEmptyKnownO_A, intr_prog_empty_o)
852 `ASSERT_KNOWN(IntrProgLvlKnownO_A, intr_prog_lvl_o )
853 `ASSERT_KNOWN(IntrProgRdFullKnownO_A, intr_rd_full_o )
854 `ASSERT_KNOWN(IntrRdLvlKnownO_A, intr_rd_lvl_o )
855 `ASSERT_KNOWN(IntrOpDoneKnownO_A, intr_op_done_o )
856 `ASSERT_KNOWN(IntrOpErrorKnownO_A, intr_op_error_o )
857
858endmodule