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