mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 04:38:42 -07:00
289 lines
9.3 KiB
Systemverilog
289 lines
9.3 KiB
Systemverilog
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
|
/*
|
|
|
|
Copyright (c) 2026 FPGA Ninja, LLC
|
|
|
|
Authors:
|
|
- Alex Forencich
|
|
|
|
*/
|
|
|
|
`resetall
|
|
`timescale 1ns / 1ps
|
|
`default_nettype none
|
|
|
|
/*
|
|
* Pyrite flashing support for UltraScale+ PCIe VPD and QSPI flash
|
|
*/
|
|
module pyrite_pcie_us_vpd_qspi #
|
|
(
|
|
parameter logic [7:0] VPD_CAP_ID = 8'h03,
|
|
parameter logic [7:0] VPD_CAP_OFFSET = 8'hB0,
|
|
parameter logic [7:0] VPD_CAP_NEXT = 8'h00,
|
|
|
|
// FW ID
|
|
parameter FPGA_ID = 32'hDEADBEEF,
|
|
parameter FW_ID = 32'h00000000,
|
|
parameter FW_VER = 32'h000_01_000,
|
|
parameter BOARD_ID = 32'h1234_0000,
|
|
parameter BOARD_VER = 32'h001_00_000,
|
|
parameter BUILD_DATE = 32'd602976000,
|
|
parameter GIT_HASH = 32'h5f87c2e8,
|
|
parameter RELEASE_INFO = 32'h00000000,
|
|
|
|
// Flash
|
|
parameter logic [3:0] FLASH_SEG_COUNT = 2,
|
|
parameter logic [3:0] FLASH_SEG_DEFAULT = 1,
|
|
parameter logic [3:0] FLASH_SEG_FALLBACK = 0,
|
|
parameter logic [31:0] FLASH_SEG0_SIZE = 32'h00000000,
|
|
parameter FLASH_DATA_W = 4,
|
|
parameter logic FLASH_DUAL_QSPI = 1'b1
|
|
)
|
|
(
|
|
input wire logic clk,
|
|
input wire logic rst,
|
|
|
|
/*
|
|
* PCIe
|
|
*/
|
|
input wire logic cfg_ext_read_received,
|
|
input wire logic cfg_ext_write_received,
|
|
input wire logic [9:0] cfg_ext_register_number,
|
|
input wire logic [7:0] cfg_ext_function_number,
|
|
input wire logic [31:0] cfg_ext_write_data,
|
|
input wire logic [3:0] cfg_ext_write_byte_enable,
|
|
output wire logic [31:0] cfg_ext_read_data,
|
|
output wire logic cfg_ext_read_data_valid,
|
|
|
|
/*
|
|
* QSPI flash
|
|
*/
|
|
output wire logic fpga_boot,
|
|
output wire logic qspi_clk,
|
|
input wire logic [FLASH_DATA_W-1:0] qspi_0_dq_i,
|
|
output wire logic [FLASH_DATA_W-1:0] qspi_0_dq_o,
|
|
output wire logic [FLASH_DATA_W-1:0] qspi_0_dq_oe,
|
|
output wire logic qspi_0_cs,
|
|
input wire logic [FLASH_DATA_W-1:0] qspi_1_dq_i,
|
|
output wire logic [FLASH_DATA_W-1:0] qspi_1_dq_o,
|
|
output wire logic [FLASH_DATA_W-1:0] qspi_1_dq_oe,
|
|
output wire logic qspi_1_cs
|
|
);
|
|
|
|
taxi_apb_if #(
|
|
.DATA_W(32),
|
|
.ADDR_W(15)
|
|
) vpd_apb();
|
|
|
|
taxi_pcie_us_vpd #(
|
|
.CAP_ID(VPD_CAP_ID),
|
|
.CAP_OFFSET(VPD_CAP_OFFSET),
|
|
.CAP_NEXT(VPD_CAP_NEXT)
|
|
)
|
|
vpd_cap_inst (
|
|
.clk(clk),
|
|
.rst(rst),
|
|
|
|
/*
|
|
* APB interface for VPD address space
|
|
*/
|
|
.m_apb(vpd_apb),
|
|
|
|
/*
|
|
* Interface to Ultrascale PCIe IP core
|
|
*/
|
|
.cfg_ext_read_received(cfg_ext_read_received),
|
|
.cfg_ext_write_received(cfg_ext_write_received),
|
|
.cfg_ext_register_number(cfg_ext_register_number),
|
|
.cfg_ext_function_number(cfg_ext_function_number),
|
|
.cfg_ext_write_data(cfg_ext_write_data),
|
|
.cfg_ext_write_byte_enable(cfg_ext_write_byte_enable),
|
|
.cfg_ext_read_data(cfg_ext_read_data),
|
|
.cfg_ext_read_data_valid(cfg_ext_read_data_valid)
|
|
);
|
|
|
|
taxi_apb_if #(
|
|
.DATA_W(32),
|
|
.ADDR_W(14)
|
|
) vpd_apb_int[2]();
|
|
|
|
taxi_apb_interconnect_1s #(
|
|
.M_CNT(2),
|
|
.ADDR_W(15),
|
|
.M_REGIONS(1),
|
|
.M_BASE_ADDR('0),
|
|
.M_ADDR_W({2{{1{{32'd14}}}}}),
|
|
.M_SECURE({2{1'b0}})
|
|
)
|
|
vpd_apb_intercon (
|
|
.clk(clk),
|
|
.rst(rst),
|
|
|
|
/*
|
|
* APB slave interface
|
|
*/
|
|
.s_apb(vpd_apb),
|
|
|
|
/*
|
|
* APB master interface
|
|
*/
|
|
.m_apb(vpd_apb_int)
|
|
);
|
|
|
|
taxi_apb_ram #(
|
|
.ADDR_W(11),
|
|
.PIPELINE_OUTPUT(1)
|
|
)
|
|
vpd_ram_inst (
|
|
.clk(clk),
|
|
.rst(rst),
|
|
|
|
/*
|
|
* AXI4-Lite slave interface
|
|
*/
|
|
.s_apb(vpd_apb_int[0])
|
|
);
|
|
|
|
logic vpd_apb_pready_reg = 1'b0;
|
|
logic [31:0] vpd_apb_prdata_reg = '0;
|
|
|
|
logic fpga_boot_reg = 1'b0;
|
|
|
|
logic qspi_clk_reg = 1'b0;
|
|
logic qspi_0_cs_reg = 1'b1;
|
|
logic [FLASH_DATA_W-1:0] qspi_0_dq_o_reg = '0;
|
|
logic [FLASH_DATA_W-1:0] qspi_0_dq_oe_reg = '0;
|
|
logic qspi_1_cs_reg = 1'b1;
|
|
logic [FLASH_DATA_W-1:0] qspi_1_dq_o_reg = '0;
|
|
logic [FLASH_DATA_W-1:0] qspi_1_dq_oe_reg = '0;
|
|
|
|
assign vpd_apb_int[1].pready = vpd_apb_pready_reg;
|
|
assign vpd_apb_int[1].prdata = vpd_apb_prdata_reg;
|
|
assign vpd_apb_int[1].pslverr = 1'b0;
|
|
assign vpd_apb_int[1].pruser = '0;
|
|
assign vpd_apb_int[1].pbuser = '0;
|
|
|
|
assign fpga_boot = fpga_boot_reg;
|
|
|
|
assign qspi_clk = qspi_clk_reg;
|
|
assign qspi_0_cs = qspi_0_cs_reg;
|
|
assign qspi_0_dq_o = qspi_0_dq_o_reg;
|
|
assign qspi_0_dq_oe = qspi_0_dq_oe_reg;
|
|
assign qspi_1_cs = FLASH_DUAL_QSPI ? qspi_1_cs_reg : 1'b1;
|
|
assign qspi_1_dq_o = FLASH_DUAL_QSPI ? qspi_1_dq_o_reg : '0;
|
|
assign qspi_1_dq_oe = FLASH_DUAL_QSPI ? qspi_1_dq_oe_reg : '0;
|
|
|
|
always_ff @(posedge clk) begin
|
|
vpd_apb_pready_reg <= 1'b0;
|
|
|
|
if (vpd_apb_int[1].penable && vpd_apb_int[1].psel && !vpd_apb_pready_reg) begin
|
|
vpd_apb_pready_reg <= 1'b1;
|
|
vpd_apb_prdata_reg <= '0;
|
|
|
|
if (vpd_apb_int[1].pwrite) begin
|
|
case (8'({vpd_apb_int[1].paddr >> 2, 2'b00}))
|
|
// FW ID
|
|
8'h0C: begin
|
|
// FW ID: FPGA JTAG ID
|
|
fpga_boot_reg <= vpd_apb_int[1].pwdata == 32'hFEE1DEAD;
|
|
end
|
|
// QSPI flash
|
|
8'h4C: begin
|
|
// SPI flash ctrl: format
|
|
fpga_boot_reg <= vpd_apb_int[1].pwdata == 32'hFEE1DEAD;
|
|
end
|
|
8'h50: begin
|
|
// SPI flash ctrl: control 0
|
|
if (vpd_apb_int[1].pstrb[0]) begin
|
|
qspi_0_dq_o_reg <= vpd_apb_int[1].pwdata[3:0];
|
|
end
|
|
if (vpd_apb_int[1].pstrb[1]) begin
|
|
qspi_0_dq_oe_reg <= vpd_apb_int[1].pwdata[11:8];
|
|
end
|
|
if (vpd_apb_int[1].pstrb[2]) begin
|
|
qspi_clk_reg <= vpd_apb_int[1].pwdata[16];
|
|
qspi_0_cs_reg <= vpd_apb_int[1].pwdata[17];
|
|
end
|
|
end
|
|
8'h54: begin
|
|
// SPI flash ctrl: control 1
|
|
if (FLASH_DUAL_QSPI) begin
|
|
if (vpd_apb_int[1].pstrb[0]) begin
|
|
qspi_1_dq_o_reg <= vpd_apb_int[1].pwdata[3:0];
|
|
end
|
|
if (vpd_apb_int[1].pstrb[1]) begin
|
|
qspi_1_dq_oe_reg <= vpd_apb_int[1].pwdata[11:8];
|
|
end
|
|
if (vpd_apb_int[1].pstrb[2]) begin
|
|
qspi_clk_reg <= vpd_apb_int[1].pwdata[16];
|
|
qspi_1_cs_reg <= vpd_apb_int[1].pwdata[17];
|
|
end
|
|
end
|
|
end
|
|
default: begin end
|
|
endcase
|
|
end
|
|
|
|
case (8'({vpd_apb_int[1].paddr >> 2, 2'b00}))
|
|
// FW ID
|
|
8'h00: vpd_apb_prdata_reg <= 32'hffffffff; // FW ID: Type
|
|
8'h04: vpd_apb_prdata_reg <= 32'h000_01_000; // FW ID: Version
|
|
8'h08: vpd_apb_prdata_reg <= 32'h40; // FW ID: Next header
|
|
8'h0C: vpd_apb_prdata_reg <= FPGA_ID; // FW ID: FPGA JTAG ID
|
|
8'h10: vpd_apb_prdata_reg <= FW_ID; // FW ID: Firmware ID
|
|
8'h14: vpd_apb_prdata_reg <= FW_VER; // FW ID: Firmware version
|
|
8'h18: vpd_apb_prdata_reg <= BOARD_ID; // FW ID: Board ID
|
|
8'h1C: vpd_apb_prdata_reg <= BOARD_VER; // FW ID: Board version
|
|
8'h20: vpd_apb_prdata_reg <= BUILD_DATE; // FW ID: Build date
|
|
8'h24: vpd_apb_prdata_reg <= GIT_HASH; // FW ID: Git commit hash
|
|
8'h28: vpd_apb_prdata_reg <= RELEASE_INFO; // FW ID: Release info
|
|
// QSPI flash
|
|
8'h40: vpd_apb_prdata_reg <= 32'h0000C120; // SPI flash ctrl: Type
|
|
8'h44: vpd_apb_prdata_reg <= 32'h000_01_000; // SPI flash ctrl: Version
|
|
8'h48: vpd_apb_prdata_reg <= 0; // SPI flash ctrl: Next header
|
|
8'h4C: begin
|
|
// SPI flash ctrl: format
|
|
vpd_apb_prdata_reg[3:0] <= FLASH_SEG_COUNT; // configuration
|
|
vpd_apb_prdata_reg[7:4] <= FLASH_SEG_DEFAULT; // default segment
|
|
vpd_apb_prdata_reg[11:8] <= FLASH_SEG_FALLBACK; // fallback segment
|
|
vpd_apb_prdata_reg[31:12] <= 20'(FLASH_SEG0_SIZE >> 12); // first segment size
|
|
end
|
|
8'h50: begin
|
|
// SPI flash ctrl: control 0
|
|
vpd_apb_prdata_reg[3:0] <= qspi_0_dq_i;
|
|
vpd_apb_prdata_reg[11:8] <= qspi_0_dq_oe;
|
|
vpd_apb_prdata_reg[16] <= qspi_clk;
|
|
vpd_apb_prdata_reg[17] <= qspi_0_cs;
|
|
end
|
|
8'h54: begin
|
|
// SPI flash ctrl: control 1
|
|
if (FLASH_DUAL_QSPI) begin
|
|
vpd_apb_prdata_reg[3:0] <= qspi_1_dq_i;
|
|
vpd_apb_prdata_reg[11:8] <= qspi_1_dq_oe;
|
|
vpd_apb_prdata_reg[16] <= qspi_clk;
|
|
vpd_apb_prdata_reg[17] <= qspi_1_cs;
|
|
end
|
|
end
|
|
default: begin end
|
|
endcase
|
|
end
|
|
|
|
if (rst) begin
|
|
vpd_apb_pready_reg <= 1'b0;
|
|
|
|
fpga_boot_reg <= 1'b0;
|
|
|
|
qspi_clk_reg <= 1'b0;
|
|
qspi_0_cs_reg <= 1'b1;
|
|
qspi_0_dq_o_reg <= '0;
|
|
qspi_0_dq_oe_reg <= '0;
|
|
qspi_1_cs_reg <= 1'b1;
|
|
qspi_1_dq_o_reg <= '0;
|
|
qspi_1_dq_oe_reg <= '0;
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
`resetall
|