blob: a7c3b9a0022f16b73bc70d5a93817cbeb0e28a9a [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 Chen16741102021-01-15 17:32:13 -080012 parameter logic AlertAsyncOn = 1'b1,
Timothy Chenaeffadc2020-12-11 15:03:07 -080013 parameter flash_key_t RndCnstAddrKey = RndCnstAddrKeyDefault,
14 parameter flash_key_t RndCnstDataKey = RndCnstDataKeyDefault,
15 parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
16 parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault
Timothy Chenf52a4612020-12-04 20:37:49 -080017) (
Timothy Chenff4a7702020-10-27 15:08:53 -070018 input clk_i,
19 input rst_ni,
20
Timothy Chenf52a4612020-12-04 20:37:49 -080021 input clk_otp_i,
22 input rst_otp_ni,
23
Timothy Chen8ea1b412020-11-18 18:32:08 -080024 // life cycle interface
Timothy Chen99f3e3a2020-12-09 18:30:19 -080025 input lc_ctrl_pkg::lc_tx_t lc_creator_seed_sw_rw_en_i,
26 input lc_ctrl_pkg::lc_tx_t lc_owner_seed_sw_rw_en_i,
27 input lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_rd_en_i,
28 input lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_wr_en_i,
29 input lc_ctrl_pkg::lc_tx_t lc_seed_hw_rd_en_i,
Timothy Chen8ea1b412020-11-18 18:32:08 -080030
Timothy Chenff4a7702020-10-27 15:08:53 -070031 // Bus Interface
32 input tlul_pkg::tl_h2d_t tl_i,
33 output tlul_pkg::tl_d2h_t tl_o,
34
35 // Flash Interface
36 input flash_rsp_t flash_i,
37 output flash_req_t flash_o,
38
39 // otp/lc/pwrmgr/keymgr Interface
Timothy Chenf52a4612020-12-04 20:37:49 -080040 output otp_ctrl_pkg::flash_otp_key_req_t otp_o,
41 input otp_ctrl_pkg::flash_otp_key_rsp_t otp_i,
Timothy Chend39402a2020-12-15 20:34:09 -080042 input lc_ctrl_pkg::lc_tx_t rma_req_i,
43 input lc_ctrl_pkg::lc_flash_rma_seed_t rma_seed_i,
44 output lc_ctrl_pkg::lc_tx_t rma_ack_o,
Timothy Chenff4a7702020-10-27 15:08:53 -070045 input pwrmgr_pkg::pwr_flash_req_t pwrmgr_i,
46 output pwrmgr_pkg::pwr_flash_rsp_t pwrmgr_o,
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
Timothy Chen16741102021-01-15 17:32:13 -080055
56 // Alerts
57 input prim_alert_pkg::alert_rx_t [flash_ctrl_reg_pkg::NumAlerts-1:0] alert_rx_i,
58 output prim_alert_pkg::alert_tx_t [flash_ctrl_reg_pkg::NumAlerts-1:0] alert_tx_o
59
60
Timothy Chenff4a7702020-10-27 15:08:53 -070061);
62
63 import flash_ctrl_reg_pkg::*;
64
65 flash_ctrl_reg2hw_t reg2hw;
66 flash_ctrl_hw2reg_t hw2reg;
67
Timothy Chen6e495182020-12-28 16:16:35 -080068 tlul_pkg::tl_h2d_t tl_win_h2d [3];
69 tlul_pkg::tl_d2h_t tl_win_d2h [3];
Timothy Chenff4a7702020-10-27 15:08:53 -070070
Timothy Chen6e495182020-12-28 16:16:35 -080071 assign tl_win_d2h[2] = flash_i.tl_flash_p2c;
Timothy Chenff4a7702020-10-27 15:08:53 -070072 // Register module
73 flash_ctrl_reg_top u_reg (
74 .clk_i,
75 .rst_ni,
76
77 .tl_i,
78 .tl_o,
79
Timothy Chen6e495182020-12-28 16:16:35 -080080 .tl_win_o (tl_win_h2d),
81 .tl_win_i (tl_win_d2h),
Timothy Chenff4a7702020-10-27 15:08:53 -070082
83 .reg2hw,
84 .hw2reg,
85
86 .devmode_i (1'b1)
87 );
88
89 // FIFO Connections
90 logic prog_fifo_wvalid;
91 logic prog_fifo_wready;
92 logic prog_fifo_rvalid;
93 logic prog_fifo_ren;
94 logic [BusWidth-1:0] prog_fifo_wdata;
95 logic [BusWidth-1:0] prog_fifo_rdata;
96 logic [FifoDepthW-1:0] prog_fifo_depth;
97 logic rd_fifo_wready;
98 logic rd_fifo_rvalid;
99 logic rd_fifo_rready;
100 logic rd_fifo_wen;
101 logic rd_fifo_ren;
102 logic [BusWidth-1:0] rd_fifo_wdata;
103 logic [BusWidth-1:0] rd_fifo_rdata;
104 logic [FifoDepthW-1:0] rd_fifo_depth;
Timothy Chen71d98f82020-12-17 17:17:25 -0800105 logic rd_fifo_full;
Timothy Chenff4a7702020-10-27 15:08:53 -0700106
107 // Program Control Connections
108 logic prog_flash_req;
109 logic prog_flash_ovfl;
110 logic [BusAddrW-1:0] prog_flash_addr;
111 logic prog_op_valid;
112
113 // Read Control Connections
114 logic rd_flash_req;
115 logic rd_flash_ovfl;
116 logic [BusAddrW-1:0] rd_flash_addr;
117
118 // Erase Control Connections
119 logic erase_flash_req;
120 logic [BusAddrW-1:0] erase_flash_addr;
121 flash_erase_e erase_flash_type;
122
123 // Done / Error signaling from ctrl modules
124 logic prog_done, rd_done, erase_done;
125 logic prog_err, rd_err, erase_err;
126
Timothy Chend5323562020-12-02 16:10:44 -0800127 // Flash Memory Properties Connections
Timothy Chenff4a7702020-10-27 15:08:53 -0700128 logic [BusAddrW-1:0] flash_addr;
129 logic flash_req;
130 logic flash_rd_done, flash_prog_done, flash_erase_done;
131 logic flash_mp_error;
132 logic [BusWidth-1:0] flash_prog_data;
133 logic flash_prog_last;
134 flash_prog_e flash_prog_type;
135 logic [BusWidth-1:0] flash_rd_data;
136 logic flash_rd_err;
137 logic flash_phy_busy;
138 logic rd_op;
139 logic prog_op;
140 logic erase_op;
141 logic [AllPagesW-1:0] err_addr;
142 flash_lcmgr_phase_e phase;
143
144 // Flash control arbitration connections to hardware interface
Timothy Chenf52a4612020-12-04 20:37:49 -0800145 flash_key_t addr_key;
146 flash_key_t data_key;
Timothy Chenff4a7702020-10-27 15:08:53 -0700147 flash_ctrl_reg2hw_control_reg_t hw_ctrl;
148 logic hw_req;
149 logic [top_pkg::TL_AW-1:0] hw_addr;
150 logic hw_done;
151 logic hw_err;
152 logic hw_rvalid;
153 logic hw_rready;
Timothy Chend39402a2020-12-15 20:34:09 -0800154 logic hw_wvalid;
155 logic [BusWidth-1:0] hw_wdata;
156 logic hw_wready;
Timothy Chenff4a7702020-10-27 15:08:53 -0700157 flash_sel_e if_sel;
158 logic sw_sel;
159 flash_lcmgr_phase_e hw_phase;
160 logic creator_seed_priv;
161 logic owner_seed_priv;
162
163 // Flash control arbitration connections to software interface
164 logic sw_ctrl_done;
165 logic sw_ctrl_err;
166
167 // Flash control muxed connections
168 flash_ctrl_reg2hw_control_reg_t muxed_ctrl;
169 logic [top_pkg::TL_AW-1:0] muxed_addr;
170 logic op_start;
171 logic [11:0] op_num_words;
172 logic [BusAddrW-1:0] op_addr;
173 flash_op_e op_type;
174 flash_part_e op_part;
175 logic [InfoTypesWidth-1:0] op_info_sel;
176 flash_erase_e op_erase_type;
177 flash_prog_e op_prog_type;
178
179 logic ctrl_init_busy;
180 logic fifo_clr;
181
182 // software tlul to flash control aribration
183 logic sw_rvalid;
184 logic adapter_rvalid;
185 logic sw_wvalid;
Timothy Chend39402a2020-12-15 20:34:09 -0800186 logic [BusWidth-1:0] sw_wdata;
Timothy Chenff4a7702020-10-27 15:08:53 -0700187 logic sw_wen;
188 logic sw_wready;
189
190 // lfsr for local entropy usage
191 logic [31:0] rand_val;
192 logic lfsr_en;
Timothy Chend39402a2020-12-15 20:34:09 -0800193 logic lfsr_seed_en;
Timothy Chenff4a7702020-10-27 15:08:53 -0700194
Timothy Chen8ea1b412020-11-18 18:32:08 -0800195 // life cycle connections
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800196 lc_ctrl_pkg::lc_tx_t lc_creator_seed_sw_rw_en;
197 lc_ctrl_pkg::lc_tx_t lc_owner_seed_sw_rw_en;
198 lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_rd_en;
199 lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_wr_en;
200 lc_ctrl_pkg::lc_tx_t lc_seed_hw_rd_en;
Timothy Chen8ea1b412020-11-18 18:32:08 -0800201
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800202 // synchronize enables into local domain
Timothy Chen8d923152020-12-02 18:01:28 -0800203 prim_lc_sync #(
204 .NumCopies(1)
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800205 ) u_lc_creator_seed_sw_rw_en_sync (
Timothy Chen8d923152020-12-02 18:01:28 -0800206 .clk_i,
207 .rst_ni,
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800208 .lc_en_i(lc_creator_seed_sw_rw_en_i),
209 .lc_en_o(lc_creator_seed_sw_rw_en)
Timothy Chen8d923152020-12-02 18:01:28 -0800210 );
211
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800212 prim_lc_sync #(
213 .NumCopies(1)
214 ) u_lc_owner_seed_sw_rw_en_sync (
215 .clk_i,
216 .rst_ni,
217 .lc_en_i(lc_owner_seed_sw_rw_en_i),
218 .lc_en_o(lc_owner_seed_sw_rw_en)
219 );
220
221 prim_lc_sync #(
222 .NumCopies(1)
223 ) u_lc_iso_part_sw_rd_en_sync (
224 .clk_i,
225 .rst_ni,
226 .lc_en_i(lc_iso_part_sw_rd_en_i),
227 .lc_en_o(lc_iso_part_sw_rd_en)
228 );
229
230 prim_lc_sync #(
231 .NumCopies(1)
232 ) u_lc_iso_part_sw_wr_en_sync (
233 .clk_i,
234 .rst_ni,
235 .lc_en_i(lc_iso_part_sw_wr_en_i),
236 .lc_en_o(lc_iso_part_sw_wr_en)
237 );
238
239 prim_lc_sync #(
240 .NumCopies(1)
241 ) u_lc_seed_hw_rd_en_sync (
242 .clk_i,
243 .rst_ni,
244 .lc_en_i(lc_seed_hw_rd_en_i),
245 .lc_en_o(lc_seed_hw_rd_en)
246 );
Timothy Chen8d923152020-12-02 18:01:28 -0800247
Timothy Chenff4a7702020-10-27 15:08:53 -0700248 prim_lfsr #(
Timothy Chenaeffadc2020-12-11 15:03:07 -0800249 .EntropyDw(EdnWidth),
Timothy Chenf52a4612020-12-04 20:37:49 -0800250 .LfsrDw(LfsrWidth),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800251 .StateOutDw(LfsrWidth),
252 .DefaultSeed(RndCnstLfsrSeed),
253 .StatePermEn(1),
254 .StatePerm(RndCnstLfsrPerm)
Timothy Chenff4a7702020-10-27 15:08:53 -0700255 ) u_lfsr (
256 .clk_i,
257 .rst_ni,
Timothy Chend39402a2020-12-15 20:34:09 -0800258 .seed_en_i(lfsr_seed_en),
259 .seed_i(rma_seed_i),
Timothy Chenff4a7702020-10-27 15:08:53 -0700260 .lfsr_en_i(lfsr_en),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800261 .entropy_i('0),
Timothy Chenff4a7702020-10-27 15:08:53 -0700262 .state_o(rand_val)
263 );
264
265 // flash control arbitration between softawre / harware interfaces
266 flash_ctrl_arb u_ctrl_arb (
267 .clk_i,
268 .rst_ni,
269
270 // software interface to rd_ctrl / erase_ctrl
271 .sw_ctrl_i(reg2hw.control),
272 .sw_addr_i(reg2hw.addr.q),
273 .sw_ack_o(sw_ctrl_done),
274 .sw_err_o(sw_ctrl_err),
275
276 // software interface to rd_fifo
277 .sw_rvalid_o(sw_rvalid),
278 .sw_rready_i(adapter_rvalid),
279
280 // software interface to prog_fifo
281 .sw_wvalid_i(sw_wvalid & sw_wen),
Timothy Chend39402a2020-12-15 20:34:09 -0800282 .sw_wdata_i(sw_wdata),
Timothy Chenff4a7702020-10-27 15:08:53 -0700283 .sw_wready_o(sw_wready),
284
285 // hardware interface to rd_ctrl / erase_ctrl
286 .hw_req_i(hw_req),
287 .hw_ctrl_i(hw_ctrl),
288
289 // hardware interface indicating operation phase
290 .hw_phase_i(hw_phase),
291
292 // hardware works on word address, however software expects byte address
293 .hw_addr_i(hw_addr),
294 .hw_ack_o(hw_done),
295 .hw_err_o(hw_err),
296
297 // hardware interface to rd_fifo
298 .hw_rvalid_o(hw_rvalid),
299 .hw_rready_i(hw_rready),
Timothy Chend39402a2020-12-15 20:34:09 -0800300 .hw_wvalid_i(hw_wvalid),
301 .hw_wdata_i(hw_wdata),
302 .hw_wready_o(hw_wready),
Timothy Chenff4a7702020-10-27 15:08:53 -0700303
304 // hardware interface does not talk to prog_fifo
305
306 // muxed interface to rd_ctrl / erase_ctrl
307 .muxed_ctrl_o(muxed_ctrl),
308 .muxed_addr_o(muxed_addr),
309 .prog_ack_i(prog_done),
310 .prog_err_i(prog_err),
311 .rd_ack_i(rd_done),
312 .rd_err_i(rd_err),
313 .erase_ack_i(erase_done),
314 .erase_err_i(erase_err),
315
316 // muxed interface to rd_fifo
317 .rd_fifo_rvalid_i(rd_fifo_rvalid),
318 .rd_fifo_rready_o(rd_fifo_rready),
319
320 // muxed interface to prog_fifo
321 .prog_fifo_wvalid_o(prog_fifo_wvalid),
Timothy Chend39402a2020-12-15 20:34:09 -0800322 .prog_fifo_wdata_o(prog_fifo_wdata),
Timothy Chenff4a7702020-10-27 15:08:53 -0700323 .prog_fifo_wready_i(prog_fifo_wready),
324
325 // flash phy initilization ongoing
326 .flash_phy_busy_i(flash_phy_busy),
327
328 // clear fifos
329 .fifo_clr_o(fifo_clr),
330
331 // phase indication
332 .phase_o(phase),
333
334 // indication that sw has been selected
Timothy Chenaeffadc2020-12-11 15:03:07 -0800335 .sel_o(if_sel)
Timothy Chenff4a7702020-10-27 15:08:53 -0700336 );
337
338 assign op_start = muxed_ctrl.start.q;
339 assign op_num_words = muxed_ctrl.num.q;
340 assign op_erase_type = flash_erase_e'(muxed_ctrl.erase_sel.q);
341 assign op_prog_type = flash_prog_e'(muxed_ctrl.prog_sel.q);
342 assign op_addr = muxed_addr[BusByteWidth +: BusAddrW];
343 assign op_type = flash_op_e'(muxed_ctrl.op.q);
344 assign op_part = flash_part_e'(muxed_ctrl.partition_sel.q);
345 assign op_info_sel = muxed_ctrl.info_sel.q;
346 assign rd_op = op_type == FlashOpRead;
347 assign prog_op = op_type == FlashOpProgram;
348 assign erase_op = op_type == FlashOpErase;
349 assign sw_sel = if_sel == SwSel;
350
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800351 // software privilege to creator seed
352 assign creator_seed_priv = lc_creator_seed_sw_rw_en == lc_ctrl_pkg::On;
353
354 // software privilege to owner seed
355 assign owner_seed_priv = lc_owner_seed_sw_rw_en == lc_ctrl_pkg::On;
356
Timothy Chenff4a7702020-10-27 15:08:53 -0700357 // hardware interface
Timothy Chenf52a4612020-12-04 20:37:49 -0800358 flash_ctrl_lcmgr #(
359 .RndCnstAddrKey(RndCnstAddrKey),
360 .RndCnstDataKey(RndCnstDataKey)
361 ) u_flash_hw_if (
Timothy Chenff4a7702020-10-27 15:08:53 -0700362 .clk_i,
363 .rst_ni,
Timothy Chenf52a4612020-12-04 20:37:49 -0800364 .clk_otp_i,
365 .rst_otp_ni,
Timothy Chenff4a7702020-10-27 15:08:53 -0700366
367 .init_i(pwrmgr_i.flash_init),
368 .init_done_o(pwrmgr_o.flash_done),
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800369 .provision_en_i(lc_seed_hw_rd_en == lc_ctrl_pkg::On),
Timothy Chenff4a7702020-10-27 15:08:53 -0700370
371 // interface to ctrl arb control ports
372 .ctrl_o(hw_ctrl),
373 .req_o(hw_req),
374 .addr_o(hw_addr),
375 .done_i(hw_done),
376 .err_i(hw_err),
377
378 // interface to ctrl_arb data ports
379 .rready_o(hw_rready),
380 .rvalid_i(hw_rvalid),
Timothy Chend39402a2020-12-15 20:34:09 -0800381 .wready_i(hw_wready),
382 .wvalid_o(hw_wvalid),
383 .wdata_o(hw_wdata),
Timothy Chenff4a7702020-10-27 15:08:53 -0700384
385 // direct form rd_fifo
386 .rdata_i(rd_fifo_rdata),
387
388 // external rma request
Timothy Chend39402a2020-12-15 20:34:09 -0800389 .rma_req_i,
390 .rma_ack_o,
Timothy Chenff4a7702020-10-27 15:08:53 -0700391
Timothy Chenff4a7702020-10-27 15:08:53 -0700392 // outgoing seeds
393 .seeds_o(keymgr_o.seeds),
394 .seed_err_o(), // TBD hook-up to Err code register
395
396 // phase indication
397 .phase_o(hw_phase),
398
Timothy Chen6b241b32020-11-13 15:15:45 -0800399 // phy read buffer enable
400 .rd_buf_en_o(flash_o.rd_buf_en),
401
Timothy Chenf52a4612020-12-04 20:37:49 -0800402 // connection to otp
403 .otp_key_req_o(otp_o),
404 .otp_key_rsp_i(otp_i),
405 .addr_key_o(addr_key),
406 .data_key_o(data_key),
407
Timothy Chenaeffadc2020-12-11 15:03:07 -0800408 // entropy interface
Timothy Chend39402a2020-12-15 20:34:09 -0800409 .edn_req_o(lfsr_seed_en),
410 .edn_ack_i(1'b1),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800411 .lfsr_en_o(lfsr_en),
412 .rand_i(rand_val),
413
Timothy Chenff4a7702020-10-27 15:08:53 -0700414 // init ongoing
415 .init_busy_o(ctrl_init_busy)
416 );
417
418 // Program FIFO
419 // Since the program and read FIFOs are never used at the same time, it should really be one
420 // FIFO with muxed inputs and outputs. This should be addressed once the flash integration
421 // strategy has been identified
422 assign prog_op_valid = op_start & prog_op;
423
424 tlul_adapter_sram #(
425 .SramAw(1), //address unused
426 .SramDw(BusWidth),
427 .ByteAccess(0), //flash may not support byte access
428 .ErrOnRead(1) //reads not supported
429 ) u_to_prog_fifo (
430 .clk_i,
431 .rst_ni,
Timothy Chen6e495182020-12-28 16:16:35 -0800432 .tl_i (tl_win_h2d[0]),
433 .tl_o (tl_win_d2h[0]),
Timothy Chenff4a7702020-10-27 15:08:53 -0700434 .req_o (sw_wvalid),
435 .gnt_i (sw_wready),
436 .we_o (sw_wen),
437 .addr_o (),
438 .wmask_o (),
Timothy Chend39402a2020-12-15 20:34:09 -0800439 .wdata_o (sw_wdata),
Timothy Chenff4a7702020-10-27 15:08:53 -0700440 .rdata_i (BusWidth'(0)),
441 .rvalid_i (1'b0),
442 .rerror_i (2'b0)
443 );
444
445 prim_fifo_sync #(
446 .Width(BusWidth),
447 .Depth(FifoDepth)
448 ) u_prog_fifo (
449 .clk_i,
450 .rst_ni,
451 .clr_i (reg2hw.fifo_rst.q | fifo_clr),
452 .wvalid_i(prog_fifo_wvalid & prog_op_valid),
453 .wready_o(prog_fifo_wready),
454 .wdata_i (prog_fifo_wdata),
455 .depth_o (prog_fifo_depth),
Philipp Wagner7858f3d2021-02-01 16:38:13 +0000456 .full_o (),
Timothy Chenff4a7702020-10-27 15:08:53 -0700457 .rvalid_o(prog_fifo_rvalid),
458 .rready_i(prog_fifo_ren),
459 .rdata_o (prog_fifo_rdata)
460 );
461
462 // Program handler is consumer of prog_fifo
Timothy Chenf52a4612020-12-04 20:37:49 -0800463 logic [1:0] prog_type_en;
464 assign prog_type_en[FlashProgNormal] = flash_i.prog_type_avail[FlashProgNormal] &
465 reg2hw.prog_type_en.normal.q;
466 assign prog_type_en[FlashProgRepair] = flash_i.prog_type_avail[FlashProgRepair] &
467 reg2hw.prog_type_en.repair.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700468 flash_ctrl_prog u_flash_ctrl_prog (
469 .clk_i,
470 .rst_ni,
471
472 // Control interface
473 .op_start_i (prog_op_valid),
474 .op_num_words_i (op_num_words),
475 .op_done_o (prog_done),
476 .op_err_o (prog_err),
477 .op_addr_i (op_addr),
478 .op_type_i (op_prog_type),
Timothy Chenf52a4612020-12-04 20:37:49 -0800479 .type_avail_i (prog_type_en),
Timothy Chenff4a7702020-10-27 15:08:53 -0700480
481 // FIFO Interface
482 .data_i (prog_fifo_rdata),
483 .data_rdy_i (prog_fifo_rvalid),
484 .data_rd_o (prog_fifo_ren),
485
486 // Flash Macro Interface
487 .flash_req_o (prog_flash_req),
488 .flash_addr_o (prog_flash_addr),
489 .flash_ovfl_o (prog_flash_ovfl),
490 .flash_data_o (flash_prog_data),
491 .flash_last_o (flash_prog_last),
492 .flash_type_o (flash_prog_type),
493 .flash_done_i (flash_prog_done),
494 .flash_error_i (flash_mp_error)
495 );
496
497 always_ff @(posedge clk_i or negedge rst_ni) begin
498 if (!rst_ni) begin
499 adapter_rvalid <= 1'b0;
500 end else begin
501 adapter_rvalid <= rd_fifo_ren && sw_rvalid;
502 end
503 end
504
505 // tlul adapter represents software's access interface to flash
506 tlul_adapter_sram #(
507 .SramAw(1), //address unused
508 .SramDw(BusWidth),
509 .ByteAccess(0), //flash may not support byte access
510 .ErrOnWrite(1) //writes not supported
511 ) u_to_rd_fifo (
512 .clk_i,
513 .rst_ni,
Timothy Chen6e495182020-12-28 16:16:35 -0800514 .tl_i (tl_win_h2d[1]),
515 .tl_o (tl_win_d2h[1]),
Timothy Chenff4a7702020-10-27 15:08:53 -0700516 .req_o (rd_fifo_ren),
517 .gnt_i (rd_fifo_rvalid),
518 .we_o (),
519 .addr_o (),
520 .wmask_o (),
521 .wdata_o (),
522 .rdata_i (rd_fifo_rdata),
523 .rvalid_i (adapter_rvalid),
524 .rerror_i (2'b0)
525 );
526
527 prim_fifo_sync #(
528 .Width(BusWidth),
529 .Depth(FifoDepth)
530 ) u_rd_fifo (
531 .clk_i,
532 .rst_ni,
533 .clr_i (reg2hw.fifo_rst.q | fifo_clr),
534 .wvalid_i(rd_fifo_wen),
535 .wready_o(rd_fifo_wready),
536 .wdata_i (rd_fifo_wdata),
Timothy Chen71d98f82020-12-17 17:17:25 -0800537 .full_o (rd_fifo_full),
Timothy Chenff4a7702020-10-27 15:08:53 -0700538 .depth_o (rd_fifo_depth),
539 .rvalid_o(rd_fifo_rvalid),
540 .rready_i(rd_fifo_rready),
541 .rdata_o (rd_fifo_rdata)
542 );
543
544 // Read handler is consumer of rd_fifo
545 flash_ctrl_rd u_flash_ctrl_rd (
546 .clk_i,
547 .rst_ni,
548
549 // To arbiter Interface
550 .op_start_i (op_start & rd_op),
551 .op_num_words_i (op_num_words),
552 .op_done_o (rd_done),
553 .op_err_o (rd_err),
554 .op_addr_i (op_addr),
555
556 // FIFO Interface
557 .data_rdy_i (rd_fifo_wready),
558 .data_o (rd_fifo_wdata),
559 .data_wr_o (rd_fifo_wen),
560
561 // Flash Macro Interface
562 .flash_req_o (rd_flash_req),
563 .flash_addr_o (rd_flash_addr),
564 .flash_ovfl_o (rd_flash_ovfl),
565 .flash_data_i (flash_rd_data),
566 .flash_done_i (flash_rd_done),
567 .flash_error_i (flash_mp_error | flash_rd_err)
568 );
569
570 // Erase handler does not consume fifo
571 flash_ctrl_erase u_flash_ctrl_erase (
572 // Software Interface
573 .op_start_i (op_start & erase_op),
574 .op_type_i (op_erase_type),
575 .op_done_o (erase_done),
576 .op_err_o (erase_err),
577 .op_addr_i (op_addr),
578
579 // Flash Macro Interface
580 .flash_req_o (erase_flash_req),
581 .flash_addr_o (erase_flash_addr),
582 .flash_op_o (erase_flash_type),
583 .flash_done_i (flash_erase_done),
584 .flash_error_i (flash_mp_error)
585 );
586
587 // Final muxing to flash macro module
588 always_comb begin
589 unique case (op_type)
590 FlashOpRead: begin
591 flash_req = rd_flash_req;
592 flash_addr = rd_flash_addr;
593 end
594 FlashOpProgram: begin
595 flash_req = prog_flash_req;
596 flash_addr = prog_flash_addr;
597 end
598 FlashOpErase: begin
599 flash_req = erase_flash_req;
600 flash_addr = erase_flash_addr;
601 end
602 default: begin
603 flash_req = 1'b0;
604 flash_addr = '0;
605 end
606 endcase // unique case (op_type)
607 end
608
609 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800610 // Data partition properties configuration
Timothy Chenff4a7702020-10-27 15:08:53 -0700611 //////////////////////////////////////
612 // extra region is the default region
613 mp_region_cfg_t [MpRegions:0] region_cfgs;
614 assign region_cfgs[MpRegions-1:0] = reg2hw.mp_region_cfg[MpRegions-1:0];
615
616 //default region
617 assign region_cfgs[MpRegions].base.q = '0;
618 assign region_cfgs[MpRegions].size.q = NumBanks * PagesPerBank;
619 assign region_cfgs[MpRegions].en.q = 1'b1;
620 assign region_cfgs[MpRegions].rd_en.q = reg2hw.default_region.rd_en.q;
621 assign region_cfgs[MpRegions].prog_en.q = reg2hw.default_region.prog_en.q;
622 assign region_cfgs[MpRegions].erase_en.q = reg2hw.default_region.erase_en.q;
623 assign region_cfgs[MpRegions].scramble_en.q = reg2hw.default_region.scramble_en.q;
Timothy Chena2db9332020-11-13 18:47:54 -0800624 assign region_cfgs[MpRegions].ecc_en.q = reg2hw.default_region.ecc_en.q;
Timothy Chend5323562020-12-02 16:10:44 -0800625 assign region_cfgs[MpRegions].he_en.q = reg2hw.default_region.he_en.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700626
627 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800628 // Info partition properties configuration
Timothy Chenff4a7702020-10-27 15:08:53 -0700629 //////////////////////////////////////
630 info_page_cfg_t [NumBanks-1:0][InfoTypes-1:0][InfosPerBank-1:0] reg2hw_info_page_cfgs;
631 info_page_cfg_t [NumBanks-1:0][InfoTypes-1:0][InfosPerBank-1:0] info_page_cfgs;
Timothy Chene97e0b82020-12-11 17:18:43 -0800632 localparam int InfoBits = $bits(info_page_cfg_t) * InfosPerBank;
Timothy Chenff4a7702020-10-27 15:08:53 -0700633
634 // transform from reg output to structure
Timothy Chene97e0b82020-12-11 17:18:43 -0800635 // Not all types have the maximum number of banks, so those are packed to 0
Timothy Chenff4a7702020-10-27 15:08:53 -0700636 % for bank in range(cfg['banks']):
637 % for idx in range(cfg['info_types']):
Timothy Chene97e0b82020-12-11 17:18:43 -0800638 assign reg2hw_info_page_cfgs[${bank}][${idx}] = InfoBits'(reg2hw.bank${bank}_info${idx}_page_cfg);
Timothy Chenff4a7702020-10-27 15:08:53 -0700639 % endfor
640 % endfor
641
642 // qualify reg2hw settings with creator / owner privileges
643 for(genvar i = 0; i < NumBanks; i++) begin : gen_info_priv_bank
644 for (genvar j = 0; j < InfoTypes; j++) begin : gen_info_priv_type
645 flash_ctrl_info_cfg # (
646 .Bank(i),
647 .InfoSel(j)
648 ) u_info_cfg (
649 .cfgs_i(reg2hw_info_page_cfgs[i][j]),
650 .creator_seed_priv_i(creator_seed_priv),
651 .owner_seed_priv_i(owner_seed_priv),
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800652 .iso_flash_wr_en_i(lc_iso_part_sw_wr_en == lc_ctrl_pkg::On),
653 .iso_flash_rd_en_i(lc_iso_part_sw_rd_en == lc_ctrl_pkg::On),
Timothy Chenff4a7702020-10-27 15:08:53 -0700654 .cfgs_o(info_page_cfgs[i][j])
655 );
656 end
657 end
658
659 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800660 // flash memory properties
Timothy Chenff4a7702020-10-27 15:08:53 -0700661 //////////////////////////////////////
662 // direct assignment since prog/rd/erase_ctrl do not make use of op_part
663 flash_part_e flash_part_sel;
664 logic [InfoTypesWidth-1:0] flash_info_sel;
665 assign flash_part_sel = op_part;
666 assign flash_info_sel = op_info_sel;
667
Timothy Chen7d051eb2020-12-11 14:06:43 -0800668 // tie off hardware clear path
669 assign hw2reg.erase_suspend.d = 1'b0;
670
Timothy Chend5323562020-12-02 16:10:44 -0800671 // Flash memory Properties
672 // Memory property is page based and thus should use phy addressing
Timothy Chenff4a7702020-10-27 15:08:53 -0700673 // This should move to flash_phy long term
674 flash_mp u_flash_mp (
675 .clk_i,
676 .rst_ni,
677
678 // arbiter interface selection
679 .if_sel_i(if_sel),
680
681 // sw configuration for data partition
682 .region_cfgs_i(region_cfgs),
683 .bank_cfgs_i(reg2hw.mp_bank_cfg),
684
685 // sw configuration for info partition
686 .info_page_cfgs_i(info_page_cfgs),
687
688 // read / prog / erase controls
689 .req_i(flash_req),
690 .phase_i(phase),
691 .req_addr_i(flash_addr[BusAddrW-1 -: AllPagesW]),
692 .req_part_i(flash_part_sel),
693 .info_sel_i(flash_info_sel),
694 .addr_ovfl_i(rd_flash_ovfl | prog_flash_ovfl),
695 .rd_i(rd_op),
696 .prog_i(prog_op),
697 .pg_erase_i(erase_op & (erase_flash_type == FlashErasePage)),
698 .bk_erase_i(erase_op & (erase_flash_type == FlashEraseBank)),
Timothy Chen7d051eb2020-12-11 14:06:43 -0800699 .erase_suspend_i(reg2hw.erase_suspend),
700 .erase_suspend_done_o(hw2reg.erase_suspend.de),
Timothy Chenff4a7702020-10-27 15:08:53 -0700701 .rd_done_o(flash_rd_done),
702 .prog_done_o(flash_prog_done),
703 .erase_done_o(flash_erase_done),
704 .error_o(flash_mp_error),
705 .err_addr_o(err_addr),
706
707 // flash phy interface
708 .req_o(flash_o.req),
709 .scramble_en_o(flash_o.scramble_en),
Timothy Chena2db9332020-11-13 18:47:54 -0800710 .ecc_en_o(flash_o.ecc_en),
Timothy Chend5323562020-12-02 16:10:44 -0800711 .he_en_o(flash_o.he_en),
Timothy Chenff4a7702020-10-27 15:08:53 -0700712 .rd_o(flash_o.rd),
713 .prog_o(flash_o.prog),
714 .pg_erase_o(flash_o.pg_erase),
715 .bk_erase_o(flash_o.bk_erase),
Timothy Chen7d051eb2020-12-11 14:06:43 -0800716 .erase_suspend_o(flash_o.erase_suspend),
Timothy Chenff4a7702020-10-27 15:08:53 -0700717 .rd_done_i(flash_i.rd_done),
718 .prog_done_i(flash_i.prog_done),
719 .erase_done_i(flash_i.erase_done)
720 );
721
722
723 // software interface feedback
724 // most values (other than flash_phy_busy) should only update when software operations
725 // are actually selected
726 assign hw2reg.op_status.done.d = 1'b1;
727 assign hw2reg.op_status.done.de = sw_ctrl_done;
728 assign hw2reg.op_status.err.d = 1'b1;
729 assign hw2reg.op_status.err.de = sw_ctrl_err;
Timothy Chen71d98f82020-12-17 17:17:25 -0800730 assign hw2reg.status.rd_full.d = rd_fifo_full;
Timothy Chenff4a7702020-10-27 15:08:53 -0700731 assign hw2reg.status.rd_full.de = sw_sel;
732 assign hw2reg.status.rd_empty.d = ~rd_fifo_rvalid;
733 assign hw2reg.status.rd_empty.de = sw_sel;
734 assign hw2reg.status.prog_full.d = ~prog_fifo_wready;
735 assign hw2reg.status.prog_full.de = sw_sel;
736 assign hw2reg.status.prog_empty.d = ~prog_fifo_rvalid;
737 assign hw2reg.status.prog_empty.de = sw_sel;
738 assign hw2reg.status.init_wip.d = flash_phy_busy | ctrl_init_busy;
739 assign hw2reg.status.init_wip.de = 1'b1;
Timothy Chenff4a7702020-10-27 15:08:53 -0700740 assign hw2reg.control.start.d = 1'b0;
741 assign hw2reg.control.start.de = sw_ctrl_done;
742 // if software operation selected, based on transaction start
743 // if software operation not selected, software is free to change contents
744 assign hw2reg.ctrl_regwen.d = sw_sel ? !op_start : 1'b1;
745
746 // phy status
747 assign hw2reg.phy_status.init_wip.d = flash_phy_busy;
748 assign hw2reg.phy_status.init_wip.de = 1'b1;
749 assign hw2reg.phy_status.prog_normal_avail.d = flash_i.prog_type_avail[FlashProgNormal];
750 assign hw2reg.phy_status.prog_normal_avail.de = 1'b1;
751 assign hw2reg.phy_status.prog_repair_avail.d = flash_i.prog_type_avail[FlashProgRepair];
752 assign hw2reg.phy_status.prog_repair_avail.de = 1'b1;
753
754 // Flash Interface
755 assign flash_o.addr = flash_addr;
756 assign flash_o.part = flash_part_sel;
Timothy Chena0a550a2020-12-03 13:11:03 -0800757 assign flash_o.info_sel = flash_info_sel;
Timothy Chenff4a7702020-10-27 15:08:53 -0700758 assign flash_o.prog_type = flash_prog_type;
759 assign flash_o.prog_data = flash_prog_data;
760 assign flash_o.prog_last = flash_prog_last;
761 assign flash_o.region_cfgs = region_cfgs;
Timothy Chenf52a4612020-12-04 20:37:49 -0800762 assign flash_o.addr_key = addr_key;
763 assign flash_o.data_key = data_key;
Timothy Chen6e495182020-12-28 16:16:35 -0800764 assign flash_o.tl_flash_c2p = tl_win_h2d[2];
Timothy Chen16741102021-01-15 17:32:13 -0800765 assign flash_o.alert_trig = reg2hw.phy_alert_cfg.alert_trig.q;
766 assign flash_o.alert_ack = reg2hw.phy_alert_cfg.alert_ack.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700767 assign flash_rd_err = flash_i.rd_err;
768 assign flash_rd_data = flash_i.rd_data;
769 assign flash_phy_busy = flash_i.init_busy;
770
771 // Interface to pwrmgr
772 // flash is not idle as long as there is a stateful operation ongoing
773 logic flash_idle_d;
774 assign flash_idle_d = ~(flash_o.req &
775 (flash_o.prog | flash_o.pg_erase | flash_o.bk_erase));
776
777 prim_flop #(
778 .Width(1),
779 .ResetValue(1'b1)
780 ) u_reg_idle (
781 .clk_i,
782 .rst_ni,
783 .d_i(flash_idle_d),
784 .q_o(pwrmgr_o.flash_idle)
785 );
786
Timothy Chen16741102021-01-15 17:32:13 -0800787 //////////////////////////////////////
788 // Alert senders
789 //////////////////////////////////////
Timothy Chenff4a7702020-10-27 15:08:53 -0700790
Timothy Chen16741102021-01-15 17:32:13 -0800791 logic [NumAlerts-1:0] alert_srcs;
792 logic [NumAlerts-1:0] alert_tests;
793
Timothy Chen5302fff2021-01-22 14:36:54 -0800794 logic recov_err;
795 assign recov_err = flash_i.flash_alert_p | ~flash_i.flash_alert_n;
Timothy Chen16741102021-01-15 17:32:13 -0800796
797 logic recov_mp_err;
798 assign recov_mp_err = flash_mp_error;
799
800 logic recov_ecc_err;
801 assign recov_ecc_err = |flash_i.ecc_single_err | |flash_i.ecc_multi_err;
802
803 assign alert_srcs = { recov_ecc_err,
804 recov_mp_err,
Timothy Chen5302fff2021-01-22 14:36:54 -0800805 recov_err
Timothy Chen16741102021-01-15 17:32:13 -0800806 };
807
808 assign alert_tests = { reg2hw.alert_test.recov_ecc_err.q & reg2hw.alert_test.recov_ecc_err.qe,
809 reg2hw.alert_test.recov_mp_err.q & reg2hw.alert_test.recov_mp_err.qe,
Timothy Chen5302fff2021-01-22 14:36:54 -0800810 reg2hw.alert_test.recov_err.q & reg2hw.alert_test.recov_err.qe
Timothy Chen16741102021-01-15 17:32:13 -0800811 };
812
813 for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_senders
814 prim_alert_sender #(
815 .AsyncOn(AlertAsyncOn)
816 ) u_alert_sender (
817 .clk_i,
818 .rst_ni,
Timothy Chen06f78312021-01-20 18:43:27 -0800819 .alert_req_i(alert_srcs[i]),
820 .alert_test_i(alert_tests[i]),
Timothy Chen16741102021-01-15 17:32:13 -0800821 .alert_ack_o(),
Timothy Chen06f78312021-01-20 18:43:27 -0800822 .alert_state_o(),
Timothy Chen16741102021-01-15 17:32:13 -0800823 .alert_rx_i(alert_rx_i[i]),
824 .alert_tx_o(alert_tx_o[i])
825 );
826 end
827
828
829 //////////////////////////////////////
830 // Errors and Interrupts
831 //////////////////////////////////////
832
833 assign hw2reg.err_code.mp_err.d = 1'b1;
834 assign hw2reg.err_code.ecc_single_err.d = 1'b1;
835 assign hw2reg.err_code.ecc_multi_err.d = 1'b1;
836 assign hw2reg.err_code.flash_err.d = 1'b1;
837 assign hw2reg.err_code.flash_alert.d = 1'b1;
838 assign hw2reg.err_code.mp_err.de = flash_mp_error;
839 assign hw2reg.err_code.ecc_single_err.de = |flash_i.ecc_single_err;
840 assign hw2reg.err_code.ecc_multi_err.de = |flash_i.ecc_multi_err;
841 assign hw2reg.err_code.flash_err.de = flash_i.flash_err;
842 assign hw2reg.err_code.flash_alert.de = flash_i.flash_alert_p | ~flash_i.flash_alert_n;
843 assign hw2reg.err_addr.d = err_addr;
844 assign hw2reg.err_addr.de = flash_mp_error;
845
846 for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_err_cons
847 assign hw2reg.ecc_err_addr[bank].d = {flash_i.ecc_addr[bank], {BusByteWidth{1'b0}}};
848 assign hw2reg.ecc_err_addr[bank].de = flash_i.ecc_single_err[bank] |
849 flash_i.ecc_multi_err[bank];
850 end
851
Timothy Chenff4a7702020-10-27 15:08:53 -0700852 // Generate edge triggered signals for sources that are level
853 logic [3:0] intr_src;
854 logic [3:0] intr_src_q;
855 logic [3:0] intr_assert;
856
857 assign intr_src = { ~prog_fifo_rvalid,
858 reg2hw.fifo_lvl.prog.q == prog_fifo_depth,
Timothy Chen71d98f82020-12-17 17:17:25 -0800859 rd_fifo_full,
Timothy Chenff4a7702020-10-27 15:08:53 -0700860 reg2hw.fifo_lvl.rd.q == rd_fifo_depth
861 };
862
863 always_ff @(posedge clk_i or negedge rst_ni) begin
864 if (!rst_ni) begin
865 intr_src_q <= 4'h8; //prog_fifo is empty by default
866 end else if (sw_sel) begin
867 intr_src_q <= intr_src;
868 end
869 end
870
871 assign intr_assert = ~intr_src_q & intr_src;
872
873
874 assign intr_prog_empty_o = reg2hw.intr_enable.prog_empty.q & reg2hw.intr_state.prog_empty.q;
875 assign intr_prog_lvl_o = reg2hw.intr_enable.prog_lvl.q & reg2hw.intr_state.prog_lvl.q;
876 assign intr_rd_full_o = reg2hw.intr_enable.rd_full.q & reg2hw.intr_state.rd_full.q;
877 assign intr_rd_lvl_o = reg2hw.intr_enable.rd_lvl.q & reg2hw.intr_state.rd_lvl.q;
878 assign intr_op_done_o = reg2hw.intr_enable.op_done.q & reg2hw.intr_state.op_done.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700879
880 assign hw2reg.intr_state.prog_empty.d = 1'b1;
881 assign hw2reg.intr_state.prog_empty.de = intr_assert[3] |
882 (reg2hw.intr_test.prog_empty.qe &
883 reg2hw.intr_test.prog_empty.q);
884
885 assign hw2reg.intr_state.prog_lvl.d = 1'b1;
886 assign hw2reg.intr_state.prog_lvl.de = intr_assert[2] |
887 (reg2hw.intr_test.prog_lvl.qe &
888 reg2hw.intr_test.prog_lvl.q);
889
890 assign hw2reg.intr_state.rd_full.d = 1'b1;
891 assign hw2reg.intr_state.rd_full.de = intr_assert[1] |
892 (reg2hw.intr_test.rd_full.qe &
893 reg2hw.intr_test.rd_full.q);
894
895 assign hw2reg.intr_state.rd_lvl.d = 1'b1;
896 assign hw2reg.intr_state.rd_lvl.de = intr_assert[0] |
897 (reg2hw.intr_test.rd_lvl.qe &
898 reg2hw.intr_test.rd_lvl.q);
899
900
901 assign hw2reg.intr_state.op_done.d = 1'b1;
902 assign hw2reg.intr_state.op_done.de = sw_ctrl_done |
903 (reg2hw.intr_test.op_done.qe &
904 reg2hw.intr_test.op_done.q);
905
Timothy Chenff4a7702020-10-27 15:08:53 -0700906
907 // Unused bits
908 logic [BusByteWidth-1:0] unused_byte_sel;
909 logic [top_pkg::TL_AW-1-BusAddrW:0] unused_higher_addr_bits;
910 logic [top_pkg::TL_AW-1:0] unused_scratch;
911
912
913 // Unused signals
914 assign unused_byte_sel = muxed_addr[BusByteWidth-1:0];
915 assign unused_higher_addr_bits = muxed_addr[top_pkg::TL_AW-1:BusAddrW];
916 assign unused_scratch = reg2hw.scratch;
917
918
919 // Assertions
920 `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid )
921 `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready )
922 `ASSERT_KNOWN(FlashKnownO_A, {flash_o.req, flash_o.rd, flash_o.prog, flash_o.pg_erase,
923 flash_o.bk_erase})
924 `ASSERT_KNOWN_IF(FlashAddrKnown_A, flash_o.addr, flash_o.req)
925 `ASSERT_KNOWN_IF(FlashProgKnown_A, flash_o.prog_data, flash_o.prog & flash_o.req)
926 `ASSERT_KNOWN(IntrProgEmptyKnownO_A, intr_prog_empty_o)
927 `ASSERT_KNOWN(IntrProgLvlKnownO_A, intr_prog_lvl_o )
928 `ASSERT_KNOWN(IntrProgRdFullKnownO_A, intr_rd_full_o )
929 `ASSERT_KNOWN(IntrRdLvlKnownO_A, intr_rd_lvl_o )
930 `ASSERT_KNOWN(IntrOpDoneKnownO_A, intr_op_done_o )
Timothy Chenff4a7702020-10-27 15:08:53 -0700931
932endmodule