fpga: Add module for reading Xilinx device DNA

- This provides a CtrlPort access to reading back the device DNA
- Available for US+ devices (i.e., RFSoC) and 7-series.


Original-commit: 43856f90da01cebc1e4b327f4435966ccd1df602
This commit is contained in:
Martin Braun
2024-05-27 17:05:06 +02:00
committed by joergho
parent 75a2526efd
commit 76f67bbb0c
5 changed files with 475 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
#
# Copyright 2023 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
##################################################
# Hardware Utilities Sources
##################################################
HWUTILS_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/hwutils/, \
device_dna.v \
device_dna_ctrlport.v \
))
+117
View File
@@ -0,0 +1,117 @@
//
// Copyright 2023 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: device_dna
//
// Description:
//
// Read back the PL DNA.
// When reset, this module will shift the PL DNA into an output register.
//
// Parameters:
//
// DNA_WIDTH: The width of the DNA register. UltraScale(+) devices have a 96-bit
// DNA, 7-series have a 57-bit DNA. If DNA_WIDTH is smaller than
// that, only LSBs will be output. If it's larger, then the DNA
// will be zero-padded.
// DEVICE_TYPE: Either ULTRASCALE or 7SERIES.
//
// Signals:
//
// dna: This register will hold the full DNA value.
// valid: This is low while the DNA value register is being populated. Only
// when high is the value in `dna' valid.
//
`default_nettype none
module device_dna #(
// Number of bits of DNA to output
parameter DNA_WIDTH = 96,
// For future use: Different FPGA types have different primitives for reading DNA
parameter DEVICE_TYPE = "ULTRASCALE"
)(
input wire clk,
input wire rst,
// The device DNA
output reg [DNA_WIDTH-1:0] dna,
// This output is low while the dna register is being populated
output wire valid
);
localparam ST_RESET = 2'd0;
localparam ST_READ = 2'd1;
localparam ST_SHIFT = 2'd2;
localparam ST_DONE = 2'd3;
localparam MAX_SHIFT = (DEVICE_TYPE == "7SERIES") ? 57 : DNA_WIDTH;
reg [1:0] state = ST_RESET;
reg [$clog2(DNA_WIDTH)-1:0] bit_cnt = 0;
wire read;
wire shift;
wire dout0;
always @(posedge clk) begin
if (rst) begin
dna <= {DNA_WIDTH{1'b0}};
state <= ST_READ;
end else if (state == ST_READ) begin
state <= ST_SHIFT;
bit_cnt <= MAX_SHIFT-1;
end else if (state == ST_SHIFT) begin
// Ultrascale shifts the DNA out LSB first, 7-series shifts the DNA out
// MSB first (cf. UG-470 and UG-570 for 7-series and Ultrascale).
if (DEVICE_TYPE == "ULTRASCALE") begin
dna <= { dout0, dna[DNA_WIDTH-1:1] };
end else if (DEVICE_TYPE == "7SERIES") begin
dna <= { dna[DNA_WIDTH-2:0], dout0 };
end
state <= (bit_cnt == 0) ? ST_DONE : ST_SHIFT;
bit_cnt <= bit_cnt - 1;
end else begin
// Nothing in ST_DONE
end
end
assign read = state == ST_READ;
assign shift = state == ST_SHIFT;
assign valid = state == ST_DONE;
if (DEVICE_TYPE == "ULTRASCALE") begin : gen_ultrascale_dna
DNA_PORTE2 #(
.SIM_DNA_VALUE(96'h12F1110_C0D111A0_11C0FFEE)
) dna_inst (
.CLK (clk),
.DIN (1'b0),
.READ (read),
.SHIFT(shift),
.DOUT (dout0)
);
end else if (DEVICE_TYPE == "7SERIES") begin : gen_7series_dna
DNA_PORT #(
.SIM_DNA_VALUE(57'h0D111A0_C0DE00FF)
) dna_inst (
.CLK (clk),
.DIN (1'b0),
.READ (read),
.SHIFT(shift),
.DOUT (dout0)
);
end else begin : gen_assert
ERROR_invalid_device_type();
end
endmodule
`default_nettype wire
+97
View File
@@ -0,0 +1,97 @@
//
// Copyright 2023 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: device_dna_ctrlport
//
// Description:
//
// Read back the PL DNA via CtrlPort transactions, 32-bit at a time.
//
// This module will return the PL DNA via a 32-bit ctrlport transaction. This
// means the DNA value is split up into multiple registers. For example, if a
// 96 bit DNA width is selected, there will be three consecutive registers
// holding the DNA value.
//
// Note the DNA value width is chip-dependent. For example, Ultrascale+ devices
// like the RFSoC have a 96-bit DNA value. Everything above the 96 bits would be
// zero-padded.
//
// After resetting, it takes some clock cycles to load the DNA value. During
// this time, transactions will return an error code.
//
// Parameters:
//
// BASE_ADDR: Readback address for the 32 LSBs of the device DNA. The next
// 32 bits will be addressable at BASE_ADDR+4, and so on.
// DNA_WIDTH: The width of the DNA register. UltraScale(+) devices have a 96-bit
// DNA, 7-series have a 57-bit DNA. If DNA_WIDTH is smaller than
// that, only LSBs will be output. If it's larger, then the DNA
// will be zero-padded.
// DEVICE_TYPE: Either ULTRASCALE or 7SERIES.
//
`default_nettype none
module device_dna_ctrlport #(
parameter BASE_ADDR = 0,
// Number of bits of DNA to output
parameter DNA_WIDTH = 96,
// For future use: Different FPGA types have different primitives for reading DNA
parameter DEVICE_TYPE = "ULTRASCALE"
)(
input wire ctrlport_clk,
input wire reset,
input wire s_ctrlport_req_rd,
input wire [19:0] s_ctrlport_req_addr,
output wire s_ctrlport_resp_ack,
output wire [ 1:0] s_ctrlport_resp_status,
output wire [31:0] s_ctrlport_resp_data
);
`include "../rfnoc/core/ctrlport.vh"
if (DEVICE_TYPE != "ULTRASCALE" && DEVICE_TYPE != "7SERIES") begin : gen_assertion
ERROR_only_ultrascale_and_7series_supported();
end
wire [DNA_WIDTH-1:0] device_dna_value;
wire device_dna_valid;
wire [1:0] reg_ro_status;
device_dna #(
.DNA_WIDTH(DNA_WIDTH),
.DEVICE_TYPE(DEVICE_TYPE)
) device_dna_i (
.clk (ctrlport_clk),
.rst (reset),
.dna (device_dna_value),
.valid(device_dna_valid)
);
ctrlport_reg_ro #(
.ADDR (BASE_ADDR),
.WIDTH (DNA_WIDTH)
// Don't need to assert COHERENT, because device_dna_value won't change unless
// device_dna_valid is also deasserted
) dna_ctrlport_reg_ro_i (
.ctrlport_clk (ctrlport_clk ),
.s_ctrlport_req_rd (s_ctrlport_req_rd ),
.s_ctrlport_req_addr (s_ctrlport_req_addr ),
.s_ctrlport_resp_ack (s_ctrlport_resp_ack ),
.s_ctrlport_resp_status (reg_ro_status ),
.s_ctrlport_resp_data (s_ctrlport_resp_data),
.value_in (device_dna_value )
);
// If we don't have a valid timestamp yet, we finish transaction,
// but with an error code
assign s_ctrlport_resp_status = device_dna_valid ? reg_ro_status : CTRL_STS_CMDERR;
endmodule
`default_nettype wire