diff --git a/hw/application_fpga/Makefile b/hw/application_fpga/Makefile index 1a1c868..6595756 100644 --- a/hw/application_fpga/Makefile +++ b/hw/application_fpga/Makefile @@ -65,8 +65,10 @@ VERILOG_SRCS = \ $(P)/core/timer/rtl/timer_core.v \ $(P)/core/timer/rtl/timer.v \ $(P)/core/uds/rtl/uds.v \ + $(P)/core/uds/rtl/uds_rom.v \ $(P)/core/touch_sense/rtl/touch_sense.v \ $(P)/core/tk1/rtl/tk1.v \ + $(P)/core/tk1/rtl/udi_rom.v \ $(P)/core/uart/rtl/uart_core.v \ $(P)/core/uart/rtl/uart_fifo.v \ $(P)/core/uart/rtl/uart.v \ @@ -228,17 +230,18 @@ tb: # Main FPGA build flow. # Synthesis. Place & Route. Bitstream generation. #------------------------------------------------------------------- -synth.json: $(FPGA_SRC) $(VERILOG_SRCS) bram_fw.hex $(P)/data/uds.hex $(P)/data/udi.hex +synth.json: $(FPGA_SRC) $(VERILOG_SRCS) bram_fw.hex $(YOSYS_PATH)yosys -v3 -l synth.log -DBRAM_FW_SIZE=$(BRAM_FW_SIZE) \ -DFIRMWARE_HEX=\"$(P)/bram_fw.hex\" \ - -DUDS_HEX=\"$(P)/data/uds.hex\" \ - -DUDI_HEX=\"$(P)/data/udi.hex\" \ -p 'synth_ice40 -dsp -top application_fpga -json $@; write_verilog -attr2comment synth.v' \ $(filter %.v, $^) -application_fpga.asc: synth.json $(P)/data/$(PIN_FILE) +application_fpga_par.json: synth.json $(P)/data/$(PIN_FILE) $(NEXTPNR_PATH)nextpnr-ice40 --ignore-loops --up5k --package sg48 --json $< \ - --pcf $(P)/data/$(PIN_FILE) --asc $@ + --pcf $(P)/data/$(PIN_FILE) --write $@ + +application_fpga.asc: application_fpga_par.json $(P)/data/uds.hex $(P)/data/udi.hex + UDS_HEX="$(P)/data/uds.hex" UDI_HEX="$(P)/data/udi.hex" OUT_ASC=$@ $(NEXTPNR_PATH)nextpnr-ice40 --up5k --package sg48 --ignore-loops --json $< --run tools/personalize.py application_fpga.bin: application_fpga.asc bram_fw.hex firmware.hex $(ICESTORM_PATH)icebram -v bram_fw.hex firmware.hex < $< > $<.tmp @@ -320,6 +323,7 @@ clean: clean_fw rm -f bram_fw.hex rm -f synth.{log,v,json} route.v application_fpga.{asc,bin,vcd} application_fpga_testfw.bin rm -f tb_application_fpga.vvp synth_tb.vvp route_tb.vvp + rm -f application_fpga_par.json rm -f *.vcd rm -f lint_issues.txt rm -rf verilated diff --git a/hw/application_fpga/core/tk1/rtl/tk1.v b/hw/application_fpga/core/tk1/rtl/tk1.v index 9a41225..c3d1534 100644 --- a/hw/application_fpga/core/tk1/rtl/tk1.v +++ b/hw/application_fpga/core/tk1/rtl/tk1.v @@ -99,9 +99,6 @@ module tk1( reg [31 : 0] cdi_mem [0 : 7]; reg cdi_mem_we; - reg [31 : 0] udi_mem [0 : 1]; - initial $readmemh(`UDI_HEX, udi_mem); - reg switch_app_reg; reg switch_app_we; @@ -156,6 +153,7 @@ module tk1( reg [2 : 0] muxed_led; + wire [31:0] udi_rdata; //---------------------------------------------------------------- // Concurrent connectivity for ports etc. @@ -196,6 +194,12 @@ module tk1( /* verilator lint_on PINMISSING */ + udi_rom rom_i( + .addr(address[0]), + .data(udi_rdata) + ); + + //---------------------------------------------------------------- // reg_update //---------------------------------------------------------------- @@ -500,7 +504,7 @@ module tk1( if ((address >= ADDR_UDI_FIRST) && (address <= ADDR_UDI_LAST)) begin if (!switch_app_reg) begin - tmp_read_data = udi_mem[address[0]]; + tmp_read_data = udi_rdata; end end end diff --git a/hw/application_fpga/core/tk1/rtl/udi_rom.v b/hw/application_fpga/core/tk1/rtl/udi_rom.v new file mode 100644 index 0000000..1c7f2bf --- /dev/null +++ b/hw/application_fpga/core/tk1/rtl/udi_rom.v @@ -0,0 +1,35 @@ +//====================================================================== +// +// udi_rom.v +// --------- +// UDI rom generated by instatiating named SB_LUT4 resources. +// Note: This makes the design tech specicific. +// +// +// Author: Claire Xiena Wolf. +// Copyright (C) 2023 - Tillitis AB +// SPDX-License-Identifier: GPL-2.0-only +// +//====================================================================== + +module udi_rom ( + input wire [0:0] addr, + output wire [31:0] data +); + generate + genvar ii; + for (ii = 0; ii < 32; ii = ii + 1'b1) begin: luts + (* udi_rom_idx=ii, keep *) SB_LUT4 + #( + .LUT_INIT({2'h1}) + ) lut_i ( + .I0(addr[0]), + .O(data[ii]) + ); + end + endgenerate +endmodule + +//====================================================================== +// EOF udi_rom.v +//====================================================================== diff --git a/hw/application_fpga/core/uds/rtl/uds.v b/hw/application_fpga/core/uds/rtl/uds.v index efda3d6..cc3bf45 100644 --- a/hw/application_fpga/core/uds/rtl/uds.v +++ b/hw/application_fpga/core/uds/rtl/uds.v @@ -36,9 +36,6 @@ module uds( //---------------------------------------------------------------- // 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; @@ -57,6 +54,17 @@ module uds( assign ready = tmp_ready; + //---------------------------------------------------------------- + // uds rom instance. + //---------------------------------------------------------------- + uds_rom rom_i( + .addr(address), + .re(uds_rd_we), + .data(tmp_read_data) + ); + + + //---------------------------------------------------------------- // reg_update //---------------------------------------------------------------- @@ -85,7 +93,6 @@ module uds( always @* begin : api uds_rd_we = 1'h0; - tmp_read_data = 32'h0; tmp_ready = 1'h0; if (cs) begin @@ -94,14 +101,12 @@ module uds( 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 //====================================================================== diff --git a/hw/application_fpga/core/uds/rtl/uds_rom.v b/hw/application_fpga/core/uds/rtl/uds_rom.v new file mode 100644 index 0000000..42496b5 --- /dev/null +++ b/hw/application_fpga/core/uds/rtl/uds_rom.v @@ -0,0 +1,39 @@ +//====================================================================== +// +// uds_rom.v +// --------- +// UDS rom. Generated by instantiating named SB_LUT4 resources. +// Note: This makes the design technology specific. +// +// +// Author: Claire Xenia Wolf +// Copyright (C) 2023 - YosysHQ, Tillitis AB +// SPDX-License-Identifier: GPL-2.0-only +// +//====================================================================== + +`default_nettype none + +module uds_rom( + input wire [2:0] addr, + input wire re, + output wire [31:0] data + ); + + generate + genvar ii; + for (ii = 0; ii < 32; ii = ii + 1'b1) begin: luts + (* uds_rom_idx=ii, keep *) SB_LUT4 + #( + .LUT_INIT({8'ha6 ^ ii[7:0], 8'h00}) + ) lut_i ( + .I0(addr[0]), .I1(addr[1]), .I2(addr[2]), .I3(re), + .O(data[ii]) + ); + end + endgenerate +endmodule // uds_rom + +//====================================================================== +// EOF uds_rom.v +//====================================================================== diff --git a/hw/application_fpga/tools/personalize.py b/hw/application_fpga/tools/personalize.py new file mode 100644 index 0000000..2e5d86f --- /dev/null +++ b/hw/application_fpga/tools/personalize.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +#======================================================================= +# +# personalize.py +# -------------- +# Python program that patches the UDS and UDI implemented using +# named LUT4 instances to have unique initial values, not the generic +# values used during synthesis, p&r and mapping. This allows us to +# generate device unique bitstreams without running the complete flow. +# +# +# Copyright (C) 2023 Tillitis AB +# Written by Myrtle Shah +# SPDX-License-Identifier: GPL-2.0-only +# +#======================================================================= + +import os + +def parse_hex(file, length): + data = [] + with open(file, "r") as f: + for line in f: + l = line.strip() + if len(l) > 0: + data.append(int(l, 16)) + assert len(data) == length, len(data) + return data + +def rewrite_lut(lut, idx, data, has_re=False): + # each LUT provides one bit per 32-bit word out of 64/256 bits total + new_init = 0 + for i, word in enumerate(data): + if (word >> idx) & 0x1: + # repeat so inputs above address have a don't care value + repeat = (16 // len(data)) + for k in range(repeat): + # UDS also has a read enable + # LUT output is zero if this isn't asserted + if has_re and k < (repeat // 2): + continue + new_init |= (1 << (k * len(data) + i)) + lut.setParam("LUT_INIT", f"{new_init:016b}") + +uds = parse_hex(os.environ["UDS_HEX"], 8) +udi = parse_hex(os.environ["UDI_HEX"], 2) + +uds_lut_count = 0 +udi_lut_count = 0 + +for cell_name, cell in ctx.cells: + if "uds_rom_idx" in cell.attrs: + index = int(cell.attrs["uds_rom_idx"], 2) + rewrite_lut(cell, index, uds, True) + uds_lut_count += 1 + if "udi_rom_idx" in cell.attrs: + index = int(cell.attrs["udi_rom_idx"], 2) + rewrite_lut(cell, index, udi, False) + udi_lut_count += 1 +assert uds_lut_count == 32, uds_lut_count +assert udi_lut_count == 32, udi_lut_count + +write_bitstream(ctx, os.environ["OUT_ASC"])