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