Skip to content

Commit

Permalink
[tlul, shim] Externalize Caliptra registers
Browse files Browse the repository at this point in the history
Move Caliptra-internal registers to a separate module with its own DV
interface and redirect shim requests to it.

Signed-off-by: Andrea Caforio <[email protected]>
  • Loading branch information
andrea-caforio committed Nov 28, 2024
1 parent d759588 commit 8e7da5a
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 37 deletions.
1 change: 1 addition & 0 deletions hw/ip/tlul/adapter_shim.core
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ filesets:
- lowrisc:tlul:common
- lowrisc:tlul:trans_intg
files:
- rtl/caliptra_regs.sv
- rtl/tlul_adapter_shim.sv
file_type: systemVerilogSource

Expand Down
60 changes: 60 additions & 0 deletions hw/ip/tlul/rtl/caliptra_regs.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// Dummy placeholder module for a Caliptra register file supporting same-cycle reads of name and
// version registers.

module caliptra_regs
import tlul_pkg::*;
#(
parameter bit [31:0] CALIPTRA_NAME_0 = 32'hDEADBEEF,
parameter bit [31:0] CALIPTRA_NAME_1 = 32'hCAFEBABE,
parameter bit [31:0] CALIPTRA_VERSION_0 = 32'h00000001,
parameter bit [31:0] CALIPTRA_VERSION_1 = 32'h00000000,

parameter int ADDR_WIDTH = top_pkg::TL_AW,
parameter int DATA_WIDTH = top_pkg::TL_DW,
parameter int MASK_WIDTH = DATA_WIDTH >> 3,
parameter int USER_WIDTH = 32,
parameter int ID_WIDTH = top_pkg::TL_AIW
) (
input clk_i,
input rst_ni,

input logic dv_i,
output logic hld_o,
input logic [ADDR_WIDTH-1:0] addr_i,
input logic write_i,
input logic [DATA_WIDTH-1:0] wdata_i,
input logic [MASK_WIDTH-1:0] wstrb_i,
input logic [2:0] size_i,
output logic [DATA_WIDTH-1:0] rdata_o,
output logic error_o,
// Optional signals
input logic last_i,
input logic [USER_WIDTH-1:0] user_i,
input logic [ID_WIDTH-1:0] id_i
);

always_comb begin
rdata_o = '0;
if (dv_i) begin
unique case (addr_i[3:0])
4'h0: rdata_o = CALIPTRA_NAME_0;
4'h4: rdata_o = CALIPTRA_NAME_1;
4'h8: rdata_o = CALIPTRA_VERSION_0;
4'hc: rdata_o = CALIPTRA_VERSION_1;
default: rdata_o = '0;
endcase
end
end

assign hld_o = 1'b0;
assign error_o = 1'b0;

logic unused_signals;
assign unused_signals = ^{clk_i, rst_ni, addr_i[31:4], write_i, wdata_i, wstrb_i, size_i, last_i,
user_i, id_i};

endmodule
80 changes: 43 additions & 37 deletions hw/ip/tlul/rtl/tlul_adapter_shim.sv
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,16 @@ module tlul_adapter_shim
import tlul_pkg::*;
import prim_mubi_pkg::mubi4_t;
#(
parameter bit [31:0] SHIM_NAME_0 = 32'hDEADBEEF,
parameter bit [31:0] SHIM_NAME_1 = 32'hCAFEBABE,
parameter bit [31:0] SHIM_VERSION_0 = 32'h00000001,
parameter bit [31:0] SHIM_VERSION_1 = 32'h00000000,

parameter bit [11:0] SHIM_REGISTER_ADDRESS_OFFSET = 12'h100,

parameter int ADDR_WIDTH = top_pkg::TL_AW,
parameter int DATA_WIDTH = top_pkg::TL_DW,
parameter int MASK_WIDTH = DATA_WIDTH >> 3,
parameter int USER_WIDTH = 32,
parameter int ID_WIDTH = top_pkg::TL_AIW,
parameter int ADDR_WIDTH = top_pkg::TL_AW,
parameter int DATA_WIDTH = top_pkg::TL_DW,
parameter int MASK_WIDTH = DATA_WIDTH >> 3,
parameter int USER_WIDTH = 32,
parameter int ID_WIDTH = top_pkg::TL_AIW,

parameter bit EnableDataIntgGen = 1,
parameter bit EnableRspDataIntgCheck = 1
parameter bit EnableDataIntgGen = 1,
parameter bit EnableRspDataIntgCheck = 1
) (
input clk_i,
input rst_ni,
Expand Down Expand Up @@ -53,8 +48,8 @@ module tlul_adapter_shim
logic pending_d, pending_q;
logic req_ack, resp_ack;

assign req_ack = dv_i & tl_i.a_ready & tl_o.a_valid & ~internal_read;
assign resp_ack = dv_i & tl_o.d_ready & tl_i.d_valid & ~internal_read;
assign req_ack = dv_i & tl_i.a_ready & tl_o.a_valid & ~internal_access;
assign resp_ack = dv_i & tl_o.d_ready & tl_i.d_valid & ~internal_access;

always_comb begin
pending_d = pending_q;
Expand All @@ -78,7 +73,7 @@ module tlul_adapter_shim
// set by the corresponding module (see `tlul_cmd_intg_gen`).
tlul_pkg::tl_h2d_t tl_o_pre;
assign tl_o_pre = '{
a_valid: dv_i & ~pending_q & ~internal_read,
a_valid: dv_i & ~pending_q & ~internal_access,
a_opcode: ~write_i ? Get : (&wstrb_i ? PutFullData : PutPartialData),
a_size: top_pkg::TL_SZW'(size_i),
a_mask: wstrb_i,
Expand All @@ -91,27 +86,38 @@ module tlul_adapter_shim
a_param: 3'h0
};

logic internal_read;
assign internal_read = |(addr_i[11:0] & SHIM_REGISTER_ADDRESS_OFFSET);

// Accesses to shim internal registers have no latency. Accesses to device registers are
// acknowledged with the TLUL d-channel handshake.
assign hld_o = !pending_q && internal_read ? 1'b0 :
pending_q && tl_o.d_ready && tl_i.d_valid ? 1'b0 : 1'b1;

// A read request to an internal register is resolved in the same clock cycle.
always_comb begin
rdata_o = tl_i.d_data;
if (internal_read) begin
unique case (addr_i[3:0])
4'h0: rdata_o = SHIM_NAME_0;
4'h4: rdata_o = SHIM_NAME_1;
4'h8: rdata_o = SHIM_VERSION_0;
4'hc: rdata_o = SHIM_VERSION_1;
default: rdata_o = tl_i.d_data;
endcase
end
end
// The shim distinguishes between two types of DV accesses: those going to an internal Caliptra
// register file and those targeting OpenTitan registers, with the latter ones being translated
// into TLUL requests while Caliptra requests are relayed to the internal register file.
logic internal_access;
assign internal_access = |(addr_i[11:0] & SHIM_REGISTER_ADDRESS_OFFSET);

// Accesses to device registers are acknowledged with the TLUL d-channel handshake.
assign hld_o = !pending_q && internal_access && !caliptra_hld ? 1'b0 :
pending_q && tl_o.d_ready && tl_i.d_valid ? 1'b0 : 1'b1;

assign rdata_o = internal_access ? caliptra_rdata : tl_i.d_data;

logic caliptra_hld;
logic caliptra_error;
logic [DATA_WIDTH-1:0] caliptra_rdata;

caliptra_regs u_caliptra_regs (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.dv_i ( dv_i & internal_access ),
.hld_o ( caliptra_hld ),
.addr_i ( addr_i ),
.write_i ( write_i ),
.wdata_i ( wdata_i ),
.wstrb_i ( wstrb_i ),
.size_i ( size_i ),
.rdata_o ( caliptra_rdata ),
.error_o ( caliptra_error ),
.last_i ( last_i ),
.user_i ( user_i ),
.id_i ( id_i )
);

tlul_cmd_intg_gen #(
.EnableDataIntgGen (EnableDataIntgGen)
Expand All @@ -128,7 +134,7 @@ module tlul_adapter_shim
.err_o ( intg_err_chk )
);

assign error_o = tl_i.d_error | intg_err_chk;
assign error_o = tl_i.d_error | caliptra_error | intg_err_chk;

logic unused_signals;
assign unused_signals = ^{last_i, user_i, size_i[2]};
Expand Down

0 comments on commit 8e7da5a

Please sign in to comment.