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: