Timothy Chen | ff4a770 | 2020-10-27 15:08:53 -0700 | [diff] [blame^] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | // |
| 5 | // Flash Controller module. |
| 6 | // |
| 7 | |
| 8 | package flash_ctrl_pkg; |
| 9 | |
| 10 | // design parameters that can be altered through topgen |
| 11 | parameter int NumBanks = flash_ctrl_reg_pkg::RegNumBanks; |
| 12 | parameter int PagesPerBank = flash_ctrl_reg_pkg::RegPagesPerBank; |
| 13 | |
| 14 | // fixed parameters of flash derived from topgen parameters |
| 15 | parameter int DataWidth = ${cfg['data_width']}; |
| 16 | parameter int MetaDataWidth = ${cfg['metadata_width']}; |
| 17 | parameter int InfoTypes = ${cfg['info_types']}; // How many types of info per bank |
| 18 | |
| 19 | // The following hard-wired values are there to work-around verilator. |
| 20 | // For some reason if the values are assigned through parameters verilator thinks |
| 21 | // they are not constant |
| 22 | parameter int InfoTypeSize [InfoTypes] = '{ |
| 23 | % for type in range(cfg['info_types']): |
| 24 | ${cfg['infos_per_bank'][type]}${"," if not loop.last else ""} |
| 25 | % endfor |
| 26 | }; |
| 27 | parameter int InfosPerBank = max_info_pages('{ |
| 28 | % for type in range(cfg['info_types']): |
| 29 | ${cfg['infos_per_bank'][type]}${"," if not loop.last else ""} |
| 30 | % endfor |
| 31 | }); |
| 32 | parameter int WordsPerPage = ${cfg['words_per_page']}; // Number of flash words per page |
| 33 | parameter int BusWidth = top_pkg::TL_DW; |
| 34 | parameter int MpRegions = 8; // flash controller protection regions |
| 35 | parameter int FifoDepth = 16; // rd / prog fifos |
| 36 | parameter int InfoTypesWidth = prim_util_pkg::vbits(InfoTypes); |
| 37 | |
| 38 | // flash phy parameters |
| 39 | parameter int DataByteWidth = prim_util_pkg::vbits(DataWidth / 8); |
| 40 | parameter int BankW = prim_util_pkg::vbits(NumBanks); |
| 41 | parameter int InfoPageW = prim_util_pkg::vbits(InfosPerBank); |
| 42 | parameter int PageW = prim_util_pkg::vbits(PagesPerBank); |
| 43 | parameter int WordW = prim_util_pkg::vbits(WordsPerPage); |
| 44 | parameter int AddrW = BankW + PageW + WordW; // all flash range |
| 45 | parameter int BankAddrW = PageW + WordW; // 1 bank of flash range |
| 46 | parameter int AllPagesW = BankW + PageW; |
| 47 | |
| 48 | // flash ctrl / bus parameters |
| 49 | // flash / bus width may be different from actual flash word width |
| 50 | parameter int BusByteWidth = prim_util_pkg::vbits(BusWidth / 8); |
| 51 | parameter int WidthMultiple = DataWidth / BusWidth; |
| 52 | parameter int BusWordsPerPage = WordsPerPage * WidthMultiple; |
| 53 | parameter int BusWordW = prim_util_pkg::vbits(BusWordsPerPage); |
| 54 | parameter int BusAddrW = BankW + PageW + BusWordW; |
| 55 | parameter int BusBankAddrW = PageW + BusWordW; |
| 56 | parameter int PhyAddrStart = BusWordW - WordW; |
| 57 | |
| 58 | // fifo parameters |
| 59 | parameter int FifoDepthW = prim_util_pkg::vbits(FifoDepth+1); |
| 60 | |
| 61 | // The end address in bus words for each kind of partition in each bank |
| 62 | parameter logic [PageW-1:0] DataPartitionEndAddr = PagesPerBank - 1; |
| 63 | parameter logic [PageW-1:0] InfoPartitionEndAddr [InfoTypes] = '{ |
| 64 | InfoTypeSize[0] - 1, |
| 65 | InfoTypeSize[1] - 1 |
| 66 | }; |
| 67 | |
| 68 | //////////////////////////// |
| 69 | // All memory protection, seed related parameters |
| 70 | // Those related for seed pages should be template candidates |
| 71 | //////////////////////////// |
| 72 | |
| 73 | // parameters for connected components |
| 74 | parameter int SeedWidth = 256; |
| 75 | |
| 76 | // lcmgr phase enum |
| 77 | typedef enum logic [1:0] { |
| 78 | PhaseSeed, |
| 79 | PhaseRma, |
| 80 | PhaseNone, |
| 81 | PhaseInvalid |
| 82 | } flash_lcmgr_phase_e; |
| 83 | |
| 84 | // alias for super long reg_pkg typedef |
| 85 | typedef flash_ctrl_reg_pkg::flash_ctrl_reg2hw_bank0_info0_page_cfg_mreg_t info_page_cfg_t; |
| 86 | typedef flash_ctrl_reg_pkg::flash_ctrl_reg2hw_mp_region_cfg_mreg_t mp_region_cfg_t; |
| 87 | |
| 88 | // memory protection specific structs |
| 89 | typedef struct packed { |
| 90 | logic [InfoTypesWidth-1:0] sel; |
| 91 | logic [AllPagesW-1:0] addr; |
| 92 | } page_addr_t; |
| 93 | |
| 94 | typedef struct packed { |
| 95 | page_addr_t page; |
| 96 | flash_lcmgr_phase_e phase; |
| 97 | info_page_cfg_t cfg; |
| 98 | } info_page_attr_t; |
| 99 | |
| 100 | typedef struct packed { |
| 101 | flash_lcmgr_phase_e phase; |
| 102 | mp_region_cfg_t cfg; |
| 103 | } data_region_attr_t; |
| 104 | |
| 105 | // flash life cycle / key manager management constants |
| 106 | // One page for creator seeds |
| 107 | // One page for owner seeds |
| 108 | parameter int NumSeeds = 2; |
| 109 | parameter int SeedBank = 0; |
| 110 | parameter int SeedInfoSel = 0; |
| 111 | parameter int CreatorSeedIdx = 0; |
| 112 | parameter int OwnerSeedIdx = 1; |
| 113 | parameter int CreatorInfoPage = 1; |
| 114 | parameter int OwnerInfoPage = 2; |
| 115 | |
| 116 | // which page of which info type of which bank |
| 117 | parameter page_addr_t SeedInfoPageSel [NumSeeds] = '{ |
| 118 | '{ |
| 119 | sel: SeedInfoSel, |
| 120 | addr: {SeedBank, CreatorInfoPage} |
| 121 | }, |
| 122 | |
| 123 | '{ |
| 124 | sel: SeedInfoSel, |
| 125 | addr: {SeedBank, OwnerInfoPage} |
| 126 | } |
| 127 | }; |
| 128 | |
| 129 | // hardware interface memory protection rules |
| 130 | parameter int HwInfoRules = 3; |
| 131 | parameter int HwDataRules = 1; |
| 132 | |
| 133 | parameter info_page_cfg_t CfgAllowRead = '{ |
| 134 | en: 1'b1, |
| 135 | rd_en: 1'b1, |
| 136 | prog_en: 1'b0, |
| 137 | erase_en: 1'b0, |
| 138 | scramble_en: 1'b0 // TBD, update to 1 once tb supports ECC |
| 139 | }; |
| 140 | |
| 141 | parameter info_page_cfg_t CfgAllowReadErase = '{ |
| 142 | en: 1'b1, |
| 143 | rd_en: 1'b1, |
| 144 | prog_en: 1'b0, |
| 145 | erase_en: 1'b1, |
| 146 | scramble_en: 1'b0 // TBD, update to 1 once tb supports ECC |
| 147 | }; |
| 148 | |
| 149 | parameter info_page_attr_t HwInfoPageAttr[HwInfoRules] = '{ |
| 150 | '{ |
| 151 | page: SeedInfoPageSel[CreatorSeedIdx], |
| 152 | phase: PhaseSeed, |
| 153 | cfg: CfgAllowRead |
| 154 | }, |
| 155 | |
| 156 | '{ |
| 157 | page: SeedInfoPageSel[OwnerSeedIdx], |
| 158 | phase: PhaseSeed, |
| 159 | cfg: CfgAllowRead |
| 160 | }, |
| 161 | |
| 162 | '{ |
| 163 | page: SeedInfoPageSel[OwnerSeedIdx], |
| 164 | phase: PhaseRma, |
| 165 | cfg: CfgAllowReadErase |
| 166 | } |
| 167 | }; |
| 168 | |
| 169 | parameter data_region_attr_t HwDataAttr[HwDataRules] = '{ |
| 170 | '{ |
| 171 | phase: PhaseRma, |
| 172 | cfg: '{ |
| 173 | en: 1'b1, |
| 174 | rd_en: 1'b1, |
| 175 | prog_en: 1'b0, |
| 176 | erase_en: 1'b1, |
| 177 | scramble_en: 1'b0, |
| 178 | base: '0, |
| 179 | size: '{default:'1} |
| 180 | } |
| 181 | } |
| 182 | }; |
| 183 | |
| 184 | |
| 185 | //////////////////////////// |
| 186 | // Flash operation related enums |
| 187 | //////////////////////////// |
| 188 | |
| 189 | // Flash Operations Supported |
| 190 | typedef enum logic [1:0] { |
| 191 | FlashOpRead = 2'h0, |
| 192 | FlashOpProgram = 2'h1, |
| 193 | FlashOpErase = 2'h2, |
| 194 | FlashOpInvalid = 2'h3 |
| 195 | } flash_op_e; |
| 196 | |
| 197 | // Flash Program Operations Supported |
| 198 | typedef enum logic { |
| 199 | FlashProgNormal = 0, |
| 200 | FlashProgRepair = 1 |
| 201 | } flash_prog_e; |
| 202 | parameter int ProgTypes = 2; |
| 203 | |
| 204 | // Flash Erase Operations Supported |
| 205 | typedef enum logic { |
| 206 | FlashErasePage = 0, |
| 207 | FlashEraseBank = 1 |
| 208 | } flash_erase_e; |
| 209 | |
| 210 | // Flash function select |
| 211 | typedef enum logic [1:0] { |
| 212 | NoneSel, |
| 213 | SwSel, |
| 214 | HwSel |
| 215 | } flash_sel_e; |
| 216 | |
| 217 | // Flash tlul to fifo direction |
| 218 | typedef enum logic { |
| 219 | WriteDir = 1'b0, |
| 220 | ReadDir = 1'b1 |
| 221 | } flash_flfo_dir_e; |
| 222 | |
| 223 | // Flash partition type |
| 224 | typedef enum logic { |
| 225 | FlashPartData = 1'b0, |
| 226 | FlashPartInfo = 1'b1 |
| 227 | } flash_part_e; |
| 228 | |
| 229 | // Flash controller to memory |
| 230 | typedef struct packed { |
| 231 | logic req; |
| 232 | logic scramble_en; |
| 233 | logic rd; |
| 234 | logic prog; |
| 235 | logic pg_erase; |
| 236 | logic bk_erase; |
| 237 | flash_part_e part; |
| 238 | logic [BusAddrW-1:0] addr; |
| 239 | logic [BusWidth-1:0] prog_data; |
| 240 | logic prog_last; |
| 241 | flash_prog_e prog_type; |
| 242 | mp_region_cfg_t [MpRegions:0] region_cfgs; |
| 243 | logic [127:0] addr_key; |
| 244 | logic [127:0] data_key; |
| 245 | } flash_req_t; |
| 246 | |
| 247 | // default value of flash_req_t (for dangling ports) |
| 248 | parameter flash_req_t FLASH_REQ_DEFAULT = '{ |
| 249 | req: 1'b0, |
| 250 | scramble_en: 1'b0, |
| 251 | rd: 1'b0, |
| 252 | prog: 1'b0, |
| 253 | pg_erase: 1'b0, |
| 254 | bk_erase: 1'b0, |
| 255 | part: FlashPartData, |
| 256 | addr: '0, |
| 257 | prog_data: '0, |
| 258 | prog_last: '0, |
| 259 | prog_type: FlashProgNormal, |
| 260 | region_cfgs: '0, |
| 261 | addr_key: 128'hDEADBEEFBEEFFACEDEADBEEF5A5AA5A5, |
| 262 | data_key: 128'hDEADBEEF5A5AA5A5DEADBEEFBEEFFACE |
| 263 | }; |
| 264 | |
| 265 | // memory to flash controller |
| 266 | typedef struct packed { |
| 267 | logic [ProgTypes-1:0] prog_type_avail; |
| 268 | logic rd_done; |
| 269 | logic prog_done; |
| 270 | logic erase_done; |
| 271 | logic rd_err; |
| 272 | logic [BusWidth-1:0] rd_data; |
| 273 | logic init_busy; |
| 274 | } flash_rsp_t; |
| 275 | |
| 276 | // default value of flash_rsp_t (for dangling ports) |
| 277 | parameter flash_rsp_t FLASH_RSP_DEFAULT = '{ |
| 278 | prog_type_avail: '{default: '1}, |
| 279 | rd_done: 1'b0, |
| 280 | prog_done: 1'b0, |
| 281 | erase_done: 1'b0, |
| 282 | rd_err: '0, |
| 283 | rd_data: '0, |
| 284 | init_busy: 1'b0 |
| 285 | }; |
| 286 | |
| 287 | //////////////////////////// |
| 288 | // The following inter-module should be moved to OTP/LC |
| 289 | //////////////////////////// |
| 290 | |
| 291 | // otp to flash_ctrl |
| 292 | typedef struct packed { |
| 293 | logic [127:0] addr_key; |
| 294 | logic [127:0] data_key; |
| 295 | // TBD: this signal will become multi-bit in the future |
| 296 | logic seed_valid; |
| 297 | logic prog_repair_en; |
| 298 | } otp_flash_t; |
| 299 | |
| 300 | // lc to flash_ctrl |
| 301 | typedef struct packed { |
| 302 | // TBD: this signal will become multi-bit in the future |
| 303 | logic rma_req; |
| 304 | logic [BusWidth-1:0] rma_req_token; |
| 305 | logic provision_en; |
| 306 | } lc_flash_req_t; |
| 307 | |
| 308 | // flash_ctrl to lc |
| 309 | typedef struct packed { |
| 310 | logic rma_ack; |
| 311 | logic [BusWidth-1:0] rma_ack_token; |
| 312 | } lc_flash_rsp_t; |
| 313 | |
| 314 | // flash_ctrl to keymgr |
| 315 | typedef struct packed { |
| 316 | logic [NumSeeds-1:0][SeedWidth-1:0] seeds; |
| 317 | } keymgr_flash_t; |
| 318 | |
| 319 | // place holder for interface to EDN, replace with real one later |
| 320 | typedef struct packed { |
| 321 | logic valid; |
| 322 | logic [3:0] entropy; |
| 323 | } edn_entropy_t; |
| 324 | |
| 325 | // default value of otp_flash_t |
| 326 | // These are hardwired default values that should never be used. |
| 327 | // Real values are individualized and supplied from OTP. |
| 328 | parameter otp_flash_t OTP_FLASH_DEFAULT = '{ |
| 329 | addr_key: 128'hDEADBEEFBEEFFACEDEADBEEF5A5AA5A5, |
| 330 | data_key: 128'hDEADBEEF5A5AA5A5DEADBEEFBEEFFACE, |
| 331 | seed_valid: 1'b1, |
| 332 | prog_repair_en: 1'b1 |
| 333 | }; |
| 334 | |
| 335 | parameter lc_flash_req_t LC_FLASH_REQ_DEFAULT = '{ |
| 336 | rma_req: 1'b0, |
| 337 | rma_req_token: '0, |
| 338 | provision_en: 1'b1 |
| 339 | }; |
| 340 | |
| 341 | parameter edn_entropy_t EDN_ENTROPY_DEFAULT = '{ |
| 342 | valid: 1'b1, |
| 343 | entropy: '0 |
| 344 | }; |
| 345 | |
| 346 | |
| 347 | // find the max number pages among info types |
| 348 | function automatic integer max_info_pages(int infos[InfoTypes]); |
| 349 | int current_max = 0; |
| 350 | for (int i = 0; i < InfoTypes; i++) begin |
| 351 | if (infos[i] > current_max) begin |
| 352 | current_max = infos[i]; |
| 353 | end |
| 354 | end |
| 355 | return current_max; |
| 356 | endfunction // max_info_banks |
| 357 | |
| 358 | |
| 359 | endpackage : flash_ctrl_pkg |