../src/lowrisc_tlul_common_0.1/rtl/tlul_err.sv Cov: 100%
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:
6: `include "prim_assert.sv"
7:
8: module tlul_err import tlul_pkg::*; (
9: input clk_i,
10: input rst_ni,
11:
12: input tl_h2d_t tl_i,
13:
14: output logic err_o
15: );
16:
17: localparam int IW = $bits(tl_i.a_source);
18: localparam int SZW = $bits(tl_i.a_size);
19: localparam int DW = $bits(tl_i.a_data);
20: localparam int MW = $bits(tl_i.a_mask);
21: localparam int SubAW = $clog2(DW/8);
22:
23: logic opcode_allowed, a_config_allowed;
24:
25: logic op_full, op_partial, op_get;
26: assign op_full = (tl_i.a_opcode == PutFullData);
27: assign op_partial = (tl_i.a_opcode == PutPartialData);
28: assign op_get = (tl_i.a_opcode == Get);
29:
30: // Anything that doesn't fall into the permitted category, it raises an error
31: assign err_o = ~(opcode_allowed & a_config_allowed);
32:
33: // opcode check
34: assign opcode_allowed = (tl_i.a_opcode == PutFullData)
35: | (tl_i.a_opcode == PutPartialData)
36: | (tl_i.a_opcode == Get);
37:
38: // a channel configuration check
39: logic addr_sz_chk; // address and size alignment check
40: logic mask_chk; // inactive lane a_mask check
41: logic fulldata_chk; // PutFullData should have size match to mask
42:
43: logic [MW-1:0] mask;
44:
45: assign mask = (1 << tl_i.a_address[SubAW-1:0]);
46:
47: always_comb begin
48: addr_sz_chk = 1'b0;
49: mask_chk = 1'b0;
50: fulldata_chk = 1'b0; // Only valid when opcode is PutFullData
51:
52: if (tl_i.a_valid) begin
53: unique case (tl_i.a_size)
54: 'h0: begin // 1 Byte
55: addr_sz_chk = 1'b1;
56: mask_chk = ~|(tl_i.a_mask & ~mask);
57: fulldata_chk = |(tl_i.a_mask & mask);
58: end
59:
60: 'h1: begin // 2 Byte
61: addr_sz_chk = ~tl_i.a_address[0];
62: // check inactive lanes if lower 2B, check a_mask[3:2], if uppwer 2B, a_mask[1:0]
63: mask_chk = (tl_i.a_address[1]) ? ~|(tl_i.a_mask & 4'b0011)
64: : ~|(tl_i.a_mask & 4'b1100);
65: fulldata_chk = (tl_i.a_address[1]) ? &tl_i.a_mask[3:2] : &tl_i.a_mask[1:0] ;
66: end
67:
68: 'h2: begin // 4 Byte
69: addr_sz_chk = ~|tl_i.a_address[SubAW-1:0];
70: mask_chk = 1'b1;
71: fulldata_chk = &tl_i.a_mask[3:0];
72: end
73:
74: default: begin // else
75: addr_sz_chk = 1'b0;
76: mask_chk = 1'b0;
77: fulldata_chk = 1'b0;
78: end
79: endcase
80: end else begin
81: addr_sz_chk = 1'b0;
82: mask_chk = 1'b0;
83: fulldata_chk = 1'b0;
84: end
85: end
86:
87: assign a_config_allowed = addr_sz_chk
88: & mask_chk
89: & (op_get | op_partial | fulldata_chk) ;
90:
91: // Only 32 bit data width for current tlul_err
92: `ASSERT_INIT(dataWidthOnly32_A, DW == 32)
93:
94: endmodule
95:
96: