blob: 0e68202d00c65355988c824b9e7d410d71fe436e [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
package tlul_pkg;
// this can be either PPC or BINTREE
// there is no functional difference, but timing and area behavior is different
// between the two instances. PPC can result in smaller implementations when timing
// is not critical, whereas BINTREE is favorable when timing pressure is high (but this
// may also result in a larger implementation). on FPGA targets, BINTREE is favorable
// both in terms of area and timing.
parameter ArbiterImpl = "PPC";
typedef enum logic [2:0] {
PutFullData = 3'h 0,
PutPartialData = 3'h 1,
Get = 3'h 4
} tl_a_op_e;
typedef enum logic [2:0] {
AccessAck = 3'h 0,
AccessAckData = 3'h 1
} tl_d_op_e;
typedef enum logic [2:0] {
InstrEn = 3'b101,
InstrDis = 3'b010
} tl_instr_en_e;
// used for intermodule connections
typedef tl_instr_en_e tl_instr_en_t;
typedef enum logic [1:0] {
InstrType = 2'b01,
DataType = 2'b10
} tl_type_e;
parameter int H2DCmdMaxWidth = 57;
parameter int H2DCmdIntgWidth = 7;
parameter int H2DCmdFullWidth = H2DCmdMaxWidth + H2DCmdIntgWidth;
parameter int D2HRspMaxWidth = 57;
parameter int D2HRspIntgWidth = 7;
parameter int D2HRspFullWidth = D2HRspMaxWidth + D2HRspIntgWidth;
parameter int DataMaxWidth = 32;
parameter int DataIntgWidth = 7;
parameter int DataFullWidth = DataMaxWidth + DataIntgWidth;
typedef struct packed {
logic [4:0] rsvd;
tl_type_e tl_type;
logic [H2DCmdIntgWidth-1:0] cmd_intg;
logic [DataIntgWidth-1:0] data_intg;
} tl_a_user_t;
parameter tl_a_user_t TL_A_USER_DEFAULT = '{
rsvd: '0,
tl_type: DataType,
cmd_intg: '0,
data_intg: '0
};
typedef struct packed {
tl_type_e tl_type;
logic [top_pkg::TL_AW-1:0] addr;
tl_a_op_e opcode;
logic [top_pkg::TL_DBW-1:0] mask;
} tl_h2d_cmd_intg_t;
typedef struct packed {
logic a_valid;
tl_a_op_e a_opcode;
logic [2:0] a_param;
logic [top_pkg::TL_SZW-1:0] a_size;
logic [top_pkg::TL_AIW-1:0] a_source;
logic [top_pkg::TL_AW-1:0] a_address;
logic [top_pkg::TL_DBW-1:0] a_mask;
logic [top_pkg::TL_DW-1:0] a_data;
tl_a_user_t a_user;
logic d_ready;
} tl_h2d_t;
localparam tl_h2d_t TL_H2D_DEFAULT = '{
d_ready: 1'b1,
a_opcode: tl_a_op_e'('0),
a_user: tl_a_user_t'('0),
default: '0
};
typedef struct packed {
logic [D2HRspIntgWidth-1:0] rsp_intg;
logic [DataIntgWidth-1:0] data_intg;
} tl_d_user_t;
parameter tl_d_user_t TL_D_USER_DEFAULT = '{
rsp_intg: '0,
data_intg: '0
};
typedef struct packed {
logic d_valid;
tl_d_op_e d_opcode;
logic [2:0] d_param;
logic [top_pkg::TL_SZW-1:0] d_size; // Bouncing back a_size
logic [top_pkg::TL_AIW-1:0] d_source;
logic [top_pkg::TL_DIW-1:0] d_sink;
logic [top_pkg::TL_DW-1:0] d_data;
tl_d_user_t d_user;
logic d_error;
logic a_ready;
} tl_d2h_t;
typedef struct packed {
tl_d_op_e opcode;
logic [top_pkg::TL_SZW-1:0] size;
// Temporarily removed because source changes throughout the fabric
// and thus cannot be used for end-to-end checking.
// A different PR will propose a work-around (a hoaky one) to see if
// it gets the job done.
//logic [top_pkg::TL_AIW-1:0] source;
logic error;
} tl_d2h_rsp_intg_t;
localparam tl_d2h_t TL_D2H_DEFAULT = '{
a_ready: 1'b1,
d_opcode: tl_d_op_e'('0),
d_user: tl_d_user_t'(0),
default: '0
};
// Check user for unsupported values
function automatic logic tl_a_user_chk(tl_a_user_t user);
logic malformed_err;
logic unused_user;
unused_user = |user;
malformed_err = ~(user.tl_type inside {InstrType, DataType});
return malformed_err;
endfunction // tl_a_user_chk
// extract variables used for command checking
function automatic tl_h2d_cmd_intg_t extract_h2d_cmd_intg(tl_h2d_t tl);
tl_h2d_cmd_intg_t payload;
logic unused_tlul;
unused_tlul = ^tl;
payload.addr = tl.a_address;
payload.opcode = tl.a_opcode;
payload.mask = tl.a_mask;
payload.tl_type = tl.a_user.tl_type;
return payload;
endfunction // extract_h2d_payload
// extract variables used for response checking
function automatic tl_d2h_rsp_intg_t extract_d2h_rsp_intg(tl_d2h_t tl);
tl_d2h_rsp_intg_t payload;
logic unused_tlul;
unused_tlul = ^tl;
payload.opcode = tl.d_opcode;
payload.size = tl.d_size;
//payload.source = tl.d_source;
payload.error = tl.d_error;
return payload;
endfunction // extract_d2h_rsp_intg
// calculate ecc for command checking
function automatic logic [H2DCmdIntgWidth-1:0] get_cmd_intg(tl_h2d_t tl);
logic [H2DCmdIntgWidth-1:0] cmd_intg;
logic [H2DCmdMaxWidth-1:0] unused_cmd_payload;
tl_h2d_cmd_intg_t cmd;
cmd = extract_h2d_cmd_intg(tl);
{cmd_intg, unused_cmd_payload} = prim_secded_pkg::prim_secded_64_57_enc(H2DCmdMaxWidth'(cmd));
return cmd_intg;
endfunction // get_cmd_intg
// calculate ecc for data checking
function automatic logic [DataIntgWidth-1:0] get_data_intg(logic [top_pkg::TL_DW-1:0] data);
logic [DataIntgWidth-1:0] data_intg;
logic [top_pkg::TL_DW-1:0] unused_data;
{data_intg, unused_data} = prim_secded_pkg::prim_secded_39_32_enc(data);
return data_intg;
endfunction // get_data_intg
endpackage