blob: 44440b435159157d714d29ac468cf7b7a76531b1 [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
Rupert Swarbrick21d6e5b2021-03-18 09:07:35 +000011module flash_ctrl
12 import flash_ctrl_pkg::*;
13 import flash_ctrl_reg_pkg::*;
14#(
15 parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}},
16 parameter flash_key_t RndCnstAddrKey = RndCnstAddrKeyDefault,
17 parameter flash_key_t RndCnstDataKey = RndCnstDataKeyDefault,
18 parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
19 parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault
Timothy Chenf52a4612020-12-04 20:37:49 -080020) (
Timothy Chenff4a7702020-10-27 15:08:53 -070021 input clk_i,
22 input rst_ni,
23
Timothy Chenf52a4612020-12-04 20:37:49 -080024 input clk_otp_i,
25 input rst_otp_ni,
26
Timothy Chen8ea1b412020-11-18 18:32:08 -080027 // life cycle interface
Timothy Chen99f3e3a2020-12-09 18:30:19 -080028 input lc_ctrl_pkg::lc_tx_t lc_creator_seed_sw_rw_en_i,
29 input lc_ctrl_pkg::lc_tx_t lc_owner_seed_sw_rw_en_i,
30 input lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_rd_en_i,
31 input lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_wr_en_i,
32 input lc_ctrl_pkg::lc_tx_t lc_seed_hw_rd_en_i,
Timothy Chen8ea1b412020-11-18 18:32:08 -080033
Timothy Chenff4a7702020-10-27 15:08:53 -070034 // Bus Interface
Timothy Chen8adb20d2021-03-25 16:49:04 -070035 input tlul_pkg::tl_h2d_t core_tl_i,
36 output tlul_pkg::tl_d2h_t core_tl_o,
37 input tlul_pkg::tl_h2d_t prim_tl_i,
38 output tlul_pkg::tl_d2h_t prim_tl_o,
Timothy Chenff4a7702020-10-27 15:08:53 -070039
40 // Flash Interface
41 input flash_rsp_t flash_i,
42 output flash_req_t flash_o,
43
44 // otp/lc/pwrmgr/keymgr Interface
Timothy Chenf52a4612020-12-04 20:37:49 -080045 output otp_ctrl_pkg::flash_otp_key_req_t otp_o,
46 input otp_ctrl_pkg::flash_otp_key_rsp_t otp_i,
Timothy Chend39402a2020-12-15 20:34:09 -080047 input lc_ctrl_pkg::lc_tx_t rma_req_i,
48 input lc_ctrl_pkg::lc_flash_rma_seed_t rma_seed_i,
49 output lc_ctrl_pkg::lc_tx_t rma_ack_o,
Timothy Chen6efde1e2021-04-16 15:39:23 -070050 output pwrmgr_pkg::pwr_flash_t pwrmgr_o,
Timothy Chenff4a7702020-10-27 15:08:53 -070051 output keymgr_flash_t keymgr_o,
52
Timothy Chend8fded82021-02-22 11:32:55 -080053 // IOs
54 input cio_tck_i,
55 input cio_tms_i,
56 input cio_tdi_i,
57 output logic cio_tdo_en_o,
58 output logic cio_tdo_o,
59
Timothy Chenff4a7702020-10-27 15:08:53 -070060 // Interrupts
Timothy Chen4798f272021-03-24 17:19:42 -070061 output logic intr_err_o, // ERR_CODE is non-zero
Timothy Chenff4a7702020-10-27 15:08:53 -070062 output logic intr_prog_empty_o, // Program fifo is empty
63 output logic intr_prog_lvl_o, // Program fifo is empty
64 output logic intr_rd_full_o, // Read fifo is full
65 output logic intr_rd_lvl_o, // Read fifo is full
66 output logic intr_op_done_o, // Requested flash operation (wr/erase) done
Timothy Chen16741102021-01-15 17:32:13 -080067
68 // Alerts
69 input prim_alert_pkg::alert_rx_t [flash_ctrl_reg_pkg::NumAlerts-1:0] alert_rx_i,
70 output prim_alert_pkg::alert_tx_t [flash_ctrl_reg_pkg::NumAlerts-1:0] alert_tx_o
71
72
Timothy Chenff4a7702020-10-27 15:08:53 -070073);
74
75 import flash_ctrl_reg_pkg::*;
76
Timothy Chen8adb20d2021-03-25 16:49:04 -070077 flash_ctrl_core_reg2hw_t reg2hw;
78 flash_ctrl_core_hw2reg_t hw2reg;
Timothy Chenff4a7702020-10-27 15:08:53 -070079
Timothy Chen8adb20d2021-03-25 16:49:04 -070080 tlul_pkg::tl_h2d_t tl_win_h2d [2];
81 tlul_pkg::tl_d2h_t tl_win_d2h [2];
Timothy Chenff4a7702020-10-27 15:08:53 -070082
Timothy Chen8adb20d2021-03-25 16:49:04 -070083 assign prim_tl_o = flash_i.tl_flash_p2c;
Timothy Chene1e0fd62021-04-07 16:13:28 -070084
Timothy Chenff4a7702020-10-27 15:08:53 -070085 // Register module
Timothy Chene1e0fd62021-04-07 16:13:28 -070086 logic intg_err;
Timothy Chen8adb20d2021-03-25 16:49:04 -070087 flash_ctrl_core_reg_top u_reg_core (
Timothy Chenff4a7702020-10-27 15:08:53 -070088 .clk_i,
89 .rst_ni,
90
Timothy Chen8adb20d2021-03-25 16:49:04 -070091 .tl_i(core_tl_i),
92 .tl_o(core_tl_o),
Timothy Chenff4a7702020-10-27 15:08:53 -070093
Timothy Chen6e495182020-12-28 16:16:35 -080094 .tl_win_o (tl_win_h2d),
95 .tl_win_i (tl_win_d2h),
Timothy Chenff4a7702020-10-27 15:08:53 -070096
97 .reg2hw,
98 .hw2reg,
99
Timothy Chene1e0fd62021-04-07 16:13:28 -0700100 .intg_err_o (intg_err),
Timothy Chenff4a7702020-10-27 15:08:53 -0700101 .devmode_i (1'b1)
102 );
103
104 // FIFO Connections
105 logic prog_fifo_wvalid;
106 logic prog_fifo_wready;
107 logic prog_fifo_rvalid;
108 logic prog_fifo_ren;
109 logic [BusWidth-1:0] prog_fifo_wdata;
110 logic [BusWidth-1:0] prog_fifo_rdata;
111 logic [FifoDepthW-1:0] prog_fifo_depth;
112 logic rd_fifo_wready;
113 logic rd_fifo_rvalid;
114 logic rd_fifo_rready;
115 logic rd_fifo_wen;
116 logic rd_fifo_ren;
117 logic [BusWidth-1:0] rd_fifo_wdata;
118 logic [BusWidth-1:0] rd_fifo_rdata;
119 logic [FifoDepthW-1:0] rd_fifo_depth;
Timothy Chen71d98f82020-12-17 17:17:25 -0800120 logic rd_fifo_full;
Timothy Chenff4a7702020-10-27 15:08:53 -0700121
122 // Program Control Connections
123 logic prog_flash_req;
124 logic prog_flash_ovfl;
125 logic [BusAddrW-1:0] prog_flash_addr;
126 logic prog_op_valid;
127
128 // Read Control Connections
129 logic rd_flash_req;
130 logic rd_flash_ovfl;
131 logic [BusAddrW-1:0] rd_flash_addr;
132
133 // Erase Control Connections
134 logic erase_flash_req;
135 logic [BusAddrW-1:0] erase_flash_addr;
136 flash_erase_e erase_flash_type;
137
138 // Done / Error signaling from ctrl modules
139 logic prog_done, rd_done, erase_done;
140 logic prog_err, rd_err, erase_err;
141
Timothy Chend5323562020-12-02 16:10:44 -0800142 // Flash Memory Properties Connections
Timothy Chenff4a7702020-10-27 15:08:53 -0700143 logic [BusAddrW-1:0] flash_addr;
144 logic flash_req;
145 logic flash_rd_done, flash_prog_done, flash_erase_done;
146 logic flash_mp_error;
147 logic [BusWidth-1:0] flash_prog_data;
148 logic flash_prog_last;
149 flash_prog_e flash_prog_type;
150 logic [BusWidth-1:0] flash_rd_data;
151 logic flash_rd_err;
152 logic flash_phy_busy;
153 logic rd_op;
154 logic prog_op;
155 logic erase_op;
156 logic [AllPagesW-1:0] err_addr;
157 flash_lcmgr_phase_e phase;
158
159 // Flash control arbitration connections to hardware interface
Timothy Chenf52a4612020-12-04 20:37:49 -0800160 flash_key_t addr_key;
Timothy Chene1e0fd62021-04-07 16:13:28 -0700161 flash_key_t rand_addr_key;
Timothy Chenf52a4612020-12-04 20:37:49 -0800162 flash_key_t data_key;
Timothy Chene1e0fd62021-04-07 16:13:28 -0700163 flash_key_t rand_data_key;
Timothy Chenff4a7702020-10-27 15:08:53 -0700164 flash_ctrl_reg2hw_control_reg_t hw_ctrl;
165 logic hw_req;
166 logic [top_pkg::TL_AW-1:0] hw_addr;
167 logic hw_done;
168 logic hw_err;
169 logic hw_rvalid;
170 logic hw_rready;
Timothy Chend39402a2020-12-15 20:34:09 -0800171 logic hw_wvalid;
172 logic [BusWidth-1:0] hw_wdata;
173 logic hw_wready;
Timothy Chenff4a7702020-10-27 15:08:53 -0700174 flash_sel_e if_sel;
175 logic sw_sel;
176 flash_lcmgr_phase_e hw_phase;
177 logic creator_seed_priv;
178 logic owner_seed_priv;
179
180 // Flash control arbitration connections to software interface
181 logic sw_ctrl_done;
182 logic sw_ctrl_err;
183
184 // Flash control muxed connections
185 flash_ctrl_reg2hw_control_reg_t muxed_ctrl;
186 logic [top_pkg::TL_AW-1:0] muxed_addr;
187 logic op_start;
188 logic [11:0] op_num_words;
189 logic [BusAddrW-1:0] op_addr;
190 flash_op_e op_type;
191 flash_part_e op_part;
192 logic [InfoTypesWidth-1:0] op_info_sel;
193 flash_erase_e op_erase_type;
194 flash_prog_e op_prog_type;
195
196 logic ctrl_init_busy;
197 logic fifo_clr;
198
199 // software tlul to flash control aribration
200 logic sw_rvalid;
201 logic adapter_rvalid;
202 logic sw_wvalid;
Timothy Chend39402a2020-12-15 20:34:09 -0800203 logic [BusWidth-1:0] sw_wdata;
Timothy Chenff4a7702020-10-27 15:08:53 -0700204 logic sw_wen;
205 logic sw_wready;
206
207 // lfsr for local entropy usage
208 logic [31:0] rand_val;
209 logic lfsr_en;
Timothy Chend39402a2020-12-15 20:34:09 -0800210 logic lfsr_seed_en;
Timothy Chenff4a7702020-10-27 15:08:53 -0700211
Timothy Chen8ea1b412020-11-18 18:32:08 -0800212 // life cycle connections
Cindy Chenf309ea52021-04-01 18:16:57 -0700213 lc_ctrl_pkg::lc_tx_t lc_creator_seed_sw_rw_en;
214 lc_ctrl_pkg::lc_tx_t lc_owner_seed_sw_rw_en;
215 lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_rd_en;
216 lc_ctrl_pkg::lc_tx_t lc_iso_part_sw_wr_en;
217 lc_ctrl_pkg::lc_tx_t lc_seed_hw_rd_en;
Timothy Chen8ea1b412020-11-18 18:32:08 -0800218
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800219 // synchronize enables into local domain
Timothy Chen8d923152020-12-02 18:01:28 -0800220 prim_lc_sync #(
221 .NumCopies(1)
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800222 ) u_lc_creator_seed_sw_rw_en_sync (
Timothy Chen8d923152020-12-02 18:01:28 -0800223 .clk_i,
224 .rst_ni,
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800225 .lc_en_i(lc_creator_seed_sw_rw_en_i),
226 .lc_en_o(lc_creator_seed_sw_rw_en)
Timothy Chen8d923152020-12-02 18:01:28 -0800227 );
228
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800229 prim_lc_sync #(
230 .NumCopies(1)
231 ) u_lc_owner_seed_sw_rw_en_sync (
232 .clk_i,
233 .rst_ni,
234 .lc_en_i(lc_owner_seed_sw_rw_en_i),
235 .lc_en_o(lc_owner_seed_sw_rw_en)
236 );
237
238 prim_lc_sync #(
239 .NumCopies(1)
240 ) u_lc_iso_part_sw_rd_en_sync (
241 .clk_i,
242 .rst_ni,
243 .lc_en_i(lc_iso_part_sw_rd_en_i),
244 .lc_en_o(lc_iso_part_sw_rd_en)
245 );
246
247 prim_lc_sync #(
248 .NumCopies(1)
249 ) u_lc_iso_part_sw_wr_en_sync (
250 .clk_i,
251 .rst_ni,
252 .lc_en_i(lc_iso_part_sw_wr_en_i),
253 .lc_en_o(lc_iso_part_sw_wr_en)
254 );
255
256 prim_lc_sync #(
257 .NumCopies(1)
258 ) u_lc_seed_hw_rd_en_sync (
259 .clk_i,
260 .rst_ni,
261 .lc_en_i(lc_seed_hw_rd_en_i),
262 .lc_en_o(lc_seed_hw_rd_en)
263 );
Timothy Chen8d923152020-12-02 18:01:28 -0800264
Timothy Chenff4a7702020-10-27 15:08:53 -0700265 prim_lfsr #(
Timothy Chenaeffadc2020-12-11 15:03:07 -0800266 .EntropyDw(EdnWidth),
Timothy Chenf52a4612020-12-04 20:37:49 -0800267 .LfsrDw(LfsrWidth),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800268 .StateOutDw(LfsrWidth),
269 .DefaultSeed(RndCnstLfsrSeed),
270 .StatePermEn(1),
271 .StatePerm(RndCnstLfsrPerm)
Timothy Chenff4a7702020-10-27 15:08:53 -0700272 ) u_lfsr (
273 .clk_i,
274 .rst_ni,
Timothy Chend39402a2020-12-15 20:34:09 -0800275 .seed_en_i(lfsr_seed_en),
276 .seed_i(rma_seed_i),
Timothy Chenff4a7702020-10-27 15:08:53 -0700277 .lfsr_en_i(lfsr_en),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800278 .entropy_i('0),
Timothy Chenff4a7702020-10-27 15:08:53 -0700279 .state_o(rand_val)
280 );
281
282 // flash control arbitration between softawre / harware interfaces
283 flash_ctrl_arb u_ctrl_arb (
284 .clk_i,
285 .rst_ni,
286
287 // software interface to rd_ctrl / erase_ctrl
288 .sw_ctrl_i(reg2hw.control),
289 .sw_addr_i(reg2hw.addr.q),
290 .sw_ack_o(sw_ctrl_done),
291 .sw_err_o(sw_ctrl_err),
292
293 // software interface to rd_fifo
294 .sw_rvalid_o(sw_rvalid),
295 .sw_rready_i(adapter_rvalid),
296
297 // software interface to prog_fifo
298 .sw_wvalid_i(sw_wvalid & sw_wen),
Timothy Chend39402a2020-12-15 20:34:09 -0800299 .sw_wdata_i(sw_wdata),
Timothy Chenff4a7702020-10-27 15:08:53 -0700300 .sw_wready_o(sw_wready),
301
302 // hardware interface to rd_ctrl / erase_ctrl
303 .hw_req_i(hw_req),
304 .hw_ctrl_i(hw_ctrl),
305
306 // hardware interface indicating operation phase
307 .hw_phase_i(hw_phase),
308
309 // hardware works on word address, however software expects byte address
310 .hw_addr_i(hw_addr),
311 .hw_ack_o(hw_done),
312 .hw_err_o(hw_err),
313
314 // hardware interface to rd_fifo
315 .hw_rvalid_o(hw_rvalid),
316 .hw_rready_i(hw_rready),
Timothy Chend39402a2020-12-15 20:34:09 -0800317 .hw_wvalid_i(hw_wvalid),
318 .hw_wdata_i(hw_wdata),
319 .hw_wready_o(hw_wready),
Timothy Chenff4a7702020-10-27 15:08:53 -0700320
321 // hardware interface does not talk to prog_fifo
322
323 // muxed interface to rd_ctrl / erase_ctrl
324 .muxed_ctrl_o(muxed_ctrl),
325 .muxed_addr_o(muxed_addr),
326 .prog_ack_i(prog_done),
327 .prog_err_i(prog_err),
328 .rd_ack_i(rd_done),
329 .rd_err_i(rd_err),
330 .erase_ack_i(erase_done),
331 .erase_err_i(erase_err),
332
333 // muxed interface to rd_fifo
334 .rd_fifo_rvalid_i(rd_fifo_rvalid),
335 .rd_fifo_rready_o(rd_fifo_rready),
336
337 // muxed interface to prog_fifo
338 .prog_fifo_wvalid_o(prog_fifo_wvalid),
Timothy Chend39402a2020-12-15 20:34:09 -0800339 .prog_fifo_wdata_o(prog_fifo_wdata),
Timothy Chenff4a7702020-10-27 15:08:53 -0700340 .prog_fifo_wready_i(prog_fifo_wready),
341
342 // flash phy initilization ongoing
343 .flash_phy_busy_i(flash_phy_busy),
344
345 // clear fifos
346 .fifo_clr_o(fifo_clr),
347
348 // phase indication
349 .phase_o(phase),
350
351 // indication that sw has been selected
Timothy Chenaeffadc2020-12-11 15:03:07 -0800352 .sel_o(if_sel)
Timothy Chenff4a7702020-10-27 15:08:53 -0700353 );
354
355 assign op_start = muxed_ctrl.start.q;
356 assign op_num_words = muxed_ctrl.num.q;
357 assign op_erase_type = flash_erase_e'(muxed_ctrl.erase_sel.q);
358 assign op_prog_type = flash_prog_e'(muxed_ctrl.prog_sel.q);
359 assign op_addr = muxed_addr[BusByteWidth +: BusAddrW];
360 assign op_type = flash_op_e'(muxed_ctrl.op.q);
361 assign op_part = flash_part_e'(muxed_ctrl.partition_sel.q);
362 assign op_info_sel = muxed_ctrl.info_sel.q;
363 assign rd_op = op_type == FlashOpRead;
364 assign prog_op = op_type == FlashOpProgram;
365 assign erase_op = op_type == FlashOpErase;
366 assign sw_sel = if_sel == SwSel;
367
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800368 // software privilege to creator seed
Cindy Chenf309ea52021-04-01 18:16:57 -0700369 assign creator_seed_priv = lc_creator_seed_sw_rw_en == lc_ctrl_pkg::On;
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800370
371 // software privilege to owner seed
Cindy Chenf309ea52021-04-01 18:16:57 -0700372 assign owner_seed_priv = lc_owner_seed_sw_rw_en == lc_ctrl_pkg::On;
Timothy Chen99f3e3a2020-12-09 18:30:19 -0800373
Timothy Chenff4a7702020-10-27 15:08:53 -0700374 // hardware interface
Timothy Chenf52a4612020-12-04 20:37:49 -0800375 flash_ctrl_lcmgr #(
376 .RndCnstAddrKey(RndCnstAddrKey),
377 .RndCnstDataKey(RndCnstDataKey)
378 ) u_flash_hw_if (
Timothy Chenff4a7702020-10-27 15:08:53 -0700379 .clk_i,
380 .rst_ni,
Timothy Chenf52a4612020-12-04 20:37:49 -0800381 .clk_otp_i,
382 .rst_otp_ni,
Timothy Chenff4a7702020-10-27 15:08:53 -0700383
Timothy Chen568b2142021-04-16 13:10:43 -0700384 .init_i(reg2hw.init),
Cindy Chenf309ea52021-04-01 18:16:57 -0700385 .provision_en_i(lc_seed_hw_rd_en == lc_ctrl_pkg::On),
Timothy Chenff4a7702020-10-27 15:08:53 -0700386
387 // interface to ctrl arb control ports
388 .ctrl_o(hw_ctrl),
389 .req_o(hw_req),
390 .addr_o(hw_addr),
391 .done_i(hw_done),
392 .err_i(hw_err),
393
394 // interface to ctrl_arb data ports
395 .rready_o(hw_rready),
396 .rvalid_i(hw_rvalid),
Timothy Chend39402a2020-12-15 20:34:09 -0800397 .wready_i(hw_wready),
398 .wvalid_o(hw_wvalid),
399 .wdata_o(hw_wdata),
Timothy Chenff4a7702020-10-27 15:08:53 -0700400
401 // direct form rd_fifo
402 .rdata_i(rd_fifo_rdata),
403
404 // external rma request
Timothy Chend39402a2020-12-15 20:34:09 -0800405 .rma_req_i,
406 .rma_ack_o,
Timothy Chenff4a7702020-10-27 15:08:53 -0700407
Timothy Chenff4a7702020-10-27 15:08:53 -0700408 // outgoing seeds
409 .seeds_o(keymgr_o.seeds),
410 .seed_err_o(), // TBD hook-up to Err code register
411
412 // phase indication
413 .phase_o(hw_phase),
414
Timothy Chen6b241b32020-11-13 15:15:45 -0800415 // phy read buffer enable
416 .rd_buf_en_o(flash_o.rd_buf_en),
417
Timothy Chenf52a4612020-12-04 20:37:49 -0800418 // connection to otp
419 .otp_key_req_o(otp_o),
420 .otp_key_rsp_i(otp_i),
421 .addr_key_o(addr_key),
422 .data_key_o(data_key),
Timothy Chene1e0fd62021-04-07 16:13:28 -0700423 .rand_addr_key_o(rand_addr_key),
424 .rand_data_key_o(rand_data_key),
Timothy Chenf52a4612020-12-04 20:37:49 -0800425
Timothy Chenaeffadc2020-12-11 15:03:07 -0800426 // entropy interface
Timothy Chend39402a2020-12-15 20:34:09 -0800427 .edn_req_o(lfsr_seed_en),
428 .edn_ack_i(1'b1),
Timothy Chenaeffadc2020-12-11 15:03:07 -0800429 .lfsr_en_o(lfsr_en),
430 .rand_i(rand_val),
431
Timothy Chenff4a7702020-10-27 15:08:53 -0700432 // init ongoing
433 .init_busy_o(ctrl_init_busy)
434 );
435
436 // Program FIFO
437 // Since the program and read FIFOs are never used at the same time, it should really be one
438 // FIFO with muxed inputs and outputs. This should be addressed once the flash integration
439 // strategy has been identified
440 assign prog_op_valid = op_start & prog_op;
441
442 tlul_adapter_sram #(
443 .SramAw(1), //address unused
444 .SramDw(BusWidth),
445 .ByteAccess(0), //flash may not support byte access
446 .ErrOnRead(1) //reads not supported
447 ) u_to_prog_fifo (
448 .clk_i,
449 .rst_ni,
Timothy Chen1a9a60f2021-02-10 18:04:39 -0800450 .tl_i (tl_win_h2d[0]),
451 .tl_o (tl_win_d2h[0]),
452 .en_ifetch_i (tlul_pkg::InstrDis),
453 .req_o (sw_wvalid),
Timothy Chen4798f272021-03-24 17:19:42 -0700454 .req_type_o (),
Timothy Chen1a9a60f2021-02-10 18:04:39 -0800455 .gnt_i (sw_wready),
456 .we_o (sw_wen),
457 .addr_o (),
458 .wmask_o (),
Timothy Chen12cce142021-03-02 18:11:01 -0800459 .intg_error_o(),
Timothy Chen1a9a60f2021-02-10 18:04:39 -0800460 .wdata_o (sw_wdata),
461 .rdata_i (BusWidth'(0)),
462 .rvalid_i (1'b0),
463 .rerror_i (2'b0)
Timothy Chenff4a7702020-10-27 15:08:53 -0700464 );
465
466 prim_fifo_sync #(
467 .Width(BusWidth),
468 .Depth(FifoDepth)
469 ) u_prog_fifo (
470 .clk_i,
471 .rst_ni,
472 .clr_i (reg2hw.fifo_rst.q | fifo_clr),
473 .wvalid_i(prog_fifo_wvalid & prog_op_valid),
474 .wready_o(prog_fifo_wready),
475 .wdata_i (prog_fifo_wdata),
476 .depth_o (prog_fifo_depth),
Philipp Wagner7858f3d2021-02-01 16:38:13 +0000477 .full_o (),
Timothy Chenff4a7702020-10-27 15:08:53 -0700478 .rvalid_o(prog_fifo_rvalid),
479 .rready_i(prog_fifo_ren),
480 .rdata_o (prog_fifo_rdata)
481 );
482
483 // Program handler is consumer of prog_fifo
Timothy Chenf52a4612020-12-04 20:37:49 -0800484 logic [1:0] prog_type_en;
485 assign prog_type_en[FlashProgNormal] = flash_i.prog_type_avail[FlashProgNormal] &
486 reg2hw.prog_type_en.normal.q;
487 assign prog_type_en[FlashProgRepair] = flash_i.prog_type_avail[FlashProgRepair] &
488 reg2hw.prog_type_en.repair.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700489 flash_ctrl_prog u_flash_ctrl_prog (
490 .clk_i,
491 .rst_ni,
492
493 // Control interface
494 .op_start_i (prog_op_valid),
495 .op_num_words_i (op_num_words),
496 .op_done_o (prog_done),
497 .op_err_o (prog_err),
498 .op_addr_i (op_addr),
499 .op_type_i (op_prog_type),
Timothy Chenf52a4612020-12-04 20:37:49 -0800500 .type_avail_i (prog_type_en),
Timothy Chenff4a7702020-10-27 15:08:53 -0700501
502 // FIFO Interface
503 .data_i (prog_fifo_rdata),
504 .data_rdy_i (prog_fifo_rvalid),
505 .data_rd_o (prog_fifo_ren),
506
507 // Flash Macro Interface
508 .flash_req_o (prog_flash_req),
509 .flash_addr_o (prog_flash_addr),
510 .flash_ovfl_o (prog_flash_ovfl),
511 .flash_data_o (flash_prog_data),
512 .flash_last_o (flash_prog_last),
513 .flash_type_o (flash_prog_type),
514 .flash_done_i (flash_prog_done),
515 .flash_error_i (flash_mp_error)
516 );
517
518 always_ff @(posedge clk_i or negedge rst_ni) begin
519 if (!rst_ni) begin
520 adapter_rvalid <= 1'b0;
521 end else begin
522 adapter_rvalid <= rd_fifo_ren && sw_rvalid;
523 end
524 end
525
526 // tlul adapter represents software's access interface to flash
527 tlul_adapter_sram #(
528 .SramAw(1), //address unused
529 .SramDw(BusWidth),
530 .ByteAccess(0), //flash may not support byte access
531 .ErrOnWrite(1) //writes not supported
532 ) u_to_rd_fifo (
533 .clk_i,
534 .rst_ni,
Timothy Chen1a9a60f2021-02-10 18:04:39 -0800535 .tl_i (tl_win_h2d[1]),
536 .tl_o (tl_win_d2h[1]),
537 .en_ifetch_i (tlul_pkg::InstrDis),
538 .req_o (rd_fifo_ren),
Timothy Chen4798f272021-03-24 17:19:42 -0700539 .req_type_o (),
Timothy Chen1a9a60f2021-02-10 18:04:39 -0800540 .gnt_i (rd_fifo_rvalid),
541 .we_o (),
542 .addr_o (),
543 .wmask_o (),
544 .wdata_o (),
Timothy Chen12cce142021-03-02 18:11:01 -0800545 .intg_error_o(),
Timothy Chen1a9a60f2021-02-10 18:04:39 -0800546 .rdata_i (rd_fifo_rdata),
547 .rvalid_i (adapter_rvalid),
548 .rerror_i (2'b0)
Timothy Chenff4a7702020-10-27 15:08:53 -0700549 );
550
551 prim_fifo_sync #(
552 .Width(BusWidth),
553 .Depth(FifoDepth)
554 ) u_rd_fifo (
555 .clk_i,
556 .rst_ni,
557 .clr_i (reg2hw.fifo_rst.q | fifo_clr),
558 .wvalid_i(rd_fifo_wen),
559 .wready_o(rd_fifo_wready),
560 .wdata_i (rd_fifo_wdata),
Timothy Chen71d98f82020-12-17 17:17:25 -0800561 .full_o (rd_fifo_full),
Timothy Chenff4a7702020-10-27 15:08:53 -0700562 .depth_o (rd_fifo_depth),
563 .rvalid_o(rd_fifo_rvalid),
564 .rready_i(rd_fifo_rready),
565 .rdata_o (rd_fifo_rdata)
566 );
567
568 // Read handler is consumer of rd_fifo
569 flash_ctrl_rd u_flash_ctrl_rd (
570 .clk_i,
571 .rst_ni,
572
573 // To arbiter Interface
574 .op_start_i (op_start & rd_op),
575 .op_num_words_i (op_num_words),
576 .op_done_o (rd_done),
577 .op_err_o (rd_err),
578 .op_addr_i (op_addr),
579
580 // FIFO Interface
581 .data_rdy_i (rd_fifo_wready),
582 .data_o (rd_fifo_wdata),
583 .data_wr_o (rd_fifo_wen),
584
585 // Flash Macro Interface
586 .flash_req_o (rd_flash_req),
587 .flash_addr_o (rd_flash_addr),
588 .flash_ovfl_o (rd_flash_ovfl),
589 .flash_data_i (flash_rd_data),
590 .flash_done_i (flash_rd_done),
591 .flash_error_i (flash_mp_error | flash_rd_err)
592 );
593
594 // Erase handler does not consume fifo
595 flash_ctrl_erase u_flash_ctrl_erase (
596 // Software Interface
597 .op_start_i (op_start & erase_op),
598 .op_type_i (op_erase_type),
599 .op_done_o (erase_done),
600 .op_err_o (erase_err),
601 .op_addr_i (op_addr),
602
603 // Flash Macro Interface
604 .flash_req_o (erase_flash_req),
605 .flash_addr_o (erase_flash_addr),
606 .flash_op_o (erase_flash_type),
607 .flash_done_i (flash_erase_done),
608 .flash_error_i (flash_mp_error)
609 );
610
611 // Final muxing to flash macro module
612 always_comb begin
613 unique case (op_type)
614 FlashOpRead: begin
615 flash_req = rd_flash_req;
616 flash_addr = rd_flash_addr;
617 end
618 FlashOpProgram: begin
619 flash_req = prog_flash_req;
620 flash_addr = prog_flash_addr;
621 end
622 FlashOpErase: begin
623 flash_req = erase_flash_req;
624 flash_addr = erase_flash_addr;
625 end
626 default: begin
627 flash_req = 1'b0;
628 flash_addr = '0;
629 end
630 endcase // unique case (op_type)
631 end
632
633 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800634 // Data partition properties configuration
Timothy Chenff4a7702020-10-27 15:08:53 -0700635 //////////////////////////////////////
636 // extra region is the default region
637 mp_region_cfg_t [MpRegions:0] region_cfgs;
638 assign region_cfgs[MpRegions-1:0] = reg2hw.mp_region_cfg[MpRegions-1:0];
639
640 //default region
641 assign region_cfgs[MpRegions].base.q = '0;
642 assign region_cfgs[MpRegions].size.q = NumBanks * PagesPerBank;
643 assign region_cfgs[MpRegions].en.q = 1'b1;
644 assign region_cfgs[MpRegions].rd_en.q = reg2hw.default_region.rd_en.q;
645 assign region_cfgs[MpRegions].prog_en.q = reg2hw.default_region.prog_en.q;
646 assign region_cfgs[MpRegions].erase_en.q = reg2hw.default_region.erase_en.q;
647 assign region_cfgs[MpRegions].scramble_en.q = reg2hw.default_region.scramble_en.q;
Timothy Chena2db9332020-11-13 18:47:54 -0800648 assign region_cfgs[MpRegions].ecc_en.q = reg2hw.default_region.ecc_en.q;
Timothy Chend5323562020-12-02 16:10:44 -0800649 assign region_cfgs[MpRegions].he_en.q = reg2hw.default_region.he_en.q;
Timothy Chenff4a7702020-10-27 15:08:53 -0700650
651 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800652 // Info partition properties configuration
Timothy Chenff4a7702020-10-27 15:08:53 -0700653 //////////////////////////////////////
654 info_page_cfg_t [NumBanks-1:0][InfoTypes-1:0][InfosPerBank-1:0] reg2hw_info_page_cfgs;
655 info_page_cfg_t [NumBanks-1:0][InfoTypes-1:0][InfosPerBank-1:0] info_page_cfgs;
Timothy Chene97e0b82020-12-11 17:18:43 -0800656 localparam int InfoBits = $bits(info_page_cfg_t) * InfosPerBank;
Timothy Chenff4a7702020-10-27 15:08:53 -0700657
658 // transform from reg output to structure
Timothy Chene97e0b82020-12-11 17:18:43 -0800659 // Not all types have the maximum number of banks, so those are packed to 0
Timothy Chenff4a7702020-10-27 15:08:53 -0700660 % for bank in range(cfg['banks']):
661 % for idx in range(cfg['info_types']):
Timothy Chene97e0b82020-12-11 17:18:43 -0800662 assign reg2hw_info_page_cfgs[${bank}][${idx}] = InfoBits'(reg2hw.bank${bank}_info${idx}_page_cfg);
Timothy Chenff4a7702020-10-27 15:08:53 -0700663 % endfor
664 % endfor
665
666 // qualify reg2hw settings with creator / owner privileges
667 for(genvar i = 0; i < NumBanks; i++) begin : gen_info_priv_bank
668 for (genvar j = 0; j < InfoTypes; j++) begin : gen_info_priv_type
669 flash_ctrl_info_cfg # (
670 .Bank(i),
671 .InfoSel(j)
672 ) u_info_cfg (
673 .cfgs_i(reg2hw_info_page_cfgs[i][j]),
674 .creator_seed_priv_i(creator_seed_priv),
675 .owner_seed_priv_i(owner_seed_priv),
Cindy Chenf309ea52021-04-01 18:16:57 -0700676 .iso_flash_wr_en_i(lc_iso_part_sw_wr_en == lc_ctrl_pkg::On),
677 .iso_flash_rd_en_i(lc_iso_part_sw_rd_en == lc_ctrl_pkg::On),
Timothy Chenff4a7702020-10-27 15:08:53 -0700678 .cfgs_o(info_page_cfgs[i][j])
679 );
680 end
681 end
682
683 //////////////////////////////////////
Timothy Chend5323562020-12-02 16:10:44 -0800684 // flash memory properties
Timothy Chenff4a7702020-10-27 15:08:53 -0700685 //////////////////////////////////////
686 // direct assignment since prog/rd/erase_ctrl do not make use of op_part
687 flash_part_e flash_part_sel;
688 logic [InfoTypesWidth-1:0] flash_info_sel;
689 assign flash_part_sel = op_part;
690 assign flash_info_sel = op_info_sel;
691
Timothy Chen7d051eb2020-12-11 14:06:43 -0800692 // tie off hardware clear path
693 assign hw2reg.erase_suspend.d = 1'b0;
694
Timothy Chend5323562020-12-02 16:10:44 -0800695 // Flash memory Properties
696 // Memory property is page based and thus should use phy addressing
Timothy Chenff4a7702020-10-27 15:08:53 -0700697 // This should move to flash_phy long term
698 flash_mp u_flash_mp (
699 .clk_i,
700 .rst_ni,
701
702 // arbiter interface selection
703 .if_sel_i(if_sel),
704
705 // sw configuration for data partition
706 .region_cfgs_i(region_cfgs),
707 .bank_cfgs_i(reg2hw.mp_bank_cfg),
708
709 // sw configuration for info partition
710 .info_page_cfgs_i(info_page_cfgs),
711
712 // read / prog / erase controls
713 .req_i(flash_req),
714 .phase_i(phase),
715 .req_addr_i(flash_addr[BusAddrW-1 -: AllPagesW]),
716 .req_part_i(flash_part_sel),
717 .info_sel_i(flash_info_sel),
718 .addr_ovfl_i(rd_flash_ovfl | prog_flash_ovfl),
719 .rd_i(rd_op),
720 .prog_i(prog_op),
721 .pg_erase_i(erase_op & (erase_flash_type == FlashErasePage)),
722 .bk_erase_i(erase_op & (erase_flash_type == FlashEraseBank)),
Timothy Chen7d051eb2020-12-11 14:06:43 -0800723 .erase_suspend_i(reg2hw.erase_suspend),
724 .erase_suspend_done_o(hw2reg.erase_suspend.de),
Timothy Chenff4a7702020-10-27 15:08:53 -0700725 .rd_done_o(flash_rd_done),
726 .prog_done_o(flash_prog_done),
727 .erase_done_o(flash_erase_done),
728 .error_o(flash_mp_error),
729 .err_addr_o(err_addr),
730
731 // flash phy interface
732 .req_o(flash_o.req),
733 .scramble_en_o(flash_o.scramble_en),
Timothy Chena2db9332020-11-13 18:47:54 -0800734 .ecc_en_o(flash_o.ecc_en),
Timothy Chend5323562020-12-02 16:10:44 -0800735 .he_en_o(flash_o.he_en),
Timothy Chenff4a7702020-10-27 15:08:53 -0700736 .rd_o(flash_o.rd),
737 .prog_o(flash_o.prog),
738 .pg_erase_o(flash_o.pg_erase),
739 .bk_erase_o(flash_o.bk_erase),
Timothy Chen7d051eb2020-12-11 14:06:43 -0800740 .erase_suspend_o(flash_o.erase_suspend),
Timothy Chenff4a7702020-10-27 15:08:53 -0700741 .rd_done_i(flash_i.rd_done),
742 .prog_done_i(flash_i.prog_done),
743 .erase_done_i(flash_i.erase_done)
744 );
745
746
747 // software interface feedback
748 // most values (other than flash_phy_busy) should only update when software operations
749 // are actually selected
750 assign hw2reg.op_status.done.d = 1'b1;
751 assign hw2reg.op_status.done.de = sw_ctrl_done;
752 assign hw2reg.op_status.err.d = 1'b1;
753 assign hw2reg.op_status.err.de = sw_ctrl_err;
Timothy Chen71d98f82020-12-17 17:17:25 -0800754 assign hw2reg.status.rd_full.d = rd_fifo_full;
Timothy Chenff4a7702020-10-27 15:08:53 -0700755 assign hw2reg.status.rd_full.de = sw_sel;
756 assign hw2reg.status.rd_empty.d = ~rd_fifo_rvalid;
757 assign hw2reg.status.rd_empty.de = sw_sel;
758 assign hw2reg.status.prog_full.d = ~prog_fifo_wready;
759 assign hw2reg.status.prog_full.de = sw_sel;
760 assign hw2reg.status.prog_empty.d = ~prog_fifo_rvalid;
761 assign hw2reg.status.prog_empty.de = sw_sel;
762 assign hw2reg.status.init_wip.d = flash_phy_busy | ctrl_init_busy;
763 assign hw2reg.status.init_wip.de = 1'b1;
Timothy Chenff4a7702020-10-27 15:08:53 -0700764 assign hw2reg.control.start.d = 1'b0;
765 assign hw2reg.control.start.de = sw_ctrl_done;
766 // if software operation selected, based on transaction start
767 // if software operation not selected, software is free to change contents
768 assign hw2reg.ctrl_regwen.d = sw_sel ? !op_start : 1'b1;
769
770 // phy status
771 assign hw2reg.phy_status.init_wip.d = flash_phy_busy;
772 assign hw2reg.phy_status.init_wip.de = 1'b1;
773 assign hw2reg.phy_status.prog_normal_avail.d = flash_i.prog_type_avail[FlashProgNormal];
774 assign hw2reg.phy_status.prog_normal_avail.de = 1'b1;
775 assign hw2reg.phy_status.prog_repair_avail.d = flash_i.prog_type_avail[FlashProgRepair];
776 assign hw2reg.phy_status.prog_repair_avail.de = 1'b1;
777
778 // Flash Interface
779 assign flash_o.addr = flash_addr;
780 assign flash_o.part = flash_part_sel;
Timothy Chena0a550a2020-12-03 13:11:03 -0800781 assign flash_o.info_sel = flash_info_sel;
Timothy Chenff4a7702020-10-27 15:08:53 -0700782 assign flash_o.prog_type = flash_prog_type;
783 assign flash_o.prog_data = flash_prog_data;
784 assign flash_o.prog_last = flash_prog_last;
785 assign flash_o.region_cfgs = region_cfgs;
Timothy Chenf52a4612020-12-04 20:37:49 -0800786 assign flash_o.addr_key = addr_key;
787 assign flash_o.data_key = data_key;
Timothy Chene1e0fd62021-04-07 16:13:28 -0700788 assign flash_o.rand_addr_key = rand_addr_key;
789 assign flash_o.rand_data_key = rand_data_key;
Timothy Chen8adb20d2021-03-25 16:49:04 -0700790 assign flash_o.tl_flash_c2p = prim_tl_i;
Timothy Chen16741102021-01-15 17:32:13 -0800791 assign flash_o.alert_trig = reg2hw.phy_alert_cfg.alert_trig.q;
792 assign flash_o.alert_ack = reg2hw.phy_alert_cfg.alert_ack.q;
Timothy Chend8fded82021-02-22 11:32:55 -0800793 assign flash_o.jtag_req.tck = cio_tck_i;
794 assign flash_o.jtag_req.tms = cio_tms_i;
795 assign flash_o.jtag_req.tdi = cio_tdi_i;
796 assign flash_o.jtag_req.trst_n = '0;
Timothy Chen4798f272021-03-24 17:19:42 -0700797 assign flash_o.ecc_multi_err_en = reg2hw.phy_err_cfg.q;
Timothy Chene1e0fd62021-04-07 16:13:28 -0700798 assign flash_o.intg_err = intg_err;
Timothy Chend8fded82021-02-22 11:32:55 -0800799 assign cio_tdo_o = flash_i.jtag_rsp.tdo;
800 assign cio_tdo_en_o = flash_i.jtag_rsp.tdo_oe;
Timothy Chenff4a7702020-10-27 15:08:53 -0700801 assign flash_rd_err = flash_i.rd_err;
802 assign flash_rd_data = flash_i.rd_data;
803 assign flash_phy_busy = flash_i.init_busy;
804
Timothy Chend8fded82021-02-22 11:32:55 -0800805
Timothy Chen4798f272021-03-24 17:19:42 -0700806
Timothy Chene1e0fd62021-04-07 16:13:28 -0700807
Timothy Chenff4a7702020-10-27 15:08:53 -0700808 // Interface to pwrmgr
809 // flash is not idle as long as there is a stateful operation ongoing
810 logic flash_idle_d;
811 assign flash_idle_d = ~(flash_o.req &
812 (flash_o.prog | flash_o.pg_erase | flash_o.bk_erase));
813
814 prim_flop #(
815 .Width(1),
816 .ResetValue(1'b1)
817 ) u_reg_idle (
818 .clk_i,
819 .rst_ni,
820 .d_i(flash_idle_d),
821 .q_o(pwrmgr_o.flash_idle)
822 );
823
Timothy Chen16741102021-01-15 17:32:13 -0800824 //////////////////////////////////////
825 // Alert senders
826 //////////////////////////////////////
Timothy Chenff4a7702020-10-27 15:08:53 -0700827
Timothy Chen16741102021-01-15 17:32:13 -0800828 logic [NumAlerts-1:0] alert_srcs;
829 logic [NumAlerts-1:0] alert_tests;
830
Timothy Chen5302fff2021-01-22 14:36:54 -0800831 logic recov_err;
832 assign recov_err = flash_i.flash_alert_p | ~flash_i.flash_alert_n;
Timothy Chen16741102021-01-15 17:32:13 -0800833
834 logic recov_mp_err;
835 assign recov_mp_err = flash_mp_error;
836
837 logic recov_ecc_err;
838 assign recov_ecc_err = |flash_i.ecc_single_err | |flash_i.ecc_multi_err;
839
Timothy Chene1e0fd62021-04-07 16:13:28 -0700840 logic fatal_intg_err;
841 assign fatal_intg_err = flash_i.intg_err | intg_err;
842
843 assign alert_srcs = { fatal_intg_err,
844 recov_ecc_err,
Timothy Chen16741102021-01-15 17:32:13 -0800845 recov_mp_err,
Timothy Chen5302fff2021-01-22 14:36:54 -0800846 recov_err
Timothy Chen16741102021-01-15 17:32:13 -0800847 };
848
Timothy Chene1e0fd62021-04-07 16:13:28 -0700849 assign alert_tests = { reg2hw.alert_test.fatal_intg_err.q & reg2hw.alert_test.fatal_intg_err.qe,
850 reg2hw.alert_test.recov_ecc_err.q & reg2hw.alert_test.recov_ecc_err.qe,
Timothy Chen16741102021-01-15 17:32:13 -0800851 reg2hw.alert_test.recov_mp_err.q & reg2hw.alert_test.recov_mp_err.qe,
Timothy Chen5302fff2021-01-22 14:36:54 -0800852 reg2hw.alert_test.recov_err.q & reg2hw.alert_test.recov_err.qe
Timothy Chen16741102021-01-15 17:32:13 -0800853 };
854
Timothy Chene1e0fd62021-04-07 16:13:28 -0700855 localparam logic [NumAlerts-1:0] IsFatal = {1'b1, 1'b0, 1'b0, 1'b0};
Timothy Chen16741102021-01-15 17:32:13 -0800856 for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_senders
857 prim_alert_sender #(
Timothy Chene1e0fd62021-04-07 16:13:28 -0700858 .AsyncOn(AlertAsyncOn[i]),
859 .IsFatal(IsFatal[i])
Timothy Chen16741102021-01-15 17:32:13 -0800860 ) u_alert_sender (
861 .clk_i,
862 .rst_ni,
Timothy Chen06f78312021-01-20 18:43:27 -0800863 .alert_req_i(alert_srcs[i]),
864 .alert_test_i(alert_tests[i]),
Timothy Chen16741102021-01-15 17:32:13 -0800865 .alert_ack_o(),
Timothy Chen06f78312021-01-20 18:43:27 -0800866 .alert_state_o(),
Timothy Chen16741102021-01-15 17:32:13 -0800867 .alert_rx_i(alert_rx_i[i]),
868 .alert_tx_o(alert_tx_o[i])
869 );
870 end
871
872
873 //////////////////////////////////////
874 // Errors and Interrupts
875 //////////////////////////////////////
876
877 assign hw2reg.err_code.mp_err.d = 1'b1;
878 assign hw2reg.err_code.ecc_single_err.d = 1'b1;
879 assign hw2reg.err_code.ecc_multi_err.d = 1'b1;
880 assign hw2reg.err_code.flash_err.d = 1'b1;
881 assign hw2reg.err_code.flash_alert.d = 1'b1;
882 assign hw2reg.err_code.mp_err.de = flash_mp_error;
883 assign hw2reg.err_code.ecc_single_err.de = |flash_i.ecc_single_err;
884 assign hw2reg.err_code.ecc_multi_err.de = |flash_i.ecc_multi_err;
885 assign hw2reg.err_code.flash_err.de = flash_i.flash_err;
886 assign hw2reg.err_code.flash_alert.de = flash_i.flash_alert_p | ~flash_i.flash_alert_n;
887 assign hw2reg.err_addr.d = err_addr;
888 assign hw2reg.err_addr.de = flash_mp_error;
889
Timothy Chen4798f272021-03-24 17:19:42 -0700890 for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_single_err_cons
891 assign hw2reg.ecc_single_err_addr[bank].d = {flash_i.ecc_addr[bank], {BusByteWidth{1'b0}}};
892 assign hw2reg.ecc_single_err_addr[bank].de = flash_i.ecc_single_err[bank];
Timothy Chen16741102021-01-15 17:32:13 -0800893 end
894
Timothy Chen4798f272021-03-24 17:19:42 -0700895 for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_multi_err_cons
896 assign hw2reg.ecc_multi_err_addr[bank].d = {flash_i.ecc_addr[bank], {BusByteWidth{1'b0}}};
897 assign hw2reg.ecc_multi_err_addr[bank].de = flash_i.ecc_multi_err[bank];
898 end
Timothy Chenff4a7702020-10-27 15:08:53 -0700899
Timothy Chen4798f272021-03-24 17:19:42 -0700900 logic [7:0] single_err_cnt_d, multi_err_cnt_d;
901 always_comb begin
902 single_err_cnt_d = reg2hw.ecc_single_err_cnt.q;
903 multi_err_cnt_d = reg2hw.ecc_multi_err_cnt.q;
904
905 if (|flash_i.ecc_single_err && single_err_cnt_d < '1) begin
906 single_err_cnt_d = single_err_cnt_d + 1'b1;
907 end
908
909 if (|flash_i.ecc_multi_err && multi_err_cnt_d < '1) begin
910 multi_err_cnt_d = multi_err_cnt_d + 1'b1;
911 end
912 end
913
914 // feed back in error count
915 assign hw2reg.ecc_single_err_cnt.de = 1'b1;
916 assign hw2reg.ecc_single_err_cnt.d = single_err_cnt_d;
917 assign hw2reg.ecc_multi_err_cnt.de = 1'b1;
918 assign hw2reg.ecc_multi_err_cnt.d = multi_err_cnt_d;
919
920 // err code interrupt event
921 flash_ctrl_reg2hw_err_code_reg_t err_code_d, err_code_q;
922 logic err_code_intr_event;
923
924 assign err_code_d = reg2hw.err_code & reg2hw.err_code_intr_en;
925
926 always_ff @(posedge clk_i or negedge rst_ni) begin
927 if (!rst_ni) begin
928 err_code_q <= '0;
929 end else begin
930 err_code_q <= err_code_d;
931 end
932 end
933
934 assign err_code_intr_event = err_code_d != err_code_q;
935
936 // general interrupt events
937 logic [3:0] intr_src_d;
938 logic [3:0] intr_src_q;
939
940 assign intr_src_d = { ~prog_fifo_rvalid,
941 reg2hw.fifo_lvl.prog.q == prog_fifo_depth,
942 rd_fifo_full,
943 reg2hw.fifo_lvl.rd.q == rd_fifo_depth
944 };
Timothy Chenff4a7702020-10-27 15:08:53 -0700945
946 always_ff @(posedge clk_i or negedge rst_ni) begin
947 if (!rst_ni) begin
948 intr_src_q <= 4'h8; //prog_fifo is empty by default
Timothy Chen4798f272021-03-24 17:19:42 -0700949 end else begin
950 if (sw_sel) begin
951 intr_src_q[3:0] <= intr_src_d[3:0];
952 end
Timothy Chenff4a7702020-10-27 15:08:53 -0700953 end
954 end
955
Timothy Chen4798f272021-03-24 17:19:42 -0700956 // interrupt events
957 logic [4:0] intr_assert;
958 assign intr_assert[4] = err_code_intr_event;
959 assign intr_assert[3:0] = ~intr_src_q & intr_src_d;
Timothy Chenff4a7702020-10-27 15:08:53 -0700960
961 assign intr_prog_empty_o = reg2hw.intr_enable.prog_empty.q & reg2hw.intr_state.prog_empty.q;
962 assign intr_prog_lvl_o = reg2hw.intr_enable.prog_lvl.q & reg2hw.intr_state.prog_lvl.q;
963 assign intr_rd_full_o = reg2hw.intr_enable.rd_full.q & reg2hw.intr_state.rd_full.q;
964 assign intr_rd_lvl_o = reg2hw.intr_enable.rd_lvl.q & reg2hw.intr_state.rd_lvl.q;
965 assign intr_op_done_o = reg2hw.intr_enable.op_done.q & reg2hw.intr_state.op_done.q;
Timothy Chen4798f272021-03-24 17:19:42 -0700966 assign intr_err_o = reg2hw.intr_enable.err.q & reg2hw.intr_state.err.q;
967
968 assign hw2reg.intr_state.err.d = 1'b1;
969 assign hw2reg.intr_state.err.de = intr_assert[4] |
970 (reg2hw.intr_test.err.qe &
971 reg2hw.intr_test.err.q);
Timothy Chenff4a7702020-10-27 15:08:53 -0700972
973 assign hw2reg.intr_state.prog_empty.d = 1'b1;
974 assign hw2reg.intr_state.prog_empty.de = intr_assert[3] |
975 (reg2hw.intr_test.prog_empty.qe &
976 reg2hw.intr_test.prog_empty.q);
977
978 assign hw2reg.intr_state.prog_lvl.d = 1'b1;
979 assign hw2reg.intr_state.prog_lvl.de = intr_assert[2] |
980 (reg2hw.intr_test.prog_lvl.qe &
981 reg2hw.intr_test.prog_lvl.q);
982
983 assign hw2reg.intr_state.rd_full.d = 1'b1;
984 assign hw2reg.intr_state.rd_full.de = intr_assert[1] |
985 (reg2hw.intr_test.rd_full.qe &
986 reg2hw.intr_test.rd_full.q);
987
988 assign hw2reg.intr_state.rd_lvl.d = 1'b1;
989 assign hw2reg.intr_state.rd_lvl.de = intr_assert[0] |
990 (reg2hw.intr_test.rd_lvl.qe &
991 reg2hw.intr_test.rd_lvl.q);
992
Timothy Chenff4a7702020-10-27 15:08:53 -0700993 assign hw2reg.intr_state.op_done.d = 1'b1;
994 assign hw2reg.intr_state.op_done.de = sw_ctrl_done |
995 (reg2hw.intr_test.op_done.qe &
996 reg2hw.intr_test.op_done.q);
997
Timothy Chenff4a7702020-10-27 15:08:53 -0700998
Timothy Chen4798f272021-03-24 17:19:42 -0700999
Timothy Chenff4a7702020-10-27 15:08:53 -07001000 // Unused bits
1001 logic [BusByteWidth-1:0] unused_byte_sel;
1002 logic [top_pkg::TL_AW-1-BusAddrW:0] unused_higher_addr_bits;
1003 logic [top_pkg::TL_AW-1:0] unused_scratch;
1004
Timothy Chenff4a7702020-10-27 15:08:53 -07001005 // Unused signals
1006 assign unused_byte_sel = muxed_addr[BusByteWidth-1:0];
1007 assign unused_higher_addr_bits = muxed_addr[top_pkg::TL_AW-1:BusAddrW];
1008 assign unused_scratch = reg2hw.scratch;
1009
1010
1011 // Assertions
Timothy Chen8adb20d2021-03-25 16:49:04 -07001012 `ASSERT_KNOWN(TlDValidKnownO_A, core_tl_o.d_valid )
1013 `ASSERT_KNOWN(TlAReadyKnownO_A, core_tl_o.a_ready )
1014 `ASSERT_KNOWN(PrimTlDValidKnownO_A, prim_tl_o.d_valid )
1015 `ASSERT_KNOWN(PrimTlAReadyKnownO_A, prim_tl_o.a_ready )
Timothy Chenff4a7702020-10-27 15:08:53 -07001016 `ASSERT_KNOWN(FlashKnownO_A, {flash_o.req, flash_o.rd, flash_o.prog, flash_o.pg_erase,
1017 flash_o.bk_erase})
1018 `ASSERT_KNOWN_IF(FlashAddrKnown_A, flash_o.addr, flash_o.req)
1019 `ASSERT_KNOWN_IF(FlashProgKnown_A, flash_o.prog_data, flash_o.prog & flash_o.req)
1020 `ASSERT_KNOWN(IntrProgEmptyKnownO_A, intr_prog_empty_o)
1021 `ASSERT_KNOWN(IntrProgLvlKnownO_A, intr_prog_lvl_o )
1022 `ASSERT_KNOWN(IntrProgRdFullKnownO_A, intr_rd_full_o )
1023 `ASSERT_KNOWN(IntrRdLvlKnownO_A, intr_rd_lvl_o )
1024 `ASSERT_KNOWN(IntrOpDoneKnownO_A, intr_op_done_o )
Timothy Chen4798f272021-03-24 17:19:42 -07001025 `ASSERT_KNOWN(IntrErrO_A, intr_err_o )
Timothy Chenff4a7702020-10-27 15:08:53 -07001026
1027endmodule