blob: 9bfa16e8567f254045d8cd1d7916db23e9189bd3 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Flash Controller module.
//
package flash_ctrl_pkg;
// design parameters that can be altered through topgen
parameter int NumBanks = flash_ctrl_reg_pkg::RegNumBanks;
parameter int PagesPerBank = flash_ctrl_reg_pkg::RegPagesPerBank;
parameter int BusPgmResBytes = flash_ctrl_reg_pkg::RegBusPgmResBytes;
// fixed parameters of flash derived from topgen parameters
parameter int DataWidth = ${cfg['data_width']};
parameter int MetaDataWidth = ${cfg['metadata_width']};
parameter int InfoTypes = ${cfg['info_types']}; // How many types of info per bank
// The following hard-wired values are there to work-around verilator.
// For some reason if the values are assigned through parameters verilator thinks
// they are not constant
parameter int InfoTypeSize [InfoTypes] = '{
% for type in range(cfg['info_types']):
${cfg['infos_per_bank'][type]}${"," if not loop.last else ""}
% endfor
};
parameter int InfosPerBank = max_info_pages('{
% for type in range(cfg['info_types']):
${cfg['infos_per_bank'][type]}${"," if not loop.last else ""}
% endfor
});
parameter int WordsPerPage = ${cfg['words_per_page']}; // Number of flash words per page
parameter int BusWidth = top_pkg::TL_DW;
parameter int MpRegions = 8; // flash controller protection regions
parameter int FifoDepth = 16; // rd / prog fifos
parameter int InfoTypesWidth = prim_util_pkg::vbits(InfoTypes);
// flash phy parameters
parameter int DataByteWidth = prim_util_pkg::vbits(DataWidth / 8);
parameter int BankW = prim_util_pkg::vbits(NumBanks);
parameter int InfoPageW = prim_util_pkg::vbits(InfosPerBank);
parameter int PageW = prim_util_pkg::vbits(PagesPerBank);
parameter int WordW = prim_util_pkg::vbits(WordsPerPage);
parameter int AddrW = BankW + PageW + WordW; // all flash range
parameter int BankAddrW = PageW + WordW; // 1 bank of flash range
parameter int AllPagesW = BankW + PageW;
// flash ctrl / bus parameters
// flash / bus width may be different from actual flash word width
parameter int BusBytes = BusWidth / 8;
parameter int BusByteWidth = prim_util_pkg::vbits(BusBytes);
parameter int WidthMultiple = DataWidth / BusWidth;
// Number of bus words that can be programmed at once
parameter int BusPgmRes = BusPgmResBytes / BusBytes;
parameter int BusPgmResWidth = prim_util_pkg::vbits(BusPgmRes);
parameter int BusWordsPerPage = WordsPerPage * WidthMultiple;
parameter int BusWordW = prim_util_pkg::vbits(BusWordsPerPage);
parameter int BusAddrW = BankW + PageW + BusWordW;
parameter int BusBankAddrW = PageW + BusWordW;
parameter int PhyAddrStart = BusWordW - WordW;
// fifo parameters
parameter int FifoDepthW = prim_util_pkg::vbits(FifoDepth+1);
// The end address in bus words for each kind of partition in each bank
parameter logic [PageW-1:0] DataPartitionEndAddr = PagesPerBank - 1;
//parameter logic [PageW-1:0] InfoPartitionEndAddr [InfoTypes] = '{
% for type in range((cfg['info_types'])):
// ${cfg['infos_per_bank'][type]-1}${"," if not loop.last else ""}
% endfor
//};
parameter logic [PageW-1:0] InfoPartitionEndAddr [InfoTypes] = '{
% for type in range((cfg['info_types'])):
InfoTypeSize[${type}] - 1${"," if not loop.last else ""}
% endfor
};
////////////////////////////
// All memory protection, seed related parameters
// Those related for seed pages should be template candidates
////////////////////////////
// parameters for connected components
parameter int SeedWidth = 256;
parameter int KeyWidth = 128;
parameter int EdnWidth = edn_pkg::ENDPOINT_BUS_WIDTH;
typedef logic [KeyWidth-1:0] flash_key_t;
// Default Lfsr configurations
// These LFSR parameters have been generated with
// $ util/design/gen-lfsr-seed.py --width 32 --seed 1274809145 --prefix ""
parameter int LfsrWidth = 32;
typedef logic [LfsrWidth-1:0] lfsr_seed_t;
typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t;
parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'ha8cee782;
parameter lfsr_perm_t RndCnstLfsrPermDefault = {
160'hd60bc7d86445da9347e0ccdd05b281df95238bb5
};
// These LFSR parameters have been generated with
// $ util/design/gen-lfsr-seed.py --width 64 --seed 691876113 --prefix ""
// lcmgr phase enum
typedef enum logic [1:0] {
PhaseSeed,
PhaseRma,
PhaseNone,
PhaseInvalid
} flash_lcmgr_phase_e;
// alias for super long reg_pkg typedef
typedef flash_ctrl_reg_pkg::flash_ctrl_reg2hw_bank0_info0_page_cfg_mreg_t info_page_cfg_t;
typedef flash_ctrl_reg_pkg::flash_ctrl_reg2hw_mp_region_cfg_mreg_t mp_region_cfg_t;
// memory protection specific structs
typedef struct packed {
logic [InfoTypesWidth-1:0] sel;
logic [AllPagesW-1:0] addr;
} page_addr_t;
typedef struct packed {
page_addr_t page;
flash_lcmgr_phase_e phase;
info_page_cfg_t cfg;
} info_page_attr_t;
typedef struct packed {
flash_lcmgr_phase_e phase;
mp_region_cfg_t cfg;
} data_region_attr_t;
// flash life cycle / key manager management constants
// One page for creator seeds
// One page for owner seeds
// One page for isolated flash page
parameter int NumSeeds = 2;
parameter int SeedBank = 0;
parameter int SeedInfoSel = 0;
parameter int CreatorSeedIdx = 0;
parameter int OwnerSeedIdx = 1;
parameter int CreatorInfoPage = 1;
parameter int OwnerInfoPage = 2;
parameter int IsolatedInfoPage = 3;
// which page of which info type of which bank for seed selection
parameter page_addr_t SeedInfoPageSel [NumSeeds] = '{
'{
sel: SeedInfoSel,
addr: {SeedBank, CreatorInfoPage}
},
'{
sel: SeedInfoSel,
addr: {SeedBank, OwnerInfoPage}
}
};
// which page of which info type of which bank for isolated partition
parameter page_addr_t IsolatedPageSel = '{
sel: SeedInfoSel,
addr: {SeedBank, IsolatedInfoPage}
};
// hardware interface memory protection rules
parameter int HwInfoRules = 3;
parameter int HwDataRules = 1;
parameter info_page_cfg_t CfgAllowRead = '{
en: 1'b1,
rd_en: 1'b1,
prog_en: 1'b0,
erase_en: 1'b0,
scramble_en: 1'b0,
ecc_en: 1'b0, // TBD, update to 1 once tb supports ECC
he_en: 1'b1
};
parameter info_page_cfg_t CfgAllowReadProgErase = '{
en: 1'b1,
rd_en: 1'b1,
prog_en: 1'b1,
erase_en: 1'b1,
scramble_en: 1'b1,
ecc_en: 1'b1,
he_en: 1'b1 // HW assumes high endurance
};
parameter info_page_attr_t HwInfoPageAttr[HwInfoRules] = '{
'{
page: SeedInfoPageSel[CreatorSeedIdx],
phase: PhaseSeed,
cfg: CfgAllowRead
},
'{
page: SeedInfoPageSel[OwnerSeedIdx],
phase: PhaseSeed,
cfg: CfgAllowRead
},
'{
page: SeedInfoPageSel[OwnerSeedIdx],
phase: PhaseRma,
cfg: CfgAllowReadProgErase
}
};
parameter data_region_attr_t HwDataAttr[HwDataRules] = '{
'{
phase: PhaseRma,
cfg: '{
en: 1'b1,
rd_en: 1'b1,
prog_en: 1'b1,
erase_en: 1'b1,
scramble_en: 1'b1,
ecc_en: 1'b1,
he_en: 1'b1, // HW assumes high endurance
base: '0,
size: '{default:'1}
}
}
};
////////////////////////////
// Design time constants
////////////////////////////
parameter flash_key_t RndCnstAddrKeyDefault =
128'h5d707f8a2d01d400928fa691c6a6e0a4;
parameter flash_key_t RndCnstDataKeyDefault =
128'h39953618f2ca6f674af39f64975ea1f5;
////////////////////////////
// Flash operation related enums
////////////////////////////
// Flash Operations Supported
typedef enum logic [1:0] {
FlashOpRead = 2'h0,
FlashOpProgram = 2'h1,
FlashOpErase = 2'h2,
FlashOpInvalid = 2'h3
} flash_op_e;
// Flash Program Operations Supported
typedef enum logic {
FlashProgNormal = 0,
FlashProgRepair = 1
} flash_prog_e;
parameter int ProgTypes = 2;
// Flash Erase Operations Supported
typedef enum logic {
FlashErasePage = 0,
FlashEraseBank = 1
} flash_erase_e;
// Flash function select
typedef enum logic [1:0] {
NoneSel,
SwSel,
HwSel
} flash_sel_e;
// Flash tlul to fifo direction
typedef enum logic {
WriteDir = 1'b0,
ReadDir = 1'b1
} flash_flfo_dir_e;
// Flash partition type
typedef enum logic {
FlashPartData = 1'b0,
FlashPartInfo = 1'b1
} flash_part_e;
// Flash controller to memory
typedef struct packed {
logic req;
logic scramble_en;
logic ecc_en;
logic he_en;
logic rd;
logic prog;
logic pg_erase;
logic bk_erase;
logic erase_suspend;
flash_part_e part;
logic [InfoTypesWidth-1:0] info_sel;
logic [BusAddrW-1:0] addr;
logic [BusWidth-1:0] prog_data;
logic prog_last;
flash_prog_e prog_type;
mp_region_cfg_t [MpRegions:0] region_cfgs;
logic [KeyWidth-1:0] addr_key;
logic [KeyWidth-1:0] data_key;
logic rd_buf_en;
tlul_pkg::tl_h2d_t tl_flash_c2p;
} flash_req_t;
// default value of flash_req_t (for dangling ports)
parameter flash_req_t FLASH_REQ_DEFAULT = '{
req: '0,
scramble_en: '0,
ecc_en: '0,
he_en: '0,
rd: '0,
prog: '0,
pg_erase: '0,
bk_erase: '0,
erase_suspend: '0,
part: FlashPartData,
info_sel: '0,
addr: '0,
prog_data: '0,
prog_last: '0,
prog_type: FlashProgNormal,
region_cfgs: '0,
addr_key: RndCnstAddrKeyDefault,
data_key: RndCnstDataKeyDefault,
rd_buf_en: 1'b0,
tl_flash_c2p: '0
};
// memory to flash controller
typedef struct packed {
logic [ProgTypes-1:0] prog_type_avail;
logic rd_done;
logic prog_done;
logic erase_done;
logic rd_err;
logic [BusWidth-1:0] rd_data;
logic init_busy;
tlul_pkg::tl_d2h_t tl_flash_p2c;
} flash_rsp_t;
// default value of flash_rsp_t (for dangling ports)
parameter flash_rsp_t FLASH_RSP_DEFAULT = '{
prog_type_avail: '{default: '1},
rd_done: 1'b0,
prog_done: 1'b0,
erase_done: 1'b0,
rd_err: '0,
rd_data: '0,
init_busy: 1'b0,
tl_flash_p2c: '0
};
// RMA entries
typedef struct packed {
logic [BankW-1:0] bank;
flash_part_e part;
logic [InfoTypesWidth-1:0] info_sel;
logic [PageW:0] start_page;
logic [PageW:0] num_pages;
} rma_wipe_entry_t;
// entries to be wiped
parameter int WipeEntries = 3;
parameter rma_wipe_entry_t RmaWipeEntries[WipeEntries] = '{
'{
bank: SeedBank,
part: FlashPartInfo,
info_sel: SeedInfoSel,
start_page: OwnerInfoPage,
num_pages: 1
},
'{
bank: 0,
part: FlashPartData,
info_sel: 0,
start_page: 0,
num_pages: PagesPerBank
},
'{
bank: 1,
part: FlashPartData,
info_sel: 0,
start_page: 0,
num_pages: PagesPerBank
}
};
// flash_ctrl to keymgr
typedef struct packed {
logic [NumSeeds-1:0][SeedWidth-1:0] seeds;
} keymgr_flash_t;
parameter keymgr_flash_t KEYMGR_FLASH_DEFAULT = '{
seeds: '{
256'h9152e32c9380a4bcc3e0ab263581e6b0e8825186e1e445631646e8bef8c45d47,
256'hfa365df52da48cd752fb3a026a8e608f0098cfe5fa9810494829d0cd9479eb78
}
};
// dft_en jtag selection
typedef enum logic [2:0] {
FlashLcTckSel,
FlashLcTdiSel,
FlashLcTmsSel,
FlashLcTdoSel,
FlashBistSel,
FlashLcDftLast
} flash_lc_jtag_e;
// find the max number pages among info types
function automatic integer max_info_pages(int infos[InfoTypes]);
int current_max = 0;
for (int i = 0; i < InfoTypes; i++) begin
if (infos[i] > current_max) begin
current_max = infos[i];
end
end
return current_max;
endfunction // max_info_banks
endpackage : flash_ctrl_pkg