Files
b210-k7-fpga/lib/sim/hwutils/dna/device_dna_tb.sv
T
Martin Braun 76f67bbb0c 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
2024-05-27 17:05:06 +02:00

207 lines
6.1 KiB
Systemverilog

//
// Copyright 2023 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Description:
//
// Testbench for device_dna and device_dna_ctrlport.
//
`default_nettype none
module device_dna_tb ();
// Include macros and time declarations for use with PkgTestExec
`include "test_exec.svh"
import PkgTestExec::*;
localparam real CLK_PERIOD = 10.0; // ns
//---------------------------------------------------------------------------
// Clocks and Resets
//---------------------------------------------------------------------------
bit clk;
bit rst;
bit rst_dut = 0;
sim_clock_gen #(.PERIOD(CLK_PERIOD))
clk_gen (.clk(clk), .rst(rst));
//---------------------------------------------------------------------------
// Device Under Test (DUT)
//---------------------------------------------------------------------------
logic i_ctrlport_req_rd = 1'b0;
logic [19:0] i_ctrlport_req_addr = 20'h0;
logic o_ctrlport_resp_ack;
logic [1:0] o_ctrlport_resp_status;
logic [31:0] o_ctrlport_resp_data;
logic o_ctrlport_resp_ack_7s;
logic [1:0] o_ctrlport_resp_status_7s;
logic [31:0] o_ctrlport_resp_data_7s;
device_dna_ctrlport #(
.BASE_ADDR(0),
.DNA_WIDTH(128)
) device_dna_dut (
.ctrlport_clk (clk),
.reset (rst | rst_dut),
.s_ctrlport_req_rd (i_ctrlport_req_rd ),
.s_ctrlport_req_addr (i_ctrlport_req_addr ),
.s_ctrlport_resp_ack (o_ctrlport_resp_ack ),
.s_ctrlport_resp_status(o_ctrlport_resp_status),
.s_ctrlport_resp_data (o_ctrlport_resp_data )
);
device_dna_ctrlport #(
.BASE_ADDR(32),
.DNA_WIDTH(57),
.DEVICE_TYPE("7SERIES")
) device_dna_dut_7s (
.ctrlport_clk (clk),
.reset (rst | rst_dut),
.s_ctrlport_req_rd (i_ctrlport_req_rd ),
.s_ctrlport_req_addr (i_ctrlport_req_addr ),
.s_ctrlport_resp_ack (o_ctrlport_resp_ack_7s ),
.s_ctrlport_resp_status(o_ctrlport_resp_status_7s),
.s_ctrlport_resp_data (o_ctrlport_resp_data_7s )
);
//--------------------------------
// Task
//--------------------------------
task automatic check_dna(
int address,
int expected_dna = 1
);
i_ctrlport_req_addr <= address;
i_ctrlport_req_rd <= 1;
@(posedge clk);
i_ctrlport_req_rd <= 0;
while (!o_ctrlport_resp_ack) @(posedge clk);
test.assert_error(
o_ctrlport_resp_ack, "CtrlPort response ACK not asserted!");
test.assert_error(
!o_ctrlport_resp_status,
$sformatf("CtrlPort response status not zero (%d)!", o_ctrlport_resp_status));
test.assert_error(
o_ctrlport_resp_data == expected_dna,
$sformatf("Incorrect DNA value: %x! Expected %x.", o_ctrlport_resp_data, expected_dna));
@(posedge clk);
endtask;
task automatic check_dna_7s(
int address,
int expected_dna = 1
);
i_ctrlport_req_addr <= address;
i_ctrlport_req_rd <= 1;
@(posedge clk);
i_ctrlport_req_rd <= 0;
while (!o_ctrlport_resp_ack_7s) @(posedge clk);
test.assert_error(
o_ctrlport_resp_ack_7s, "CtrlPort response ACK not asserted!");
test.assert_error(
!o_ctrlport_resp_status_7s,
$sformatf("CtrlPort response status not zero (%d)!", o_ctrlport_resp_status_7s));
test.assert_error(
o_ctrlport_resp_data_7s == expected_dna,
$sformatf("Incorrect DNA value: %x! Expected %x.", o_ctrlport_resp_data_7s, expected_dna));
@(posedge clk);
endtask;
//---------------------------------------------------------------------------
// Main Test Process
//---------------------------------------------------------------------------
initial begin : tb_main
string tb_name;
tb_name = $sformatf("device_dna_ctrlport");
test.start_tb(tb_name, 1ms);
//-------------------------------------------------------
// Reset clock generator and wait for reset to complete
//-------------------------------------------------------
test.start_test("Reset", 100us);
clk_gen.reset();
if (rst) @rst;
test.end_test();
//--------------------------------
// Test Sequences
//--------------------------------
// Reset DNA module and verify that we cannot read back serial immediately after
test.start_test("Reset DUT only", 2us);
rst_dut <= 1; // Assert reset for one clock cycle
@(posedge clk);
rst_dut <= 0;
// Now we wait for some amount of clock cycles that is smaller than the time
// it takes to fully load the DNA value (at least 96 cycles on any UltraScale
// device)
repeat (12) @(posedge clk);
// Request a read and wait for ACK
i_ctrlport_req_rd <= 1;
@(posedge clk);
i_ctrlport_req_rd <= 0;
while (!o_ctrlport_resp_ack) @(posedge clk);
test.assert_error(
o_ctrlport_resp_status == 2'b01,
$sformatf("Response status should be 1, but is %d", o_ctrlport_resp_status));
// Oh no! We call reset *again*, in the middle of a read.
rst_dut <= 1; // Assert reset for one clock cycle
@(posedge clk);
rst_dut <= 0;
// Now wait for status to clear
while (o_ctrlport_resp_status) @(posedge clk);
test.end_test();
// Read back the DNA value
test.start_test("Reading DNA values", 1ms);
check_dna(0, 32'h11C0FFEE);
check_dna(4, 32'hC0D111A0);
check_dna(8, 32'h012F1110);
@(posedge clk);
test.end_test();
// One more reset and read
test.start_test("Reading DNA values after 2nd reset", 1ms);
rst_dut <= 1; // Assert reset for one clock cycle
@(posedge clk);
rst_dut <= 0;
@(posedge clk);
// Now wait for status to clear
while (o_ctrlport_resp_status) @(posedge clk);
check_dna(0, 32'h11C0FFEE);
test.end_test();
// Read back the DNA value (7-series)
test.start_test("Reading DNA values (7-series)", 1ms);
check_dna_7s(32, 32'hC0DE00FF);
check_dna_7s(36, 32'h00D111A0);
@(posedge clk);
test.end_test();
//--------------------------------
// Finish Up
//--------------------------------
test.end_tb();
end : tb_main
endmodule : device_dna_tb
`default_nettype wire