Make initial public release

This commit is contained in:
Joachim Strömbergson 2022-09-19 08:51:11 +02:00 committed by Daniel Lublin
commit 715de60f4a
251 changed files with 881225 additions and 0 deletions

View file

@ -0,0 +1,7 @@
# uds
Unique Device Secret core
## Introduction
This core store and protect the Unique Device Secret. The
storage is implemented in discrete registers. The contents can be read once between chip reset, and only if the system is in not in application access mode.

View file

@ -0,0 +1,129 @@
//======================================================================
//
// uds.v
// --------
// Top level wrapper for the uds core.
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
//
//======================================================================
`default_nettype none
module uds(
input wire clk,
input wire reset_n,
output wire fw_app_mode,
input wire cs,
input wire [7 : 0] address,
output wire [31 : 0] read_data,
output wire ready
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
localparam ADDR_NAME0 = 8'h00;
localparam ADDR_NAME1 = 8'h01;
localparam ADDR_VERSION = 8'h02;
localparam ADDR_UDS_FIRST = 8'h10;
localparam ADDR_UDS_LAST = 8'h17;
localparam CORE_NAME0 = 32'h7564735f; // "uds_"
localparam CORE_NAME1 = 32'h6d656d20; // "mem "
localparam CORE_VERSION = 32'h00000001;
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [31 : 0] uds_reg [0 : 7];
initial $readmemh(`UDS_HEX, uds_reg);
reg uds_rd_reg [0 : 7];
reg uds_rd_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [31 : 0] tmp_read_data;
reg tmp_ready;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign read_data = tmp_read_data;
assign ready = tmp_ready;
//----------------------------------------------------------------
// reg_update
//----------------------------------------------------------------
always @ (posedge clk)
begin : reg_update
integer i;
if (!reset_n) begin
for (i = 0 ; i < 8 ; i = i + 1) begin
uds_rd_reg[i] <= 1'h0;;
end
end
else begin
if (uds_rd_we) begin
uds_rd_reg[address[2 : 0]] <= 1'h1;
end
end
end // reg_update
//----------------------------------------------------------------
// api
//
// The interface command decoding logic.
//----------------------------------------------------------------
always @*
begin : api
uds_rd_we = 1'h0;
tmp_read_data = 32'h0;
tmp_ready = 1'h0;
if (cs) begin
tmp_ready = 1'h1;
if (address == ADDR_NAME0) begin
tmp_read_data = CORE_NAME0;
end
if (address == ADDR_NAME1) begin
tmp_read_data = CORE_NAME1;
end
if (address == ADDR_VERSION) begin
tmp_read_data = CORE_VERSION;
end
if ((address >= ADDR_UDS_FIRST) && (address <= ADDR_UDS_LAST)) begin
if (!fw_app_mode) begin
if (uds_rd_reg[address[2 : 0]] == 1'h0) begin
tmp_read_data = uds_reg[address[2 : 0]];
uds_rd_we = 1'h1;
end
end
end
end
end
endmodule // uds
//======================================================================
// EOF uds.v
//======================================================================

View file

@ -0,0 +1,300 @@
//======================================================================
//
// tb_uds.v
// -----------
// Testbench for the UDS core.
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
//
//======================================================================
`default_nettype none
module tb_uds();
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
parameter DEBUG = 1;
parameter DUMP_WAIT = 0;
parameter CLK_HALF_PERIOD = 1;
parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
localparam ADDR_NAME0 = 8'h00;
localparam ADDR_NAME1 = 8'h01;
localparam ADDR_VERSION = 8'h02;
localparam ADDR_UDS_FIRST = 8'h10;
localparam ADDR_UDS_LAST = 8'h17;
//----------------------------------------------------------------
// Register and Wire declarations.
//----------------------------------------------------------------
reg [31 : 0] cycle_ctr;
reg [31 : 0] error_ctr;
reg [31 : 0] tc_ctr;
reg tb_monitor;
reg tb_clk;
reg tb_reset_n;
reg tb_cs;
reg [7 : 0] tb_address;
wire [31 : 0] tb_read_data;
reg [31 : 0] read_data;
//----------------------------------------------------------------
// Device Under Test.
//----------------------------------------------------------------
uds dut(
.clk(tb_clk),
.reset_n(tb_reset_n),
.cs(tb_cs),
.address(tb_address),
.read_data(tb_read_data)
);
//----------------------------------------------------------------
// clk_gen
//
// Always running clock generator process.
//----------------------------------------------------------------
always
begin : clk_gen
#CLK_HALF_PERIOD;
tb_clk = !tb_clk;
end // clk_gen
//----------------------------------------------------------------
// sys_monitor()
//
// An always running process that creates a cycle counter and
// conditionally displays information about the DUT.
//----------------------------------------------------------------
always
begin : sys_monitor
cycle_ctr = cycle_ctr + 1;
#(CLK_PERIOD);
if (tb_monitor)
begin
dump_dut_state();
end
end
//----------------------------------------------------------------
// dump_dut_state()
//
// Dump the state of the dump when needed.
//----------------------------------------------------------------
task dump_dut_state;
begin : dump_dut_state
integer i;
$display("State of DUT");
$display("------------");
$display("Cycle: %08d", cycle_ctr);
for (i = 0 ; i < 8 ; i = i + 1) begin
$display("uds_reg[%1d]: 0x%08x, uds_rd_reg[%1d]: 0x%1x",
i, dut.uds_reg[i], i, dut.uds_rd_reg[i]);
end
$display("");
$display("");
end
endtask // dump_dut_state
//----------------------------------------------------------------
// reset_dut()
//
// Toggle reset to put the DUT into a well known state.
//----------------------------------------------------------------
task reset_dut;
begin
$display("--- Toggle reset.");
tb_reset_n = 0;
#(2 * CLK_PERIOD);
tb_reset_n = 1;
end
endtask // reset_dut
//----------------------------------------------------------------
// display_test_result()
//
// Display the accumulated test results.
//----------------------------------------------------------------
task display_test_result;
begin
if (error_ctr == 0)
begin
$display("--- All %02d test cases completed successfully", tc_ctr);
end
else
begin
$display("--- %02d tests completed - %02d test cases did not complete successfully.",
tc_ctr, error_ctr);
end
end
endtask // display_test_result
//----------------------------------------------------------------
// init_sim()
//
// Initialize all counters and testbed functionality as well
// as setting the DUT inputs to defined values.
//----------------------------------------------------------------
task init_sim;
begin
cycle_ctr = 0;
error_ctr = 0;
tc_ctr = 0;
tb_monitor = 0;
tb_clk = 1'h0;
tb_reset_n = 1'h1;
tb_cs = 1'h0;
tb_address = 8'h0;
end
endtask // init_sim
//----------------------------------------------------------------
// read_word()
//
// Read a data word from the given address in the DUT.
// the word read will be available in the global variable
// read_data.
//----------------------------------------------------------------
task read_word(input [11 : 0] address);
begin
tb_address = address;
tb_cs = 1;
#(CLK_PERIOD);
read_data = tb_read_data;
tb_cs = 0;
if (DEBUG)
begin
$display("--- Reading 0x%08x from 0x%02x.", read_data, address);
$display("");
end
end
endtask // read_word
//----------------------------------------------------------------
// test1()
//----------------------------------------------------------------
task test1;
begin
tc_ctr = tc_ctr + 1;
tb_monitor = 1'h0;
$display("");
$display("--- test1: started.");
$display("--- test1: Reading NAME and version info.");
read_word(ADDR_NAME0);
read_word(ADDR_NAME1);
read_word(ADDR_VERSION);
$display("--- test1: Dumping DUT state to show UDS contents");
dump_dut_state();
$display("--- test1: Reading UDS words.");
read_word(ADDR_UDS_FIRST + 0);
read_word(ADDR_UDS_FIRST + 1);
read_word(ADDR_UDS_FIRST + 2);
$display("--- test1: Dumping state again to see read bits.");
dump_dut_state();
$display("--- test1: Reading rest of the words.");
read_word(ADDR_UDS_FIRST + 3);
read_word(ADDR_UDS_FIRST + 4);
read_word(ADDR_UDS_FIRST + 5);
read_word(ADDR_UDS_FIRST + 6);
read_word(ADDR_UDS_FIRST + 7);
$display("--- test1: Dumping state again to see read bits.");
dump_dut_state();
$display("--- test1: Reading UDS words again.");
read_word(ADDR_UDS_FIRST + 0);
read_word(ADDR_UDS_FIRST + 1);
read_word(ADDR_UDS_FIRST + 2);
read_word(ADDR_UDS_FIRST + 3);
read_word(ADDR_UDS_FIRST + 4);
read_word(ADDR_UDS_FIRST + 5);
read_word(ADDR_UDS_FIRST + 6);
read_word(ADDR_UDS_FIRST + 7);
$display("--- test1: Resetting DUT.");
reset_dut();
$display("--- test1: Dumping state again to see read bits.");
dump_dut_state();
$display("--- test1: Reading UDS words.");
read_word(ADDR_UDS_FIRST + 0);
read_word(ADDR_UDS_FIRST + 1);
read_word(ADDR_UDS_FIRST + 2);
read_word(ADDR_UDS_FIRST + 3);
read_word(ADDR_UDS_FIRST + 4);
read_word(ADDR_UDS_FIRST + 5);
read_word(ADDR_UDS_FIRST + 6);
read_word(ADDR_UDS_FIRST + 7);
$display("--- test1: Reading UDS words again.");
read_word(ADDR_UDS_FIRST + 0);
read_word(ADDR_UDS_FIRST + 1);
read_word(ADDR_UDS_FIRST + 2);
read_word(ADDR_UDS_FIRST + 3);
read_word(ADDR_UDS_FIRST + 4);
read_word(ADDR_UDS_FIRST + 5);
read_word(ADDR_UDS_FIRST + 6);
read_word(ADDR_UDS_FIRST + 7);
$display("--- test1: completed.");
$display("");
end
endtask // tes1
//----------------------------------------------------------------
// uds_test
//----------------------------------------------------------------
initial
begin : uds_test
$display("");
$display(" -= Testbench for uds started =-");
$display(" ===========================");
$display("");
init_sim();
reset_dut();
test1();
display_test_result();
$display("");
$display(" -= Testbench for uds started =-");
$display(" ===========================");
$display("");
$finish;
end // uds_test
endmodule // tb_uds
//======================================================================
// EOF tb_uds.v
//======================================================================

View file

@ -0,0 +1,55 @@
#===================================================================
#
# Makefile
# --------
# Makefile for building the UDS core.
#
#
# Author: Joachim Strombergson
# Copyright (C) 2022 - Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
#
#===================================================================
TOP_SRC=../rtl/uds.v
TB_TOP_SRC =../tb/tb_uds.v
CC = iverilog
CC_FLAGS = -Wall
LINT = verilator
LINT_FLAGS = +1364-2001ext+ --lint-only -Wall -Wno-fatal -Wno-DECLFILENAME
all: top.sim
top.sim: $(TB_TOP_SRC) $(TOP_SRC)
$(CC) $(CC_FLAGS) -o top.sim $(TB_TOP_SRC) $(TOP_SRC)
sim-top: top.sim
./top.sim
lint-top: $(TOP_SRC)
$(LINT) $(LINT_FLAGS) $(TOP_SRC)
clean:
rm -f top.sim
help:
@echo "Build system for simulation of UDS core"
@echo ""
@echo "Supported targets:"
@echo "------------------"
@echo "top.sim: Build top level simulation target."
@echo "sim-top: Run top level simulation."
@echo "lint-top: Lint top rtl source files."
@echo "clean: Delete all built files."
#===================================================================
# EOF Makefile
#===================================================================