blob: a8278f7525d80376bb86a2dc71ecccd418a42b27 [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 constants
parameter int DataWidth = top_pkg::FLASH_DATA_WIDTH;
parameter int NumBanks = top_pkg::FLASH_BANKS;
parameter int InfoTypes = top_pkg::FLASH_INFO_TYPES; // How many types of info per bank
// TBD, 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
`ifdef VERILATOR
parameter int InfoTypeSize [InfoTypes] = '{4, 4}; // size per bank
parameter int InfosPerBank = max_info_pages('{4, 4});
`else
parameter int InfoTypeSize [InfoTypes] = top_pkg::FLASH_INFO_PER_BANK; // size per bank
parameter int InfosPerBank = max_info_pages(InfoTypeSize);
`endif
parameter int PagesPerBank = top_pkg::FLASH_PAGES_PER_BANK; // Data pages per bank
parameter int WordsPerPage = top_pkg::FLASH_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 BusByteWidth = prim_util_pkg::vbits(BusWidth / 8);
parameter int WidthMultiple = DataWidth / BusWidth;
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] = '{
InfoTypeSize[0] - 1,
InfoTypeSize[1] - 1
};
////////////////////////////
// All memory protection, seed related parameters
// Those related for seed pages should be template candidates
////////////////////////////
// parameters for connected components
parameter int SeedWidth = 256;
// 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
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;
// which page of which info type of which bank
parameter page_addr_t SeedInfoPageSel [NumSeeds] = '{
'{
sel: SeedInfoSel,
addr: {SeedBank, CreatorInfoPage}
},
'{
sel: SeedInfoSel,
addr: {SeedBank, OwnerInfoPage}
}
};
// 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
};
parameter info_page_cfg_t CfgAllowReadErase = '{
en: 1'b1,
rd_en: 1'b1,
prog_en: 1'b0,
erase_en: 1'b1
};
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: CfgAllowReadErase
}
};
parameter data_region_attr_t HwDataAttr[HwDataRules] = '{
'{
phase: PhaseRma,
cfg: '{
en: 1'b1,
rd_en: 1'b1,
prog_en: 1'b0,
erase_en: 1'b1,
base: '0,
size: '{default:'1}
}
}
};
////////////////////////////
// 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 rd;
logic prog;
logic pg_erase;
logic bk_erase;
flash_part_e part;
logic [BusAddrW-1:0] addr;
logic [BusWidth-1:0] prog_data;
logic prog_last;
flash_prog_e prog_type;
logic scramble_en;
logic [127:0] addr_key;
logic [127:0] data_key;
} flash_req_t;
// default value of flash_req_t (for dangling ports)
parameter flash_req_t FLASH_REQ_DEFAULT = '{
req: 1'b0,
rd: 1'b0,
prog: 1'b0,
pg_erase: 1'b0,
bk_erase: 1'b0,
part: FlashPartData,
addr: '0,
prog_data: '0,
prog_last: '0,
prog_type: FlashProgNormal,
scramble_en: '0,
addr_key: 128'hDEADBEEFBEEFFACEDEADBEEF5A5AA5A5,
data_key: 128'hDEADBEEF5A5AA5A5DEADBEEFBEEFFACE
};
// 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;
} 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
};
////////////////////////////
// The following inter-module should be moved to OTP/LC
////////////////////////////
// otp to flash_ctrl
typedef struct packed {
logic [127:0] addr_key;
logic [127:0] data_key;
// TBD: this signal will become multi-bit in the future
logic seed_valid;
logic prog_repair_en;
} otp_flash_t;
// lc to flash_ctrl
typedef struct packed {
// TBD: this signal will become multi-bit in the future
logic rma_req;
logic [BusWidth-1:0] rma_req_token;
logic provision_en;
} lc_flash_req_t;
// flash_ctrl to lc
typedef struct packed {
logic rma_ack;
logic [BusWidth-1:0] rma_ack_token;
} lc_flash_rsp_t;
// flash_ctrl to keymgr
typedef struct packed {
logic [NumSeeds-1:0][SeedWidth-1:0] seeds;
} keymgr_flash_t;
// place holder for interface to EDN, replace with real one later
typedef struct packed {
logic valid;
logic [3:0] entropy;
} edn_entropy_t;
// default value of otp_flash_t
// These are hardwired default values that should never be used.
// Real values are individualized and supplied from OTP.
parameter otp_flash_t OTP_FLASH_DEFAULT = '{
addr_key: 128'hDEADBEEFBEEFFACEDEADBEEF5A5AA5A5,
data_key: 128'hDEADBEEF5A5AA5A5DEADBEEFBEEFFACE,
seed_valid: 1'b1,
prog_repair_en: 1'b1
};
parameter lc_flash_req_t LC_FLASH_REQ_DEFAULT = '{
rma_req: 1'b0,
rma_req_token: '0,
provision_en: 1'b1
};
parameter edn_entropy_t EDN_ENTROPY_DEFAULT = '{
valid: 1'b1,
entropy: '0
};
// 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