../src/lowrisc_tlul_adapter_reg_0.1/rtl/tlul_adapter_reg.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: `include "prim_assert.sv"
   6: 
   7: /**
   8:  * Tile-Link UL adapter for Register interface
   9:  */
  10: 
  11: module tlul_adapter_reg import tlul_pkg::*; #(
  12:   parameter  int RegAw = 8,
  13:   parameter  int RegDw = 32, // Shall be matched with TL_DW
  14:   localparam int RegBw = RegDw/8
  15: ) (
  16:   input clk_i,
  17:   input rst_ni,
  18: 
  19:   // TL-UL interface
  20:   input  tl_h2d_t tl_i,
  21:   output tl_d2h_t tl_o,
  22: 
  23:   // Register interface
  24:   output logic             re_o,
  25:   output logic             we_o,
  26:   output logic [RegAw-1:0] addr_o,
  27:   output logic [RegDw-1:0] wdata_o,
  28:   output logic [RegBw-1:0] be_o,
  29:   input        [RegDw-1:0] rdata_i,
  30:   input                    error_i
  31: );
  32: 
  33:   localparam int IW  = $bits(tl_i.a_source);
  34:   localparam int SZW = $bits(tl_i.a_size);
  35: 
  36:   logic outstanding;    // Indicates current request is pending
  37:   logic a_ack, d_ack;
  38: 
  39:   logic [RegDw-1:0] rdata;
  40:   logic             error, err_internal;
  41: 
  42:   logic addr_align_err;     // Size and alignment
  43:   logic malformed_meta_err; // User signal format error or unsupported
  44:   logic tl_err;             // Common TL-UL error checker
  45: 
  46:   logic [IW-1:0]  reqid;
  47:   logic [SZW-1:0] reqsz;
  48:   tl_d_op_e       rspop;
  49: 
  50:   logic rd_req, wr_req;
  51: 
  52:   assign a_ack   = tl_i.a_valid & tl_o.a_ready;
  53:   assign d_ack   = tl_o.d_valid & tl_i.d_ready;
  54:   // Request signal
  55:   assign wr_req  = a_ack & ((tl_i.a_opcode == PutFullData) | (tl_i.a_opcode == PutPartialData));
  56:   assign rd_req  = a_ack & (tl_i.a_opcode == Get);
  57: 
  58:   assign we_o    = wr_req & ~err_internal;
  59:   assign re_o    = rd_req & ~err_internal;
  60:   assign addr_o  = {tl_i.a_address[RegAw-1:2], 2'b00}; // generate always word-align
  61:   assign wdata_o = tl_i.a_data;
  62:   assign be_o    = tl_i.a_mask;
  63: 
  64:   always_ff @(posedge clk_i or negedge rst_ni) begin
  65:     if (!rst_ni)    outstanding <= 1'b0;
  66:     else if (a_ack) outstanding <= 1'b1;
  67:     else if (d_ack) outstanding <= 1'b0;
  68:   end
  69: 
  70:   always_ff @(posedge clk_i or negedge rst_ni) begin
  71:     if (!rst_ni) begin
  72:       reqid <= '0;
  73:       reqsz <= '0;
  74:       rspop <= AccessAck;
  75:     end else if (a_ack) begin
  76:       reqid <= tl_i.a_source;
  77:       reqsz <= tl_i.a_size;
  78:       // Return AccessAckData regardless of error
  79:       rspop <= (rd_req) ? AccessAckData : AccessAck ;
  80:     end
  81:   end
  82: 
  83:   always_ff @(posedge clk_i or negedge rst_ni) begin
  84:     if (!rst_ni) begin
  85:       rdata  <= '0;
  86:       error <= 1'b0;
  87:     end else if (a_ack) begin
  88:       rdata <= (err_internal) ? '1 : rdata_i;
  89:       error <= error_i | err_internal;
  90:     end
  91:   end
  92: 
  93:   assign tl_o = '{
  94:     a_ready:  ~outstanding,
  95:     d_valid:  outstanding,
  96:     d_opcode: rspop,
  97:     d_param:  '0,
  98:     d_size:   reqsz,
  99:     d_source: reqid,
 100:     d_sink:   '0,
 101:     d_data:   rdata,
 102:     d_user:  '0,
 103:     d_error: error
 104:   };
 105: 
 106:   ////////////////////
 107:   // Error Handling //
 108:   ////////////////////
 109:   assign err_internal = addr_align_err | malformed_meta_err | tl_err ;
 110: 
 111:   // malformed_meta_err
 112:   //    Raised if not supported feature is turned on or user signal has malformed
 113:   assign malformed_meta_err = (tl_i.a_user.parity_en == 1'b1);
 114: 
 115:   // addr_align_err
 116:   //    Raised if addr isn't aligned with the size
 117:   //    Read size error is checked in tlul_assert.sv
 118:   //    Here is it added due to the limitation of register interface.
 119:   always_comb begin
 120:     if (wr_req) begin
 121:       // Only word-align is accepted based on comportability spec
 122:       addr_align_err = |tl_i.a_address[1:0];
 123:     end else begin
 124:       // No request
 125:       addr_align_err = 1'b0;
 126:     end
 127:   end
 128: 
 129:   // tl_err : separate checker
 130:   tlul_err u_err (
 131:     .clk_i,
 132:     .rst_ni,
 133:     .tl_i,
 134:     .err_o (tl_err)
 135:   );
 136: 
 137:   `ASSERT_INIT(MatchedWidthAssert, RegDw == top_pkg::TL_DW)
 138: 
 139: endmodule
 140: