../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: