blob: 4c1719030fa2b28067a41be05c2d785f644a5440 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Provides termination for a TL interface.
module tlul_sink import tlul_pkg::*; (
input logic clk_i,
input logic rst_ni,
input tlul_pkg::tl_h2d_t tl_i,
output tlul_pkg::tl_d2h_t tl_o
);
logic a_ack, d_ack;
logic rd_req, wr_req;
logic pending;
localparam int IDW = $bits(tl_i.a_source);
localparam int SZW = $bits(tl_i.a_size);
logic [IDW-1:0] d_source_q;
logic [SZW-1:0] d_size_q;
tl_d_op_e d_opcode_q;
logic d_error_q;
logic addr_align_err; // Size and alignment
logic wr_mask_err; // Write mask always all 1s.
logic malformed_meta_err; // User signal format error or unsupported
logic tl_err; // Common TL-UL error checker
assign a_ack = tl_i.a_valid & tl_o.a_ready;
assign d_ack = tl_o.d_valid & tl_i.d_ready;
assign wr_req = a_ack & ((tl_i.a_opcode == PutFullData) | (tl_i.a_opcode == PutPartialData));
assign rd_req = a_ack & (tl_i.a_opcode == Get);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) pending <= 1'b0;
else if (a_ack) pending <= 1'b1;
else if (d_ack) pending <= 1'b0;
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
d_source_q <= '0;
d_size_q <= '0;
d_opcode_q <= AccessAck;
d_error_q <= 1'b0;
end else if (a_ack) begin
d_source_q <= tl_i.a_source;
d_size_q <= tl_i.a_size;
d_opcode_q <= rd_req ? AccessAckData : AccessAck;
d_error_q <= (addr_align_err | wr_mask_err | malformed_meta_err | tl_err);
end
end
////////////////////
// Error Handling //
////////////////////
// Accept only word aligned address.
assign addr_align_err = wr_req ? (|tl_i.a_address[1:0]) : 1'b0;
// Write mask should be all 1s.
assign wr_mask_err = wr_req ? ~(&tl_i.a_mask) : 1'b0;
// Don't allow unsupported values.
assign malformed_meta_err = tl_a_user_chk(tl_i.a_user);
// tl_err : separate checker
tlul_err u_err (
.clk_i,
.rst_ni,
.tl_i,
.err_o (tl_err)
);
//////////////////
// Final Output //
//////////////////
tlul_pkg::tl_d2h_t tl_o_pre;
assign tl_o_pre = '{
a_ready: ~pending,
d_valid: pending,
d_opcode: d_opcode_q,
d_param: '0,
d_size: d_size_q,
d_source: d_source_q,
d_sink: '0,
d_data: '0,
d_user: '0,
d_error: d_error_q
};
tlul_rsp_intg_gen u_gen (
.tl_i(tl_o_pre),
.tl_o
);
endmodule