From d6e0d90dfd807c7a8acfceec9aa1990c987b7447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Str=C3=B6mbergson?= Date: Wed, 3 Apr 2024 13:51:34 +0200 Subject: [PATCH 1/3] First attempt at supporting host based reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The feature enables the interface_rts signal from the CH552 MCU in constraints as well as inte FPGA interface. The signal is routed into the clk_reset_gen block where it is sampled. If the sampled signal is set, a system reset is triggered Signed-off-by: Joachim Strömbergson --- hw/application_fpga/data/application_fpga_tk1.pcf | 2 +- hw/application_fpga/rtl/application_fpga.v | 7 ++++++- hw/application_fpga/rtl/clk_reset_gen.v | 13 ++++++++++++- hw/application_fpga/tb/application_fpga_vsim.v | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/hw/application_fpga/data/application_fpga_tk1.pcf b/hw/application_fpga/data/application_fpga_tk1.pcf index c22b7fa3..7070a041 100644 --- a/hw/application_fpga/data/application_fpga_tk1.pcf +++ b/hw/application_fpga/data/application_fpga_tk1.pcf @@ -15,7 +15,7 @@ set_io interface_rx 26 set_io interface_tx 25 # set_io interface_cts 27 -# set_io interface_rts 28 +set_io interface_rts 28 # Touch sense. diff --git a/hw/application_fpga/rtl/application_fpga.v b/hw/application_fpga/rtl/application_fpga.v index 4f8b5e54..4cc5d218 100644 --- a/hw/application_fpga/rtl/application_fpga.v +++ b/hw/application_fpga/rtl/application_fpga.v @@ -19,6 +19,7 @@ module application_fpga( output wire interface_rx, input wire interface_tx, + input wire interface_rts, input wire touch_event, @@ -148,7 +149,11 @@ module application_fpga( // Module instantiations. //---------------------------------------------------------------- clk_reset_gen #(.RESET_CYCLES(200)) - reset_gen_inst(.clk(clk), .rst_n(reset_n)); + reset_gen_inst( + .host_reset(interface_rts), + .clk(clk), + .rst_n(reset_n) + ); picorv32 #( diff --git a/hw/application_fpga/rtl/clk_reset_gen.v b/hw/application_fpga/rtl/clk_reset_gen.v index 4466f75a..d096abee 100644 --- a/hw/application_fpga/rtl/clk_reset_gen.v +++ b/hw/application_fpga/rtl/clk_reset_gen.v @@ -18,6 +18,7 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) ( + input wire host_reset, output wire clk, output wire rst_n ); @@ -33,6 +34,8 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) reg rst_n_reg = 1'h0; reg rst_n_new; + reg [1 : 0] host_reset_sample_reg = 2'h0; + wire hfosc_clk; wire pll_clk; @@ -93,7 +96,9 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) //---------------------------------------------------------------- always @(posedge clk) begin : reg_update - rst_n_reg <= rst_n_new; + rst_n_reg <= rst_n_new; + host_reset_sample_reg[0] <= host_reset; + host_reset_sample_reg[1] <= host_reset_sample_reg[0]; if (rst_ctr_we) rst_ctr_reg <= rst_ctr_new; @@ -114,6 +119,12 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) rst_ctr_new = rst_ctr_reg + 1'h1; rst_ctr_we = 1'h1; end + + if (host_reset_sample_reg[1]) begin + rst_n_new = 1'h0; + end + + end endmodule // reset_gen diff --git a/hw/application_fpga/tb/application_fpga_vsim.v b/hw/application_fpga/tb/application_fpga_vsim.v index b496daf5..fa3a3172 100644 --- a/hw/application_fpga/tb/application_fpga_vsim.v +++ b/hw/application_fpga/tb/application_fpga_vsim.v @@ -36,6 +36,7 @@ module application_fpga( output wire interface_rx, input wire interface_tx, + input wire interface_rts, input wire touch_event, From 16eba3b8dd9b550e3fa5f75786d0e8f052b48ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Str=C3=B6mbergson?= Date: Thu, 4 Apr 2024 11:44:14 +0200 Subject: [PATCH 2/3] Trigger the original reset loop logic when host requests a reset Add comments to explain function and clean up heade, footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Joachim Strömbergson --- hw/application_fpga/rtl/clk_reset_gen.v | 34 +++++++++++++++++-------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/hw/application_fpga/rtl/clk_reset_gen.v b/hw/application_fpga/rtl/clk_reset_gen.v index d096abee..95fb1680 100644 --- a/hw/application_fpga/rtl/clk_reset_gen.v +++ b/hw/application_fpga/rtl/clk_reset_gen.v @@ -1,12 +1,15 @@ //====================================================================== // // clk_reset_gen.v -// ----------- +// --------------- // Clock and reset generator used in the Tillitis Key 1 design. +// // This module instantiate the internal SB_HFOSC clock source in the // Lattice ice40 UP device. It then connects it to the PLL, and // finally connects the output from the PLL to the global clock net. // +// The reset generator provides a stable reset of the design. +// // // Author: Joachim Strombergson // Copyright (C) 2022 - Tillitis AB @@ -92,13 +95,15 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) //---------------------------------------------------------------- - // reg_update. + // reg_update + // + // Note no reset, since these registers are used to create + // the reset in the design. //---------------------------------------------------------------- always @(posedge clk) begin : reg_update - rst_n_reg <= rst_n_new; - host_reset_sample_reg[0] <= host_reset; - host_reset_sample_reg[1] <= host_reset_sample_reg[0]; + rst_n_reg <= rst_n_new; + host_reset_sample_reg <= {host_reset_sample_reg[0], host_reset}; if (rst_ctr_we) rst_ctr_reg <= rst_ctr_new; @@ -106,7 +111,15 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) //---------------------------------------------------------------- - // rst_logic. + // rst_logic + // + // From cold boot, when the bitstream has been loaded and + // all registers are zeroised. This means that the counter + // logic is active, and the reset is being asserted for + // RESET_CYCLES. Then the default reset reg value is applied. + // + // When a second reset is requested from the host we + // reset the counter. This activates the counter logic. //---------------------------------------------------------------- always @* begin : rst_logic @@ -121,14 +134,13 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) end if (host_reset_sample_reg[1]) begin - rst_n_new = 1'h0; + rst_ctr_new = 8'h0; + rst_ctr_we = 1'h1; end - - end -endmodule // reset_gen +endmodule // clk_reset_gen //====================================================================== -// EOF reset_gen.v +// EOF clk_reset_gen.v //====================================================================== From bd45d3b0ddd365c9eb63fc38c05a81d35480b1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Str=C3=B6mbergson?= Date: Thu, 4 Apr 2024 14:46:14 +0200 Subject: [PATCH 3/3] Move reset control and status into the tk1 core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tk1 core is now able to handle external and internal reset request, trigger a system and store reset status that persists the reset. The reset status is exposed to SW as bits 17..16 in the FW_APP register. The fw_app status is now bound to bit 0. Signed-off-by: Joachim Strömbergson --- hw/application_fpga/core/tk1/rtl/tk1.v | 106 ++++++++++++++++----- hw/application_fpga/rtl/application_fpga.v | 6 +- hw/application_fpga/rtl/clk_reset_gen.v | 14 +-- 3 files changed, 92 insertions(+), 34 deletions(-) diff --git a/hw/application_fpga/core/tk1/rtl/tk1.v b/hw/application_fpga/core/tk1/rtl/tk1.v index bd456421..2c1943c4 100644 --- a/hw/application_fpga/core/tk1/rtl/tk1.v +++ b/hw/application_fpga/core/tk1/rtl/tk1.v @@ -28,6 +28,9 @@ module tk1( output wire [14 : 0] ram_aslr, output wire [31 : 0] ram_scramble, + input wire external_reset, + output wire sys_reset, + output wire led_r, output wire led_g, output wire led_b, @@ -144,6 +147,15 @@ module tk1( reg force_trap_reg; reg force_trap_set; + reg [1 : 0] external_reset_sample_reg = 2'h0; + reg [1 : 0] external_reset_sample_new; + reg sys_reset_reg; + reg sys_reset_we; + + reg [1 : 0] reset_status_reg = 2'h0; + reg [1 : 0] reset_status_new; + reg reset_status_we; + //---------------------------------------------------------------- // Wires. @@ -173,6 +185,8 @@ module tk1( assign ram_aslr = ram_aslr_reg; assign ram_scramble = ram_scramble_reg; + assign sys_reset = sys_reset_reg; + //---------------------------------------------------------------- // Module instance. @@ -204,35 +218,40 @@ module tk1( //---------------------------------------------------------------- // reg_update + // + // Note that the reset_status_reg is not reset, since that would + // erase the status info we want to persist between reboots. //---------------------------------------------------------------- always @ (posedge clk) begin : reg_update if (!reset_n) begin - switch_app_reg <= 1'h0; - led_reg <= 3'h6; - gpio1_reg <= 2'h0; - gpio2_reg <= 2'h0; - gpio3_reg <= 1'h0; - gpio4_reg <= 1'h0; - app_start_reg <= 32'h0; - app_size_reg <= 32'h0; - blake2s_addr_reg <= 32'h0; - cdi_mem[0] <= 32'h0; - cdi_mem[1] <= 32'h0; - cdi_mem[2] <= 32'h0; - cdi_mem[3] <= 32'h0; - cdi_mem[4] <= 32'h0; - cdi_mem[5] <= 32'h0; - cdi_mem[6] <= 32'h0; - cdi_mem[7] <= 32'h0; - cpu_trap_ctr_reg <= 24'h0; - cpu_trap_led_reg <= 3'h0; - cpu_mon_en_reg <= 1'h0; - cpu_mon_first_reg <= 32'h0; - cpu_mon_last_reg <= 32'h0; - ram_aslr_reg <= 15'h0; - ram_scramble_reg <= 32'h0; - force_trap_reg <= 1'h0; + switch_app_reg <= 1'h0; + led_reg <= 3'h6; + gpio1_reg <= 2'h0; + gpio2_reg <= 2'h0; + gpio3_reg <= 1'h0; + gpio4_reg <= 1'h0; + app_start_reg <= 32'h0; + app_size_reg <= 32'h0; + blake2s_addr_reg <= 32'h0; + cdi_mem[0] <= 32'h0; + cdi_mem[1] <= 32'h0; + cdi_mem[2] <= 32'h0; + cdi_mem[3] <= 32'h0; + cdi_mem[4] <= 32'h0; + cdi_mem[5] <= 32'h0; + cdi_mem[6] <= 32'h0; + cdi_mem[7] <= 32'h0; + cpu_trap_ctr_reg <= 24'h0; + cpu_trap_led_reg <= 3'h0; + cpu_mon_en_reg <= 1'h0; + cpu_mon_first_reg <= 32'h0; + cpu_mon_last_reg <= 32'h0; + ram_aslr_reg <= 15'h0; + ram_scramble_reg <= 32'h0; + force_trap_reg <= 1'h0; + sys_reset_reg <= 1'h0; + external_reset_sample_reg <= 2'h0; end else begin @@ -244,6 +263,17 @@ module tk1( gpio2_reg[0] <= gpio2; gpio2_reg[1] <= gpio2_reg[0]; + external_reset_sample_reg <= external_reset_sample_new; + + + if (sys_reset_we) begin + sys_reset_reg <= 1'h1; + end + + if (reset_status_we) begin + reset_status_reg <= reset_status_new; + end + if (switch_app_we) begin switch_app_reg <= 1'h1; end @@ -330,6 +360,30 @@ module tk1( end + //---------------------------------------------------------------- + // system_reset_logic + // + // Sample the external reset request input. If it is set, we + // assert the sys_reset signal and sets the reset status reg + // to indicate that the reset was caused by external request. + // When the reset happens the sys_reset_reg will be cleared. + //---------------------------------------------------------------- + always @* + begin : system_reset_logic + sys_reset_we = 1'h0; + reset_status_new = 2'h0; + reset_status_we = 1'h0; + + external_reset_sample_new = {external_reset_sample_reg[0], external_reset}; + + if (external_reset_sample_reg[1]) begin + sys_reset_we = 1'h1; + reset_status_new = 2'h1; + reset_status_we = 1'h1; + end + end + + //---------------------------------------------------------------- // security_monitor // @@ -476,7 +530,7 @@ module tk1( end if (address == ADDR_SWITCH_APP) begin - tmp_read_data = {32{switch_app_reg}}; + tmp_read_data = {14'h0, reset_status_reg, 15'h0, switch_app_reg}; end if (address == ADDR_LED) begin diff --git a/hw/application_fpga/rtl/application_fpga.v b/hw/application_fpga/rtl/application_fpga.v index 4cc5d218..7c916994 100644 --- a/hw/application_fpga/rtl/application_fpga.v +++ b/hw/application_fpga/rtl/application_fpga.v @@ -142,6 +142,7 @@ module application_fpga( wire force_trap; wire [14 : 0] ram_aslr; wire [31 : 0] ram_scramble; + wire tk1_sys_reset; /* verilator lint_on UNOPTFLAT */ @@ -150,7 +151,7 @@ module application_fpga( //---------------------------------------------------------------- clk_reset_gen #(.RESET_CYCLES(200)) reset_gen_inst( - .host_reset(interface_rts), + .sys_reset(tk1_sys_reset), .clk(clk), .rst_n(reset_n) ); @@ -322,6 +323,9 @@ module application_fpga( .ram_aslr(ram_aslr), .ram_scramble(ram_scramble), + .external_reset(interface_rts), + .sys_reset(tk1_sys_reset), + .led_r(led_r), .led_g(led_g), .led_b(led_b), diff --git a/hw/application_fpga/rtl/clk_reset_gen.v b/hw/application_fpga/rtl/clk_reset_gen.v index 95fb1680..c5ef1987 100644 --- a/hw/application_fpga/rtl/clk_reset_gen.v +++ b/hw/application_fpga/rtl/clk_reset_gen.v @@ -21,7 +21,7 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) ( - input wire host_reset, + input wire sys_reset, output wire clk, output wire rst_n ); @@ -37,7 +37,7 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) reg rst_n_reg = 1'h0; reg rst_n_new; - reg [1 : 0] host_reset_sample_reg = 2'h0; + reg sys_reset_reg; wire hfosc_clk; wire pll_clk; @@ -102,8 +102,8 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) //---------------------------------------------------------------- always @(posedge clk) begin : reg_update - rst_n_reg <= rst_n_new; - host_reset_sample_reg <= {host_reset_sample_reg[0], host_reset}; + rst_n_reg <= rst_n_new; + sys_reset_reg <= sys_reset; if (rst_ctr_we) rst_ctr_reg <= rst_ctr_new; @@ -118,8 +118,8 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) // logic is active, and the reset is being asserted for // RESET_CYCLES. Then the default reset reg value is applied. // - // When a second reset is requested from the host we - // reset the counter. This activates the counter logic. + // When a system reset is requested we reset the counter. + // This activates the counter logic and the reset is asserted. //---------------------------------------------------------------- always @* begin : rst_logic @@ -133,7 +133,7 @@ module clk_reset_gen #(parameter RESET_CYCLES = 200) rst_ctr_we = 1'h1; end - if (host_reset_sample_reg[1]) begin + if (sys_reset_reg) begin rst_ctr_new = 8'h0; rst_ctr_we = 1'h1; end