diff --git a/src/pcie/rtl/taxi_pcie_us_cfg.sv b/src/pcie/rtl/taxi_pcie_us_cfg.sv new file mode 100644 index 0000000..88a0232 --- /dev/null +++ b/src/pcie/rtl/taxi_pcie_us_cfg.sv @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: CERN-OHL-S-2.0 +/* + +Copyright (c) 2018-2025 FPGA Ninja, LLC + +Authors: +- Alex Forencich + +*/ + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * UltraScale PCIe configuration shim + */ +module taxi_pcie_us_cfg # +( + parameter PF_COUNT = 1, + parameter VF_COUNT = 0, + parameter VF_OFFSET = 64, + parameter F_COUNT = PF_COUNT+VF_COUNT, + parameter logic READ_EXT_TAG_ENABLE = 1'b1, + parameter logic READ_MAX_READ_REQ_SIZE = 1'b1, + parameter logic READ_MAX_PAYLOAD_SIZE = 1'b1, + parameter PCIE_CAP_OFFSET = 12'h0C0 +) +( + input wire logic clk, + input wire logic rst, + + /* + * Configuration outputs + */ + output wire logic [F_COUNT-1:0] ext_tag_en, + output wire logic [F_COUNT*3-1:0] max_read_req_size, + output wire logic [F_COUNT*3-1:0] max_payload_size, + + /* + * Interface to Ultrascale PCIe IP core + */ + output wire logic [9:0] cfg_mgmt_addr, + output wire logic [7:0] cfg_mgmt_function_number, + output wire logic cfg_mgmt_write, + output wire logic [31:0] cfg_mgmt_write_data, + output wire logic [3:0] cfg_mgmt_byte_enable, + output wire logic cfg_mgmt_read, + input wire logic [31:0] cfg_mgmt_read_data, + input wire logic cfg_mgmt_read_write_done +); + +localparam CL_F_COUNT = F_COUNT > 1 ? $clog2(F_COUNT) : 1; + +localparam READ_REV_CTRL = READ_EXT_TAG_ENABLE || READ_MAX_READ_REQ_SIZE || READ_MAX_PAYLOAD_SIZE; + +localparam DEV_CTRL_OFFSET = PCIE_CAP_OFFSET + 12'h008; + +logic [F_COUNT-1:0] ext_tag_en_reg = '0, ext_tag_en_next; +logic [F_COUNT*3-1:0] max_read_req_size_reg = '0, max_read_req_size_next; +logic [F_COUNT*3-1:0] max_payload_size_reg = '0, max_payload_size_next; + +logic [9:0] cfg_mgmt_addr_reg = '0, cfg_mgmt_addr_next; +logic [7:0] cfg_mgmt_function_number_reg = '0, cfg_mgmt_function_number_next; +logic cfg_mgmt_write_reg = 1'b0, cfg_mgmt_write_next; +logic [31:0] cfg_mgmt_write_data_reg = '0, cfg_mgmt_write_data_next; +logic [3:0] cfg_mgmt_byte_enable_reg = '0, cfg_mgmt_byte_enable_next; +logic cfg_mgmt_read_reg = 1'b0, cfg_mgmt_read_next; +logic [31:0] cfg_mgmt_read_data_reg = '0; +logic cfg_mgmt_read_write_done_reg = 1'b0; + +logic [7:0] delay_reg = 8'hff, delay_next; +logic [CL_F_COUNT-1:0] func_cnt_reg = '0, func_cnt_next; + +assign ext_tag_en = ext_tag_en_reg; +assign max_read_req_size = max_read_req_size_reg; +assign max_payload_size = max_payload_size_reg; + +assign cfg_mgmt_addr = cfg_mgmt_addr_reg; +assign cfg_mgmt_function_number = cfg_mgmt_function_number_reg; +assign cfg_mgmt_write = cfg_mgmt_write_reg; +assign cfg_mgmt_write_data = cfg_mgmt_write_data_reg; +assign cfg_mgmt_byte_enable = cfg_mgmt_byte_enable_reg; +assign cfg_mgmt_read = cfg_mgmt_read_reg; + +always_comb begin + ext_tag_en_next = ext_tag_en_reg; + max_read_req_size_next = max_read_req_size_reg; + max_payload_size_next = max_payload_size_reg; + + cfg_mgmt_addr_next = cfg_mgmt_addr_reg; + cfg_mgmt_function_number_next = cfg_mgmt_function_number_reg; + cfg_mgmt_write_next = cfg_mgmt_write_reg && !cfg_mgmt_read_write_done; + cfg_mgmt_write_data_next = cfg_mgmt_write_data_reg; + cfg_mgmt_byte_enable_next = cfg_mgmt_byte_enable_reg; + cfg_mgmt_read_next = cfg_mgmt_read_reg && !cfg_mgmt_read_write_done; + + delay_next = delay_reg; + func_cnt_next = func_cnt_reg; + + if (delay_reg > 0) begin + delay_next = delay_reg - 1; + end else begin + cfg_mgmt_addr_next = 10'(DEV_CTRL_OFFSET >> 2); + cfg_mgmt_read_next = 1'b1; + if (cfg_mgmt_read_write_done_reg) begin + cfg_mgmt_read_next = 1'b0; + + ext_tag_en_next[func_cnt_reg] = cfg_mgmt_read_data_reg[8]; + max_read_req_size_next[func_cnt_reg*3 +: 3] = cfg_mgmt_read_data_reg[14:12]; + max_payload_size_next[func_cnt_reg*3 +: 3] = cfg_mgmt_read_data_reg[7:5]; + + if (func_cnt_reg == F_COUNT-1) begin + func_cnt_next = 0; + cfg_mgmt_function_number_next = 0; + end else if (func_cnt_reg == PF_COUNT-1) begin + func_cnt_next = func_cnt_reg + 1; + cfg_mgmt_function_number_next = VF_OFFSET; + end else begin + func_cnt_next = func_cnt_reg + 1; + cfg_mgmt_function_number_next = cfg_mgmt_function_number_reg + 1; + end + + delay_next = 8'hff; + end + end +end + +always_ff @(posedge clk) begin + ext_tag_en_reg <= ext_tag_en_next; + max_read_req_size_reg <= max_read_req_size_next; + max_payload_size_reg <= max_payload_size_next; + + cfg_mgmt_addr_reg <= cfg_mgmt_addr_next; + cfg_mgmt_function_number_reg <= cfg_mgmt_function_number_next; + cfg_mgmt_write_reg <= cfg_mgmt_write_next; + cfg_mgmt_write_data_reg <= cfg_mgmt_write_data_next; + cfg_mgmt_byte_enable_reg <= cfg_mgmt_byte_enable_next; + cfg_mgmt_read_reg <= cfg_mgmt_read_next; + cfg_mgmt_read_data_reg <= cfg_mgmt_read_data; + cfg_mgmt_read_write_done_reg <= cfg_mgmt_read_write_done; + + delay_reg <= delay_next; + func_cnt_reg <= func_cnt_next; + + if (rst) begin + ext_tag_en_reg <= '0; + max_read_req_size_reg <= '0; + max_payload_size_reg <= '0; + + cfg_mgmt_addr_reg <= '0; + cfg_mgmt_function_number_reg <= '0; + cfg_mgmt_write_reg <= 1'b0; + cfg_mgmt_read_reg <= 1'b0; + cfg_mgmt_read_write_done_reg <= 1'b0; + + delay_reg <= 8'hff; + func_cnt_reg <= '0; + end +end + +endmodule + +`resetall