From 8fd566666d7289a2f4b216229da2f136f75db51b Mon Sep 17 00:00:00 2001 From: Andrea Caforio Date: Thu, 28 Nov 2024 14:27:58 +0100 Subject: [PATCH] [tlul, shim] Externalize Valid-Hold registers Move Valid-Hold-internal registers to a separate module with its own VH interface and redirect requests to it. Signed-off-by: Andrea Caforio --- hw/ip/aes/pre_dv/aes_tb/README.md | 5 +- hw/ip/aes/pre_dv/aes_tb/aes_tb.core | 3 +- .../aes/pre_dv/aes_tb/data/gcm_k128_a0_d0.svh | 6 +- .../pre_dv/aes_tb/data/gcm_k128_a0_d16.svh | 6 +- .../pre_dv/aes_tb/data/gcm_k128_a20_d60.svh | 6 +- .../pre_dv/aes_tb/data/gcm_k128_a20_d64.svh | 6 +- hw/ip/aes/pre_dv/aes_tb/data/modes_d64.svh | 6 +- hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb.sv | 122 +++++++++----- hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_c_dpi.sv | 2 +- hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_pkg.sv | 26 +-- hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_reqs.sv | 3 - .../pre_dv/aes_tb/rtl/tlul_adapter_tb_reqs.sv | 6 +- hw/ip/aes/pre_dv/aes_tb/rtl/vh_regs.sv | 60 +++++++ hw/ip/tlul/adapter_shim.core | 12 +- ...l_adapter_shim.vlt => tlul_adapter_vh.vlt} | 2 +- ...ter_shim.waiver => tlul_adapter_vh.waiver} | 2 +- hw/ip/tlul/rtl/tlul_adapter_shim.sv | 143 +---------------- hw/ip/tlul/rtl/tlul_adapter_vh.sv | 149 ++++++++++++++++++ 18 files changed, 339 insertions(+), 226 deletions(-) create mode 100644 hw/ip/aes/pre_dv/aes_tb/rtl/vh_regs.sv rename hw/ip/tlul/lint/{tlul_adapter_shim.vlt => tlul_adapter_vh.vlt} (82%) rename hw/ip/tlul/lint/{tlul_adapter_shim.waiver => tlul_adapter_vh.waiver} (82%) mode change 100644 => 120000 hw/ip/tlul/rtl/tlul_adapter_shim.sv create mode 100644 hw/ip/tlul/rtl/tlul_adapter_vh.sv diff --git a/hw/ip/aes/pre_dv/aes_tb/README.md b/hw/ip/aes/pre_dv/aes_tb/README.md index d50b0c587ac55..f9145df0e27e6 100644 --- a/hw/ip/aes/pre_dv/aes_tb/README.md +++ b/hw/ip/aes/pre_dv/aes_tb/README.md @@ -1,9 +1,9 @@ -# TLUL/Shim Verilator Testbench +# AES Verilator Testbench This directory contains the Verilator testbench for the AES IP block. Out of the box, the testbench contains test vectors for most of the salient use cases, nonetheless extending the testbench with further tests is straightforward as detailed below. By default, communication with the IP happens over the TLUL bus. -If a TLUL/shim adapter is available, messages can optionally be relayed by the shim. +If a TLUL/Valid-Hold adapter is available, messages can optionally be relayed by the adapter. ## Current Test Vectors @@ -53,6 +53,7 @@ To execute the obtained Verilator binary and with trace generation, run: - rtl/aes\_tb.sv: contains the testbench logic - rtl/tlul\_delayer.sv: contains an optional delayer module to artificially induce random delays in the TLUL bus. - rtl/tlul\_adapter_tb_reqs.sv: is an adapter than converts generic read/write requests into TLUL requests. +- rtl/vh\_regs.sv: dummy placeholder module for a Valid-Hold register file. - rtl/aes\_tb_reqs.sv: contains requests (stimuli) that are fed to the testbench. - rtl/aes\_tb_pkg.sv: contains common parameters and functions. - data/*: contains test vector files. diff --git a/hw/ip/aes/pre_dv/aes_tb/aes_tb.core b/hw/ip/aes/pre_dv/aes_tb/aes_tb.core index b3fdffa07ffef..4445bb6174c2f 100644 --- a/hw/ip/aes/pre_dv/aes_tb/aes_tb.core +++ b/hw/ip/aes/pre_dv/aes_tb/aes_tb.core @@ -9,7 +9,7 @@ filesets: depend: - lowrisc:ip:aes - lowrisc:dv:aes_model_dpi - - lowrisc:tlul:adapter_shim + - lowrisc:tlul:adapter_vh files: - data/gcm_k128_a20_d60.svh : {is_include_file : true} - data/gcm_k128_a20_d64.svh : {is_include_file : true} @@ -19,6 +19,7 @@ filesets: - rtl/aes_tb_pkg.sv - rtl/aes_tb_reqs.sv - rtl/aes_tb_c_dpi.sv + - rtl/vh_regs.sv - rtl/tlul_delayer.sv - rtl/tlul_adapter_tb_reqs.sv - rtl/aes_tb.sv diff --git a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d0.svh b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d0.svh index eb9a680fd6add..20bbc0814d872 100644 --- a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d0.svh +++ b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d0.svh @@ -105,7 +105,7 @@ read_request(AES_DATA_OUT_2_OFFSET), \ read_request(AES_DATA_OUT_3_OFFSET), \ \ - /* Read Caliptra-specific register */ \ - read_caliptra(CALIPTRA_NAME_0_OFFSET), \ - read_caliptra(CALIPTRA_VERSION_0_OFFSET) \ + /* Read VH-specific register */ \ + read_vh(VH_NAME_0_OFFSET), \ + read_vh(VH_VERSION_0_OFFSET) \ }; diff --git a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d16.svh b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d16.svh index 3662a655d3daa..56c4e31721e7d 100644 --- a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d16.svh +++ b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a0_d16.svh @@ -131,7 +131,7 @@ read_request(AES_DATA_OUT_2_OFFSET), \ read_request(AES_DATA_OUT_3_OFFSET), \ \ - /* Read Caliptra-specific register */ \ - read_caliptra(CALIPTRA_NAME_0_OFFSET), \ - read_caliptra(CALIPTRA_VERSION_0_OFFSET) \ + /* Read VH-specific register */ \ + read_vh(VH_NAME_0_OFFSET), \ + read_vh(VH_VERSION_0_OFFSET) \ }; diff --git a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d60.svh b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d60.svh index 1619ce659bd26..d9cc328c138ea 100644 --- a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d60.svh +++ b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d60.svh @@ -836,7 +836,7 @@ read_request(AES_DATA_OUT_2_OFFSET), \ read_request(AES_DATA_OUT_3_OFFSET), \ \ - /* Read Caliptra-specific register */ \ - read_caliptra(CALIPTRA_NAME_0_OFFSET), \ - read_caliptra(CALIPTRA_VERSION_0_OFFSET) \ + /* Read VH-specific register */ \ + read_vh(VH_NAME_0_OFFSET), \ + read_vh(VH_VERSION_0_OFFSET) \ }; diff --git a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d64.svh b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d64.svh index 642166d21b014..fb52e0529ab3d 100644 --- a/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d64.svh +++ b/hw/ip/aes/pre_dv/aes_tb/data/gcm_k128_a20_d64.svh @@ -247,7 +247,7 @@ read_request(AES_DATA_OUT_2_OFFSET), \ read_request(AES_DATA_OUT_3_OFFSET), \ \ - /* Read Caliptra-specific register */ \ - read_caliptra(CALIPTRA_NAME_0_OFFSET), \ - read_caliptra(CALIPTRA_VERSION_0_OFFSET) \ + /* Read VH-specific register */ \ + read_vh(VH_NAME_0_OFFSET), \ + read_vh(VH_VERSION_0_OFFSET) \ }; diff --git a/hw/ip/aes/pre_dv/aes_tb/data/modes_d64.svh b/hw/ip/aes/pre_dv/aes_tb/data/modes_d64.svh index 1c63a3ecf832c..07fe133f1fcf9 100644 --- a/hw/ip/aes/pre_dv/aes_tb/data/modes_d64.svh +++ b/hw/ip/aes/pre_dv/aes_tb/data/modes_d64.svh @@ -3600,7 +3600,7 @@ read_request(AES_DATA_OUT_3_OFFSET), \ read_request(AES_STATUS_OFFSET, 32'(1'b1) << AES_STATUS_IDLE_OFFSET), \ \ - /* Read Caliptra-specific register */ \ - read_caliptra(CALIPTRA_NAME_0_OFFSET), \ - read_caliptra(CALIPTRA_VERSION_0_OFFSET) \ + /* Read VH-specific register */ \ + read_vh(VH_NAME_0_OFFSET), \ + read_vh(VH_VERSION_0_OFFSET) \ }; diff --git a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb.sv b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb.sv index 57e1b46617691..f4c842b4668cf 100644 --- a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb.sv +++ b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb.sv @@ -19,7 +19,7 @@ module aes_tb localparam bit EnableDataIntgGen = 1, localparam bit EnableRspDataIntgCheck = 1, localparam bit DelayerEnable = 0, - localparam bit ShimEnable = 1 + localparam bit ValidHoldEnable = 1 ) ( input logic clk_i, input logic rst_ni, @@ -101,56 +101,102 @@ module aes_tb end aes_tb_reqs u_aes_tb_reqs ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .pop_req_i ( bus_pop ), - .req_o ( bus_req ), - .done_o ( bus_done ) + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .pop_req_i ( bus_pop ), + .req_o ( bus_req ), + .done_o ( bus_done ) ); // Every request that is not a `c_dpi_load` counts as a valid bus access. logic bus_en; assign bus_en = ~bus_req.c_dpi_load; - // The shim converts inputs from the valid-hold protocol into TLUL requests. - if (ShimEnable) begin : gen_tlul_adapter_shim - tlul_adapter_shim #( + // The Valid-Hold adapter converts inputs from the valid-hold protocol into TLUL requests. + if (ValidHoldEnable) begin : gen_tlul_adapter_vh + + logic int_dv; + logic [top_pkg::TL_AW-1:0] int_addr; + logic int_write; + logic [top_pkg::TL_DW-1:0] int_wdata; + logic [top_pkg::TL_DBW-1:0] int_wstrb; + logic [2:0] int_size; + logic int_hld; + logic [top_pkg::TL_DW-1:0] int_rdata; + logic int_error; + logic int_last; + logic [31:0] int_user; + logic [top_pkg::TL_AIW-1:0] int_id; + + tlul_adapter_vh #( .EnableDataIntgGen ( EnableDataIntgGen ), .EnableRspDataIntgCheck ( EnableRspDataIntgCheck ) - ) u_tlul_adapter_shim ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .tl_i ( tl_d2h_delayed ), - .tl_o ( tl_h2d ), - .dv_i ( bus_en ), - .addr_i ( bus_req.addr ), - .write_i ( bus_req.write ), - .wdata_i ( bus_req.wdata ), - .wstrb_i ( 4'b1111 ), - .size_i ( 3'b010 ), - .hld_o ( bus_wait ), - .rdata_o ( bus_rdata ), - .error_o ( bus_error ), - .last_i ( 1'b0 ), - .user_i ( 32'(TL_A_USER_DEFAULT) ), - .id_i ( '0 ) + ) u_tlul_adapter_vh ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_i ( tl_d2h_delayed ), + .tl_o ( tl_h2d ), + // Valid-Hold to TLUL + .dv_i ( bus_en ), + .addr_i ( bus_req.addr ), + .write_i ( bus_req.write ), + .wdata_i ( bus_req.wdata ), + .wstrb_i ( 4'b1111 ), + .size_i ( 3'b010 ), + .hld_o ( bus_wait ), + .rdata_o ( bus_rdata ), + .error_o ( bus_error ), + .last_i ( 1'b0 ), + .user_i ( 32'(TL_A_USER_DEFAULT) ), + .id_i ( '0 ), + // Valid-Hold to internal register + .int_dv_o ( int_dv ), + .int_addr_o ( int_addr ), + .int_write_o ( int_write ), + .int_wdata_o ( int_wdata ), + .int_wstrb_o ( int_wstrb ), + .int_size_o ( int_size ), + .int_hld_i ( int_hld ), + .int_rdata_i ( int_rdata ), + .int_error_i ( int_error ), + .int_last_o ( int_last ), + .int_user_o ( int_user ), + .int_id_o ( int_id ) ); + + vh_regs u_vh_regs ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .dv_i ( int_dv ), + .addr_i ( int_addr ), + .write_i ( int_write ), + .wdata_i ( int_wdata ), + .wstrb_i ( int_wstrb ), + .size_i ( int_size ), + .hld_o ( int_hld ), + .rdata_o ( int_rdata ), + .error_o ( int_error ), + .last_i ( int_last ), + .user_i ( int_user ), + .id_i ( int_id ) + ); + end else begin : gen_tlul_adapter tlul_adapter_tb_reqs #( .EnableDataIntgGen ( EnableDataIntgGen ), .EnableRspDataIntgCheck ( EnableRspDataIntgCheck ) ) u_tlul_adapter_tb_reqs ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .tl_i ( tl_d2h_delayed ), - .tl_o ( tl_h2d ), - .en_i ( bus_en ), - .wait_o ( bus_wait ), - .addr_i ( bus_req.addr ), - .write_i ( bus_req.write ), - .wdata_i ( bus_req.wdata ), - .rdata_o ( bus_rdata ), - .error_o ( bus_error ) + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_i ( tl_d2h_delayed ), + .tl_o ( tl_h2d ), + .en_i ( bus_en ), + .wait_o ( bus_wait ), + .addr_i ( bus_req.addr ), + .write_i ( bus_req.write ), + .wdata_i ( bus_req.wdata ), + .rdata_o ( bus_rdata ), + .error_o ( bus_error ) ); end @@ -228,7 +274,7 @@ module aes_tb end end - logic [31:0] data_mask; + logic [31:0] data_mask; assign data_mask = data_cntr_q >= 4 ? 32'hffff_ffff : data_cntr_q == 3 ? 32'h00ff_ffff : data_cntr_q == 2 ? 32'h0000_ffff : diff --git a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_c_dpi.sv b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_c_dpi.sv index 661e7239dcb72..5dbce124fc366 100644 --- a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_c_dpi.sv +++ b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_c_dpi.sv @@ -9,8 +9,8 @@ module aes_tb_c_dpi import aes_pkg::*; - import aes_tb_pkg::*; import aes_model_dpi_pkg::*; + import aes_tb_pkg::*; #( parameter int ADLength = 0, parameter int DataLength = 16 diff --git a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_pkg.sv b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_pkg.sv index e79da4420b22f..62f12d42efc0a 100644 --- a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_pkg.sv +++ b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_pkg.sv @@ -30,11 +30,11 @@ package aes_tb_pkg; parameter int AES_TRIGGER_DATA_OUT_CLEAR_OFFSET = 2; parameter int AES_TRIGGER_PRNG_RESEED_OFFSET = 3; - // Caliptra register offsets - parameter logic [11:0] CALIPTRA_NAME_0_OFFSET = 12'h100; - parameter logic [11:0] CALIPTRA_NAME_1_OFFSET = 12'h104; - parameter logic [11:0] CALIPTRA_VERSION_0_OFFSET = 12'h108; - parameter logic [11:0] CALIPTRA_VERSION_1_OFFSET = 12'h10c; + // Valid-Hold register offsets + parameter logic [11:0] VH_NAME_0_OFFSET = 12'h100; + parameter logic [11:0] VH_NAME_1_OFFSET = 12'h104; + parameter logic [11:0] VH_VERSION_0_OFFSET = 12'h108; + parameter logic [11:0] VH_VERSION_1_OFFSET = 12'h10c; `include `REQUESTS_FILE @@ -53,14 +53,14 @@ package aes_tb_pkg; logic [127:0] tag; // Only used in the GCM decryption case. } c_dpi_input_t; - // Grouping of all signals required for a TLUL/shim read/write request and to instrument the + // Grouping of all signals required for a TLUL/VH read/write request and to instrument the // `c_dpi` API. typedef struct packed { logic write; logic [top_pkg::TL_AW-1:0] addr; logic [top_pkg::TL_DW-1:0] wdata; - // Internal signal: The request is a `c_dpi` invocation instead of a TLUL/shim request. + // Internal signal: The request is a `c_dpi` invocation instead of a TLUL/VH request. logic c_dpi_load; // Internal signal: To mask read request responses, e.g., to check whether a certain bit is set. @@ -70,7 +70,7 @@ package aes_tb_pkg; c_dpi_input_t c_dpi_input; } bus_request_t; - // write_request returns a filled out `bus_request_t` struct for a TLUL/shim write request. + // write_request returns a filled out `bus_request_t` struct for a TLUL/VH write request. function automatic bus_request_t write_request (logic [7:0] addr, logic [top_pkg::TL_DW-1:0] wdata); bus_request_t req = '{ @@ -84,7 +84,7 @@ package aes_tb_pkg; return req; endfunction - // read_request returns a filled out `bus_request_t` struct for a TLUL/shim read request. + // read_request returns a filled out `bus_request_t` struct for a TLUL/VH read request. function automatic bus_request_t read_request (logic [7:0] addr, logic [top_pkg::TL_DW-1:0] mask = '0); bus_request_t req = '{ @@ -98,10 +98,10 @@ package aes_tb_pkg; return req; endfunction - // read_caliptra returns a filled out `bus_request_t` struct for an internal Caliptra register. - // This is only useful if a TLUL-to-Shim adapter is configured otherwise the request will result - // in a zero-value being returned by the register file. - function automatic bus_request_t read_caliptra (logic [11:0] addr); + // read_vh returns a filled out `bus_request_t` struct for an internal register. This is only + // useful if a TLUL-to-VH adapter is configured otherwise the request will result in a zero-value + // being returned by the register file. + function automatic bus_request_t read_vh (logic [11:0] addr); bus_request_t req = '{ c_dpi_load: 1'b0, write: 1'b0, diff --git a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_reqs.sv b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_reqs.sv index e60b9e7de2d20..1ef5b6bd717cf 100644 --- a/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_reqs.sv +++ b/hw/ip/aes/pre_dv/aes_tb/rtl/aes_tb_reqs.sv @@ -3,9 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 module aes_tb_reqs - import aes_pkg::*; - import aes_reg_pkg::*; - import tlul_pkg::*; import aes_tb_pkg::*; ( input logic clk_i, diff --git a/hw/ip/aes/pre_dv/aes_tb/rtl/tlul_adapter_tb_reqs.sv b/hw/ip/aes/pre_dv/aes_tb/rtl/tlul_adapter_tb_reqs.sv index fe70b4f959c68..8abe4fa55f7b0 100644 --- a/hw/ip/aes/pre_dv/aes_tb/rtl/tlul_adapter_tb_reqs.sv +++ b/hw/ip/aes/pre_dv/aes_tb/rtl/tlul_adapter_tb_reqs.sv @@ -51,9 +51,9 @@ module tlul_adapter_tb_reqs end end - // Only make a new request (through `a_valid`) to the device when none are - // pending. If the integrity checks are enabled, the `a_user` fields will be - // set by the corresponding module (see `tlul_cmd_intg_gen`). + // Only make a new request (through `a_valid`) to the device when none are pending. If the + // integrity checks are enabled, the `a_user` fields will be set by the corresponding module + // (see `tlul_cmd_intg_gen`). tlul_pkg::tl_h2d_t tl_o_pre; assign tl_o_pre = '{ a_valid: en_i & ~pending_q, diff --git a/hw/ip/aes/pre_dv/aes_tb/rtl/vh_regs.sv b/hw/ip/aes/pre_dv/aes_tb/rtl/vh_regs.sv new file mode 100644 index 0000000000000..add0b6cf30e7d --- /dev/null +++ b/hw/ip/aes/pre_dv/aes_tb/rtl/vh_regs.sv @@ -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 Valid-Hold register file supporting same-cycle reads of name and +// version registers. + +module vh_regs + import tlul_pkg::*; +#( + parameter bit [31:0] VH_NAME_0 = 32'hDEADBEEF, + parameter bit [31:0] VH_NAME_1 = 32'hCAFEBABE, + parameter bit [31:0] VH_VERSION_0 = 32'h00000001, + parameter bit [31:0] VH_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 = VH_NAME_0; + 4'h4: rdata_o = VH_NAME_1; + 4'h8: rdata_o = VH_VERSION_0; + 4'hc: rdata_o = VH_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 diff --git a/hw/ip/tlul/adapter_shim.core b/hw/ip/tlul/adapter_shim.core index 9dc1e9b2a740b..cb93e4d506a50 100644 --- a/hw/ip/tlul/adapter_shim.core +++ b/hw/ip/tlul/adapter_shim.core @@ -2,8 +2,8 @@ CAPI=2: # Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:tlul:adapter_shim:0.1" -description: "TL-UL/Shim interface adapter" +name: "lowrisc:tlul:adapter_vh:0.1" +description: "TLUL/Valid-Hold interface adapter" filesets: files_rtl: @@ -13,7 +13,7 @@ filesets: - lowrisc:tlul:common - lowrisc:tlul:trans_intg files: - - rtl/tlul_adapter_shim.sv + - rtl/tlul_adapter_vh.sv file_type: systemVerilogSource files_verilator_waiver: @@ -21,7 +21,7 @@ filesets: # common waivers - lowrisc:lint:common files: - - lint/tlul_adapter_shim.vlt + - lint/tlul_adapter_vh.vlt file_type: vlt files_ascentlint_waiver: @@ -29,7 +29,7 @@ filesets: # common waivers - lowrisc:lint:common files: - - lint/tlul_adapter_shim.waiver + - lint/tlul_adapter_vh.waiver file_type: waiver files_veriblelint_waiver: @@ -50,7 +50,7 @@ targets: - tool_ascentlint ? (files_ascentlint_waiver) - tool_veriblelint ? (files_veriblelint_waiver) - files_rtl - toplevel: tlul_adapter_shim + toplevel: tlul_adapter_vh lint: <<: *default_target diff --git a/hw/ip/tlul/lint/tlul_adapter_shim.vlt b/hw/ip/tlul/lint/tlul_adapter_vh.vlt similarity index 82% rename from hw/ip/tlul/lint/tlul_adapter_shim.vlt rename to hw/ip/tlul/lint/tlul_adapter_vh.vlt index e3eb84558c369..4f5f6668877ff 100644 --- a/hw/ip/tlul/lint/tlul_adapter_shim.vlt +++ b/hw/ip/tlul/lint/tlul_adapter_vh.vlt @@ -2,4 +2,4 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // -// waiver file for tlul_adapter_shim +// waiver file for tlul_adapter_vh diff --git a/hw/ip/tlul/lint/tlul_adapter_shim.waiver b/hw/ip/tlul/lint/tlul_adapter_vh.waiver similarity index 82% rename from hw/ip/tlul/lint/tlul_adapter_shim.waiver rename to hw/ip/tlul/lint/tlul_adapter_vh.waiver index 694bccdee2fd8..a599144ebd7a7 100644 --- a/hw/ip/tlul/lint/tlul_adapter_shim.waiver +++ b/hw/ip/tlul/lint/tlul_adapter_vh.waiver @@ -2,4 +2,4 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 # -# waiver file for TLUL Shim adapter +# waiver file for TLUL/VH adapter diff --git a/hw/ip/tlul/rtl/tlul_adapter_shim.sv b/hw/ip/tlul/rtl/tlul_adapter_shim.sv deleted file mode 100644 index c17170a857287..0000000000000 --- a/hw/ip/tlul/rtl/tlul_adapter_shim.sv +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright lowRISC contributors (OpenTitan project). -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -`include "prim_assert.sv" - -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 bit EnableDataIntgGen = 1, - parameter bit EnableRspDataIntgCheck = 1 -) ( - input clk_i, - input rst_ni, - - output tl_h2d_t tl_o, - input tl_d2h_t tl_i, - - // Shim interface - 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 -); - - // Differentiate between two levels of acknowledgements: - // - `req_ack`: A host-to-device request is acknowledged by the device, - // meaning that the response is pending. - // - `resp_ack`: The device-to-host response is acknowledged. - 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; - - always_comb begin - pending_d = pending_q; - if (req_ack) begin - pending_d = 1'b1; - end else if (resp_ack) begin - pending_d = 1'b0; - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - pending_q <= 1'b0; - end else begin - pending_q <= pending_d; - end - end - - // Only make a new request (through `a_valid`) to the device when none are - // pending. If the integrity checks are enabled, the `a_user` fields will be - // 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_opcode: ~write_i ? Get : (&wstrb_i ? PutFullData : PutPartialData), - a_size: top_pkg::TL_SZW'(size_i), - a_mask: wstrb_i, - a_source: id_i, - a_address: addr_i, - a_data: wdata_i, - a_user: '{default: '0, instr_type: prim_mubi_pkg::MuBi4False}, - d_ready: 1'b1, - // unused - 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 - - tlul_cmd_intg_gen #( - .EnableDataIntgGen (EnableDataIntgGen) - ) u_cmd_intg_gen ( - .tl_i ( tl_o_pre ), - .tl_o ( tl_o ) - ); - - logic intg_err_chk; - tlul_rsp_intg_chk #( - .EnableRspDataIntgCheck(EnableRspDataIntgCheck) - ) u_rsp_chk ( - .tl_i ( tl_i ), - .err_o ( intg_err_chk ) - ); - - assign error_o = tl_i.d_error | intg_err_chk; - - logic unused_signals; - assign unused_signals = ^{last_i, user_i, size_i[2]}; - - // Make sure the shim parameters are compatible with TLUL datapath widths. - `ASSERT_INIT(TlInvalidAddrWidth_A, ADDR_WIDTH == top_pkg::TL_AW) - `ASSERT_INIT(TlInvalidDataWidth_A, DATA_WIDTH == top_pkg::TL_DW) - `ASSERT_INIT(TlInvalidMaskWidth_A, MASK_WIDTH == top_pkg::TL_DBW) - `ASSERT_INIT(TlInvalidUserWidth_A, ID_WIDTH == top_pkg::TL_AIW) - -endmodule diff --git a/hw/ip/tlul/rtl/tlul_adapter_shim.sv b/hw/ip/tlul/rtl/tlul_adapter_shim.sv new file mode 120000 index 0000000000000..73ef5ade2f7fb --- /dev/null +++ b/hw/ip/tlul/rtl/tlul_adapter_shim.sv @@ -0,0 +1 @@ +tlul_adapter_vh.sv \ No newline at end of file diff --git a/hw/ip/tlul/rtl/tlul_adapter_vh.sv b/hw/ip/tlul/rtl/tlul_adapter_vh.sv new file mode 100644 index 0000000000000..19685a47d3737 --- /dev/null +++ b/hw/ip/tlul/rtl/tlul_adapter_vh.sv @@ -0,0 +1,149 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`include "prim_assert.sv" + +module tlul_adapter_vh + import tlul_pkg::*; + import prim_mubi_pkg::mubi4_t; +#( + 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 [ADDR_WIDTH-1:0] VH_REGISTER_ADDRESS_OFFSET = 32'h0000_0100, + + parameter bit EnableDataIntgGen = 1, + parameter bit EnableRspDataIntgCheck = 1 +) ( + input clk_i, + input rst_ni, + + output tl_h2d_t tl_o, + input tl_d2h_t tl_i, + + // Valid-Hold device interface (VH to TLUL). + 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, + input logic last_i, + input logic [USER_WIDTH-1:0] user_i, + input logic [ID_WIDTH-1:0] id_i, + + // Valid-Hold host interface (VH to internal registers). The signals from the VH device interface + // are routed to the VH host interface for every internal access, see the `internal_access` signal. + output logic int_dv_o, + input logic int_hld_i, + output logic [ADDR_WIDTH-1:0] int_addr_o, + output logic int_write_o, + output logic [DATA_WIDTH-1:0] int_wdata_o, + output logic [MASK_WIDTH-1:0] int_wstrb_o, + output logic [2:0] int_size_o, + input logic [DATA_WIDTH-1:0] int_rdata_i, + input logic int_error_i, + output logic int_last_o, + output logic [USER_WIDTH-1:0] int_user_o, + output logic [ID_WIDTH-1:0] int_id_o +); + + // Differentiate between two levels of acknowledgements: + // - `req_ack`: A host-to-device request is acknowledged by the device, meaning that the response + // is pending. + // - `resp_ack`: The device-to-host response is acknowledged. + logic pending_d, pending_q; + logic req_ack, resp_ack; + + 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; + if (req_ack) begin + pending_d = 1'b1; + end else if (resp_ack) begin + pending_d = 1'b0; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + pending_q <= 1'b0; + end else begin + pending_q <= pending_d; + end + end + + // Only make a new request (through `a_valid`) to the device when none are pending. If the + // integrity checks are enabled, the `a_user` fields will be 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_access, + a_opcode: ~write_i ? Get : (&wstrb_i ? PutFullData : PutPartialData), + a_size: top_pkg::TL_SZW'(size_i), + a_mask: wstrb_i, + a_source: id_i, + a_address: addr_i, + a_data: wdata_i, + a_user: '{default: '0, instr_type: prim_mubi_pkg::MuBi4False}, + d_ready: 1'b1, + // unused + a_param: 3'h0 + }; + + // The adapter distinguishes between two types of VH accesses: those going to an internal register + // file and those targeting OpenTitan registers, with the latter ones being translated into TLUL + // requests while the other requests are relayed to the internal register file. + logic internal_access; + assign internal_access = addr_i >= VH_REGISTER_ADDRESS_OFFSET; + + // Accesses to device registers are acknowledged with the TLUL d-channel handshake. + assign hld_o = !pending_q && internal_access && !int_hld_i ? 1'b0 : + pending_q && tl_o.d_ready && tl_i.d_valid ? 1'b0 : 1'b1; + + assign rdata_o = internal_access ? int_rdata_i : tl_i.d_data; + + // Route signals to the VH host interface. + assign int_dv_o = dv_i & internal_access; + assign int_addr_o = addr_i; + assign int_write_o = write_i; + assign int_wdata_o = wdata_i; + assign int_wstrb_o = wstrb_i; + assign int_size_o = size_i; + assign int_last_o = last_i; + assign int_user_o = user_i; + assign int_id_o = id_i; + + tlul_cmd_intg_gen #( + .EnableDataIntgGen (EnableDataIntgGen) + ) u_cmd_intg_gen ( + .tl_i ( tl_o_pre ), + .tl_o ( tl_o ) + ); + + logic intg_err_chk; + tlul_rsp_intg_chk #( + .EnableRspDataIntgCheck(EnableRspDataIntgCheck) + ) u_rsp_chk ( + .tl_i ( tl_i ), + .err_o ( intg_err_chk ) + ); + + assign error_o = tl_i.d_error | int_error_i | intg_err_chk; + + // Make sure the VH parameters are compatible with TLUL datapath widths. + `ASSERT_INIT(TlInvalidAddrWidth_A, ADDR_WIDTH == top_pkg::TL_AW) + `ASSERT_INIT(TlInvalidDataWidth_A, DATA_WIDTH == top_pkg::TL_DW) + `ASSERT_INIT(TlInvalidMaskWidth_A, MASK_WIDTH == top_pkg::TL_DBW) + `ASSERT_INIT(TlInvalidUserWidth_A, ID_WIDTH == top_pkg::TL_AIW) + +endmodule