[top] First draft of reset controller integration

- This PR does not implement the actual reset controller, but
  simply wires up the top level resets as if the controller existed
- The purpose of this PR is to get agreement on the general connectivity
  or reset nets and ports
diff --git a/hw/Makefile b/hw/Makefile
index 8277ea0..aab067a 100644
--- a/hw/Makefile
+++ b/hw/Makefile
@@ -16,6 +16,14 @@
 
 TOPS ?= top_earlgrey
 
+# conditional flags
+VERBOSE ?= 0
+toolflags ?=
+ifeq ($(VERBOSE),1)
+  toolflags      += -v
+endif
+
+
 ips_reg = $(addsuffix _reg, $(IPS))
 
 tops_gen = $(addsuffix _gen,$(TOPS))
@@ -44,8 +52,8 @@
 	$(eval $@_TOP := $(strip $(foreach top,$(TOPS),$(findstring $(top),$@))))
 	${PRJ_DIR}/util/topgen.py -t ${PRJ_DIR}/hw/$($@_TOP)/doc/$($@_TOP).hjson \
 		--tpl ${PRJ_DIR}/hw/$($@_TOP)/doc/ \
-		-o ${PRJ_DIR}/hw/$($@_TOP)/
+		-o ${PRJ_DIR}/hw/$($@_TOP)/ ${toolflags}
 	${PRJ_DIR}/util/topgen.py -t ${PRJ_DIR}/hw/$($@_TOP)/doc/$($@_TOP).hjson \
-		-r -o ${PRJ_DIR}/hw/$($@_TOP)/dv/env/
+		-r -o ${PRJ_DIR}/hw/$($@_TOP)/dv/env/ ${toolflags}
 
 .PHONY: all $(ips_reg) $(tops_gen)
diff --git a/hw/top_earlgrey/doc/top_earlgrey.gen.hjson b/hw/top_earlgrey/doc/top_earlgrey.gen.hjson
index b31b81c..37dd6af 100644
--- a/hw/top_earlgrey/doc/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/doc/top_earlgrey.gen.hjson
@@ -16,6 +16,25 @@
       freq: "100000000"
     }
   ]
+  resets:
+  [
+    {
+      name: lc
+      type: root
+      clk: main
+    }
+    {
+      name: sys
+      type: root
+      clk: main
+    }
+    {
+      name: spi_device
+      type: leaf
+      root: sys
+      clk: main
+    }
+  ]
   num_cores: "1"
   module:
   [
@@ -23,6 +42,10 @@
       name: uart
       type: uart
       clock: main
+      reset_connections:
+      {
+        rst_ni: sys
+      }
       base_addr: 0x40000000
       size: 0x1000
       ip_clock: main
@@ -94,6 +117,10 @@
       name: gpio
       type: gpio
       clock: main
+      reset_connections:
+      {
+        rst_ni: sys
+      }
       base_addr: 0x40010000
       size: 0x1000
       ip_clock: main
@@ -123,6 +150,10 @@
       name: spi_device
       type: spi_device
       clock: main
+      reset_connections:
+      {
+        rst_ni: spi_device
+      }
       base_addr: 0x40020000
       size: 0x1000
       ip_clock: main
@@ -194,6 +225,10 @@
       name: flash_ctrl
       type: flash_ctrl
       clock: main
+      reset_connections:
+      {
+        rst_ni: lc
+      }
       base_addr: 0x40030000
       size: 0x1000
       ip_clock: main
@@ -241,6 +276,10 @@
       name: rv_timer
       type: rv_timer
       clock: main
+      reset_connections:
+      {
+        rst_ni: sys
+      }
       base_addr: 0x40080000
       size: 0x1000
       ip_clock: main
@@ -263,6 +302,10 @@
       name: hmac
       type: hmac
       clock: main
+      reset_connections:
+      {
+        rst_ni: sys
+      }
       base_addr: 0x40120000
       size: 0x1000
       ip_clock: main
@@ -290,6 +333,10 @@
       name: rv_plic
       type: rv_plic
       clock: main
+      reset_connections:
+      {
+        rst_ni: sys
+      }
       base_addr: 0x40090000
       generated: "true"
       parameter:
@@ -311,18 +358,30 @@
   [
     {
       name: rom
+      reset_connections:
+      {
+        rst_ni: sys
+      }
       type: rom
       base_addr: 0x00008000
       size: 0x2000
     }
     {
       name: ram_main
+      reset_connections:
+      {
+        rst_ni: sys
+      }
       type: ram_1p
       base_addr: 0x10000000
       size: 0x10000
     }
     {
       name: eflash
+      reset_connections:
+      {
+        rst_ni: lc
+      }
       type: eflash
       base_addr: 0x20000000
       size: 0x80000
@@ -333,6 +392,11 @@
     {
       name: main
       clock: main
+      reset: sys
+      reset_connections:
+      {
+        rst_main_ni: sys
+      }
       connections:
       {
         corei:
diff --git a/hw/top_earlgrey/doc/top_earlgrey.hjson b/hw/top_earlgrey/doc/top_earlgrey.hjson
index 9a56d44..281455b 100644
--- a/hw/top_earlgrey/doc/top_earlgrey.hjson
+++ b/hw/top_earlgrey/doc/top_earlgrey.hjson
@@ -12,6 +12,17 @@
     { name: "main", freq: "100000000" }
   ]
 
+  // Reset attributes
+  // name: name of reset. Real name is `name`_rst_n
+  // type: reset type, either root or leaf
+  // root: if reset type not root, the root reset it is related to
+  // clk:  related clock domain for synchronous release
+  resets: [
+    { name: "lc", type: "root", clk: "main"}
+    { name: "sys", type: "root", clk: "main"}
+    { name: "spi_device", type: "leaf", root: "sys", clk: "main"}
+  ]
+
   // Number of cores: used in rv_plic and timer
   num_cores: "1",
 
@@ -22,39 +33,50 @@
     { name: "uart",     // instance name
       type: "uart",     // Must be matched to the ip name in `ip.hson` (_reg, _cfg permitted)
                         // and `hw/ip/{type}`
+
       clock: "main",    // `ip.hjson` clock is internal name, here top determines
                         // actual clock (signal matched at the top)
+
+      // reset connections defines the port to top level reset connection
+      // the ip.hjson will declare the reset port names
+      reset_connections: {rst_ni: "sys"},
       base_addr: "0x40000000",
     },
     { name: "gpio",
       type: "gpio",
       clock: "main",
+      reset_connections: {rst_ni: "sys"},
       base_addr: "0x40010000",
     }
 
     { name: "spi_device",
       type: "spi_device",
       clock: "main",
+      reset_connections: {rst_ni: "spi_device"},
       base_addr: "0x40020000",
     },
     { name: "flash_ctrl",
       type: "flash_ctrl",
       clock: "main",
+      reset_connections: {rst_ni: "lc"},
       base_addr: "0x40030000",
     },
     { name: "rv_timer",
       type: "rv_timer",
       clock: "main",
+      reset_connections: {rst_ni: "sys"},
       base_addr: "0x40080000",
     },
     { name: "hmac",
       type: "hmac",
       clock: "main",
+      reset_connections: {rst_ni: "sys"},
       base_addr: "0x40120000",
     },
     { name: "rv_plic",
       type: "rv_plic",
       clock: "main",
+      reset_connections: {rst_ni: "sys"},
       base_addr: "0x40090000",
       generated: "true"         // Indicate this module is generated in the topgen
       parameter: {
@@ -68,9 +90,9 @@
   // Memories (ROM, RAM, eFlash) are defined at the top.
   // It utilizes the primitive cells but configurable
   memory: [
-    { name: "rom",      type: "rom",    base_addr: "0x00008000", size: "0x2000"  },
-    { name: "ram_main", type: "ram_1p", base_addr: "0x10000000", size: "0x10000" },
-    { name: "eflash",   type: "eflash", base_addr: "0x20000000", size: "0x80000" },
+    { name: "rom",      reset_connections: {rst_ni: "sys"}, type: "rom",    base_addr: "0x00008000", size: "0x2000"  },
+    { name: "ram_main", reset_connections: {rst_ni: "sys"}, type: "ram_1p", base_addr: "0x10000000", size: "0x10000" },
+    { name: "eflash",   reset_connections: {rst_ni: "lc"},  type: "eflash", base_addr: "0x20000000", size: "0x80000" },
   ],
 
   debug_mem_base_addr: "0x1A110000",
@@ -81,6 +103,8 @@
   xbar: [
     { name: "main",
       clock: "main",    // Main clock, used in sockets
+      reset: "sys",
+      reset_connections: {rst_main_ni: "sys"}
     },
   ],
 
diff --git a/hw/top_earlgrey/doc/top_earlgrey.tpl.sv b/hw/top_earlgrey/doc/top_earlgrey.tpl.sv
index d2bc994..8ce39f8 100644
--- a/hw/top_earlgrey/doc/top_earlgrey.tpl.sv
+++ b/hw/top_earlgrey/doc/top_earlgrey.tpl.sv
@@ -76,6 +76,12 @@
   tl_h2d_t tl_${m["name"]}_d_h2d;
   tl_d2h_t tl_${m["name"]}_d_d2h;
 % endfor
+
+  //reset wires declaration
+% for reset in top['resets']:
+  logic ${reset['name']}_rst_n;
+% endfor
+
 <%
   interrupt_num = sum([x["width"] if "width" in x else 1 for x in top["interrupt"]])
 %>\
@@ -96,12 +102,24 @@
   logic [${(interrupt_num).bit_length()-1}:0] irq_id[1];
   logic [0:0]   msip;
 
-  // Non-debug module reset == reset for everything except for the debug module
-  // and the logic required to access it.
-  logic ndmreset_n;
-  logic ndmreset_from_dm;
-  assign ndmreset_n = (scanmode_i) ? rst_ni : ~ndmreset_from_dm & rst_ni;
 
+  // Non-debug module reset == reset for everything except for the debug module
+  logic ndmreset_req;
+
+  // root resets
+  // TODO: lc_rst_n is not the true root reset.  It will be differentiated once the
+  //       the reset controller logic is present
+  assign lc_rst_n = rst_ni;
+  assign sys_rst_n = (scanmode_i) ? lc_rst_n : ~ndmreset_req & lc_rst_n;
+
+  //non-root reset assignments
+% for reset in top['resets']:
+  % if reset['type'] in ['leaf']:
+  assign ${reset['name']}_rst_n = ${reset['root']}_rst_n;
+  % endif
+% endfor
+
+  // debug request from rv_dm to core
   logic debug_req;
 
   // processor core
@@ -116,7 +134,7 @@
   ) core (
     // clock and reset
     .clk_i                (clk_i),
-    .rst_ni               (ndmreset_n),
+    .rst_ni               (sys_rst_n),
     .test_en_i            (1'b0),
     // static pinning
     .hart_id_i            (32'b0),
@@ -151,9 +169,9 @@
                                 // 1                required by standard
   ) u_dm_top (
     .clk_i         (clk_i),
-    .rst_ni        (rst_ni),
+    .rst_ni        (lc_rst_n),
     .testmode_i    (1'b0),
-    .ndmreset_o    (ndmreset_from_dm),
+    .ndmreset_o    (ndmreset_req),
     .dmactive_o    (),
     .debug_req_o   (debug_req),
     .unavailable_i (1'b0),
@@ -177,12 +195,16 @@
 
 ## Memory Instantiation
 % for m in top["memory"]:
+<%
+  resets = m['reset_connections']
+%>\
   % if m["type"] == "ram_1p":
 <%
      data_width = int(top["datawidth"])
      dw_byte = data_width // 8
      addr_width = ((int(m["size"], 0) // dw_byte) -1).bit_length()
      sram_depth = (int(m["size"], 0) // dw_byte)
+
 %>\
   // sram device
   logic        ${m["name"]}_req;
@@ -199,8 +221,9 @@
     .Outstanding(1)
   ) tl_adapter_${m["name"]} (
     .clk_i,
-    .rst_ni   (ndmreset_n),
-
+    % for key in resets:
+    .${key}   (${resets[key]}_rst_n),
+    % endfor
     .tl_i     (tl_${m["name"]}_d_h2d),
     .tl_o     (tl_${m["name"]}_d_d2h),
 
@@ -222,7 +245,9 @@
     .DataBitsPerMask(${int(data_width/4)})
   ) u_ram1p_${m["name"]} (
     .clk_i,
-    .rst_ni   (ndmreset_n),
+    % for key in resets:
+    .${key}   (${resets[key]}_rst_n),
+    % endfor
 
     .req_i    (${m["name"]}_req),
     .write_i  (${m["name"]}_we),
@@ -252,7 +277,9 @@
     .ErrOnWrite(1)
   ) tl_adapter_${m["name"]} (
     .clk_i,
-    .rst_ni   (ndmreset_n),
+    % for key in resets:
+    .${key}   (${resets[key]}_rst_n),
+    % endfor
 
     .tl_i     (tl_${m["name"]}_d_h2d),
     .tl_o     (tl_${m["name"]}_d_d2h),
@@ -274,7 +301,9 @@
     .Depth(${rom_depth})
   ) u_rom_${m["name"]} (
     .clk_i,
-    .rst_ni   (ndmreset_n),
+    % for key in resets:
+    .${key}   (${resets[key]}_rst_n),
+    % endfor
     .cs_i     (${m["name"]}_req),
     .addr_i   (${m["name"]}_addr),
     .dout_o   (${m["name"]}_rdata),
@@ -302,7 +331,9 @@
     .ErrOnWrite(1)
   ) tl_adapter_${m["name"]} (
     .clk_i,
-    .rst_ni     (ndmreset_n),
+    % for key in resets:
+    .${key}   (${resets[key]}_rst_n),
+    % endfor
 
     .tl_i       (tl_${m["name"]}_d_h2d),
     .tl_o       (tl_${m["name"]}_d_d2h),
@@ -325,7 +356,9 @@
     .DataWidth(${data_width})
   ) u_flash_${m["name"]} (
     .clk_i,
-    .rst_ni,
+    % for key in resets:
+    .${key}   (${resets[key]}_rst_n),
+    % endfor
     .host_req_i      (flash_host_req),
     .host_addr_i     (flash_host_addr),
     .host_req_rdy_o  (flash_host_req_rdy),
@@ -339,9 +372,12 @@
     // flash memory is embedded within controller
   % endif
 % endfor
-
 ## Peripheral Instantiation
+
 % for m in top["module"]:
+<%
+
+%>\
   % if "parameter" in m:
   ${m["type"]} #(
     % for k, v in m["parameter"].items():
@@ -389,11 +425,18 @@
       .irq_id_o   (irq_id),
       .msip_o     (msip),
     % endif
+
     % if m["scan"] == "true":
       .scanmode_i   (scanmode_i),
     % endif
-      .clk_i(${"clk_i" if m["clock"] == "main" else "clk_"+ m["clock"] + "_i"}),
-      .rst_ni(${"ndmreset_n" if m["clock"] == "main" else "rst_" + m["clock"] + "_ni"})
+      .clk_i (${"clk_i" if m["clock"] == "main" else "clk_"+ m["clock"] + "_i"}),
+    % for k, v in m["reset_connections"].items():
+        % if loop.last:
+      .${k} (${v}_rst_n)
+        % else:
+      .${k} (${v}_rst_n),
+        % endif
+    % endfor
   );
 
 % endfor
@@ -410,10 +453,8 @@
 
   // TL-UL Crossbar
   logic clk_main;
-  logic ndmreset_sync_main_n;   // ndmreset synchronized to clk_main
-
   assign clk_main = clk_i;
-  assign ndmreset_sync_main_n = ndmreset_n;
+
 
 % for xbar in top["xbar"]:
 <%
@@ -421,11 +462,11 @@
 %>\
   xbar_${xbar["name"]} u_xbar_${xbar["name"]} (
   % for clock in xbar["clocks"]:
-    ## TODO: How we can handle the reset?
     .clk_${clock}_i  (clk_${clock}),
-    .rst_${clock}_ni (ndmreset_sync_${clock}_n),
   % endfor
-
+  % for k, v in xbar["reset_connections"].items():
+    .${k} (${v}_rst_n),
+  % endfor
   % for node in xbar["nodes"]:
     % if node["type"] == "device":
     .tl_${(node["name"]+"_o").ljust(name_len+2)} (tl_${node["name"]}_d_h2d),
diff --git a/hw/top_earlgrey/doc/xbar_main.hjson b/hw/top_earlgrey/doc/xbar_main.hjson
index 6694c7c..2c49d87 100644
--- a/hw/top_earlgrey/doc/xbar_main.hjson
+++ b/hw/top_earlgrey/doc/xbar_main.hjson
@@ -1,6 +1,7 @@
 { name: "main",
   type: "xbar",
   clock: "main", // Main clock, used in sockets
+  reset_primary: "rst_main_ni", // Main reset, used in sockets
   nodes: [
     { name:  "corei",
       type:  "host",
diff --git a/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson b/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson
index ee7e552..c246a2b 100644
--- a/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson
+++ b/hw/top_earlgrey/ip/xbar/doc/xbar_main.gen.hjson
@@ -9,6 +9,11 @@
 {
   name: main
   clock: main
+  reset: sys
+  reset_connections:
+  {
+    rst_main_ni: sys
+  }
   connections:
   {
     corei:
diff --git a/hw/top_earlgrey/rtl/top_earlgrey.sv b/hw/top_earlgrey/rtl/top_earlgrey.sv
index d18e26f..5e46916 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey.sv
@@ -76,6 +76,12 @@
   tl_d2h_t tl_ram_main_d_d2h;
   tl_h2d_t tl_eflash_d_h2d;
   tl_d2h_t tl_eflash_d_d2h;
+
+  //reset wires declaration
+  logic lc_rst_n;
+  logic sys_rst_n;
+  logic spi_device_rst_n;
+
   logic [53:0]  intr_vector;
   // Interrupt source list
   logic intr_uart_tx_watermark;
@@ -108,12 +114,20 @@
   logic [5:0] irq_id[1];
   logic [0:0]   msip;
 
-  // Non-debug module reset == reset for everything except for the debug module
-  // and the logic required to access it.
-  logic ndmreset_n;
-  logic ndmreset_from_dm;
-  assign ndmreset_n = (scanmode_i) ? rst_ni : ~ndmreset_from_dm & rst_ni;
 
+  // Non-debug module reset == reset for everything except for the debug module
+  logic ndmreset_req;
+
+  // root resets
+  // TODO: lc_rst_n is not the true root reset.  It will be differentiated once the
+  //       the reset controller logic is present
+  assign lc_rst_n = rst_ni;
+  assign sys_rst_n = (scanmode_i) ? lc_rst_n : ~ndmreset_req & lc_rst_n;
+
+  //non-root reset assignments
+  assign spi_device_rst_n = sys_rst_n;
+
+  // debug request from rv_dm to core
   logic debug_req;
 
   // processor core
@@ -128,7 +142,7 @@
   ) core (
     // clock and reset
     .clk_i                (clk_i),
-    .rst_ni               (ndmreset_n),
+    .rst_ni               (sys_rst_n),
     .test_en_i            (1'b0),
     // static pinning
     .hart_id_i            (32'b0),
@@ -163,9 +177,9 @@
                                 // 1                required by standard
   ) u_dm_top (
     .clk_i         (clk_i),
-    .rst_ni        (rst_ni),
+    .rst_ni        (lc_rst_n),
     .testmode_i    (1'b0),
-    .ndmreset_o    (ndmreset_from_dm),
+    .ndmreset_o    (ndmreset_req),
     .dmactive_o    (),
     .debug_req_o   (debug_req),
     .unavailable_i (1'b0),
@@ -200,7 +214,7 @@
     .ErrOnWrite(1)
   ) tl_adapter_rom (
     .clk_i,
-    .rst_ni   (ndmreset_n),
+    .rst_ni   (sys_rst_n),
 
     .tl_i     (tl_rom_d_h2d),
     .tl_o     (tl_rom_d_d2h),
@@ -221,7 +235,7 @@
     .Depth(2048)
   ) u_rom_rom (
     .clk_i,
-    .rst_ni   (ndmreset_n),
+    .rst_ni   (sys_rst_n),
     .cs_i     (rom_req),
     .addr_i   (rom_addr),
     .dout_o   (rom_rdata),
@@ -243,8 +257,7 @@
     .Outstanding(1)
   ) tl_adapter_ram_main (
     .clk_i,
-    .rst_ni   (ndmreset_n),
-
+    .rst_ni   (sys_rst_n),
     .tl_i     (tl_ram_main_d_h2d),
     .tl_o     (tl_ram_main_d_d2h),
 
@@ -265,7 +278,7 @@
     .DataBitsPerMask(8)
   ) u_ram1p_ram_main (
     .clk_i,
-    .rst_ni   (ndmreset_n),
+    .rst_ni   (sys_rst_n),
 
     .req_i    (ram_main_req),
     .write_i  (ram_main_we),
@@ -295,7 +308,7 @@
     .ErrOnWrite(1)
   ) tl_adapter_eflash (
     .clk_i,
-    .rst_ni     (ndmreset_n),
+    .rst_ni   (lc_rst_n),
 
     .tl_i       (tl_eflash_d_h2d),
     .tl_o       (tl_eflash_d_d2h),
@@ -318,7 +331,7 @@
     .DataWidth(32)
   ) u_flash_eflash (
     .clk_i,
-    .rst_ni,
+    .rst_ni   (lc_rst_n),
     .host_req_i      (flash_host_req),
     .host_addr_i     (flash_host_addr),
     .host_req_rdy_o  (flash_host_req_rdy),
@@ -343,8 +356,9 @@
       .intr_rx_break_err_o (intr_uart_rx_break_err),
       .intr_rx_timeout_o (intr_uart_rx_timeout),
       .intr_rx_parity_err_o (intr_uart_rx_parity_err),
-      .clk_i(clk_i),
-      .rst_ni(ndmreset_n)
+
+      .clk_i (clk_i),
+      .rst_ni (sys_rst_n)
   );
 
   gpio gpio (
@@ -354,8 +368,9 @@
       .cio_gpio_o    (cio_gpio_gpio_d2p_o),
       .cio_gpio_en_o (cio_gpio_gpio_en_d2p_o),
       .intr_gpio_o (intr_gpio_gpio),
-      .clk_i(clk_i),
-      .rst_ni(ndmreset_n)
+
+      .clk_i (clk_i),
+      .rst_ni (sys_rst_n)
   );
 
   spi_device spi_device (
@@ -372,9 +387,10 @@
       .intr_rxerr_o (intr_spi_device_rxerr),
       .intr_rxoverflow_o (intr_spi_device_rxoverflow),
       .intr_txunderflow_o (intr_spi_device_txunderflow),
+
       .scanmode_i   (scanmode_i),
-      .clk_i(clk_i),
-      .rst_ni(ndmreset_n)
+      .clk_i (clk_i),
+      .rst_ni (spi_device_rst_n)
   );
 
   flash_ctrl flash_ctrl (
@@ -388,16 +404,18 @@
       .intr_op_error_o (intr_flash_ctrl_op_error),
       .flash_o(flash_c2m),
       .flash_i(flash_m2c),
-      .clk_i(clk_i),
-      .rst_ni(ndmreset_n)
+
+      .clk_i (clk_i),
+      .rst_ni (lc_rst_n)
   );
 
   rv_timer rv_timer (
       .tl_i (tl_rv_timer_d_h2d),
       .tl_o (tl_rv_timer_d_d2h),
       .intr_timer_expired_0_0_o (intr_rv_timer_timer_expired_0_0),
-      .clk_i(clk_i),
-      .rst_ni(ndmreset_n)
+
+      .clk_i (clk_i),
+      .rst_ni (sys_rst_n)
   );
 
   hmac hmac (
@@ -405,8 +423,9 @@
       .tl_o (tl_hmac_d_d2h),
       .intr_hmac_done_o (intr_hmac_hmac_done),
       .intr_fifo_full_o (intr_hmac_fifo_full),
-      .clk_i(clk_i),
-      .rst_ni(ndmreset_n)
+
+      .clk_i (clk_i),
+      .rst_ni (sys_rst_n)
   );
 
   rv_plic #(
@@ -418,8 +437,9 @@
       .irq_o      (irq_plic),
       .irq_id_o   (irq_id),
       .msip_o     (msip),
-      .clk_i(clk_i),
-      .rst_ni(ndmreset_n)
+
+      .clk_i (clk_i),
+      .rst_ni (sys_rst_n)
   );
 
   // interrupt assignments
@@ -451,15 +471,12 @@
 
   // TL-UL Crossbar
   logic clk_main;
-  logic ndmreset_sync_main_n;   // ndmreset synchronized to clk_main
-
   assign clk_main = clk_i;
-  assign ndmreset_sync_main_n = ndmreset_n;
+
 
   xbar_main u_xbar_main (
     .clk_main_i  (clk_main),
-    .rst_main_ni (ndmreset_sync_main_n),
-
+    .rst_main_ni (sys_rst_n),
     .tl_corei_i      (tl_corei_h_h2d),
     .tl_corei_o      (tl_corei_h_d2h),
     .tl_cored_i      (tl_cored_h_h2d),
diff --git a/util/tlgen/elaborate.py b/util/tlgen/elaborate.py
index 55ab994..31e0f2d 100644
--- a/util/tlgen/elaborate.py
+++ b/util/tlgen/elaborate.py
@@ -29,7 +29,7 @@
     ## Build address map
     ## Each socket_1n should have address map
 
-    ## Gather clocks
+    ## Gather clocks and resets
     xbar.clocks = {xbar.clock
                    } | {clk
                         for node in xbar.nodes for clk in node.clocks}
diff --git a/util/tlgen/item.py b/util/tlgen/item.py
index b26b54e..6c40360 100644
--- a/util/tlgen/item.py
+++ b/util/tlgen/item.py
@@ -44,6 +44,7 @@
     clocks = []  # Clocks  # Clock domain of the node
     # e.g. async_fifo in : clk_core , out : clk_main
 
+
     # If NodeType is Socket out from 1:N then address steering is used
     # But this value is also propagated up to a Host from multiple Devices
     # Device Node should have address_from, address_to
diff --git a/util/tlgen/xbar.py b/util/tlgen/xbar.py
index 04dc39f..8dfae7a 100644
--- a/util/tlgen/xbar.py
+++ b/util/tlgen/xbar.py
@@ -20,6 +20,7 @@
     clock = ""  # str  # Main clock remove 'clk_' prefix
     name = ""  # str  # e.g. "main" --> main_xbar
     clocks = []  # Clocks
+
     # prefix is useful if SoC has more than one Xbar
 
     # variables after elaboration. Shouldn't be touched by outside
diff --git a/util/topgen.py b/util/topgen.py
index 0431c66..388c2b0 100755
--- a/util/topgen.py
+++ b/util/topgen.py
@@ -58,7 +58,7 @@
         if not tlgen.elaborate(xbar):
             log.error("Elaboration failed." + repr(xbar))
 
-        # Add clocks to the top configuration
+        # Add clocks/resets to the top configuration
         obj["clocks"] = xbar.clocks
         try:
             out_rtl, out_pkg, out_bind = tlgen.generate(xbar)
@@ -347,7 +347,7 @@
                  (", ".join([x["name"] for x in xbar_objs])))
 
         # TODO: Add validate
-        topcfg, error = validate_top(topcfg)
+        topcfg, error = validate_top(topcfg, ip_objs, xbar_objs)
         if error != 0:
             raise SystemExit("Error occured while validating top.hjson")
 
diff --git a/util/topgen/validate.py b/util/topgen/validate.py
index 4f45aba..3f1e1a4 100644
--- a/util/topgen/validate.py
+++ b/util/topgen/validate.py
@@ -1,7 +1,6 @@
 # Copyright lowRISC contributors.
 # Licensed under the Apache License, Version 2.0, see LICENSE for details.
 # SPDX-License-Identifier: Apache-2.0
-
 import logging as log
 
 from reggen.validate import val_types, check_keys
@@ -84,8 +83,101 @@
 def check_pinmux(top, prefix):
     return 0
 
+def check_resets(top, ipobjs, xbarobjs):
+    # all defined reset nets
+    reset_nets = [reset['name'] for reset in top['resets']]
+    error = 0
 
-def validate_top(top):
+    # Check reset port connection for all IPs
+    for ipcfg in top['module']:
+        log.info("Checking resets for %s" % ipcfg['name'].lower())
+        ipdef = [ip for ip in ipobjs if ipcfg['type'] == ip['name'].lower()]
+        error += check_rst_def(ipdef, ipcfg['type'])
+        error += validate_reset(ipcfg, ipdef[0], reset_nets)
+
+        if error:
+            log.error("module reset checking failed")
+            break
+
+    # Check reset port connection for all xbars
+    for xbarcfg in top['xbar']:
+        log.info("Checking resets for %s" % xbarcfg['name'].lower())
+        xbardef = [
+            xbar for xbar in xbarobjs
+            if xbarcfg['name'] == xbar['name'].lower()
+        ]
+        error += check_rst_def(xbardef, xbarcfg['name'])
+        error += validate_reset(xbarcfg, xbardef[0], reset_nets, "xbar")
+
+        if error:
+            log.error("xbar reset checking failed")
+            break
+
+    return error
+
+def check_rst_def(inst_def, name):
+    error = 0
+    if not inst_def:
+        log.error("Could not find %s.hjson for" % name)
+        error += 1
+
+    if len(inst_def) > 1:
+        log.error("Duplicate %s.hjson" % name)
+        error += 1
+
+    return error
+
+# Checks the following
+# For each defined reset connection in top*.hjson, there exists a defined port at the destination
+# and defined reset net
+# There are the same number of defined connections as there are ports
+def validate_reset(top, inst, reset_nets, prefix=""):
+    # Gather inst port list
+    error = 0
+    inst_port_list = []
+    if 'reset_primary' not in inst.keys():
+        log.info("%s %s does not have a reset_primary defined, default used" %
+                 (prefix, inst['name']))
+        inst_port_list.append("rst_ni")
+    else:
+        inst_port_list.append(inst['reset_primary'])
+
+    if 'other_reset_list' in inst.keys():
+        inst_port_list.extend(inst['other_reset_list'])
+    log.info("%s %s resets are %s" %
+             (prefix, inst['name'].lower(), inst_port_list))
+
+    if len(top['reset_connections'].keys()) != len(inst_port_list):
+        error += 1
+        log.error("%s %s mismatched number of ports and nets" %
+                  (prefix, inst['name']))
+
+    missing_port = [
+        port for port in top['reset_connections'].keys()
+        if port not in inst_port_list
+    ]
+
+    if missing_port:
+        error += 1
+        log.error("%s %s Following reset ports do not exist:" %
+                  (prefix, inst['name']))
+        [log.error("%s" % port) for port in missing_port]
+
+    missing_net = [
+        net for port, net in top['reset_connections'].items()
+        if net not in reset_nets
+    ]
+
+    if missing_net:
+        error += 1
+        log.error("%s %s Following reset nets do not exist:" %
+                  (prefix, inst['name']))
+        [log.error("%s" % net) for net in missing_net]
+
+    return error
+
+
+def validate_top(top, ipobjs, xbarobjs):
     # return as it is for now
     error = check_keys(top, top_required, top_optional, top_added, "top")
 
@@ -95,6 +187,9 @@
 
     component = top['name']
 
+    ## Reset check
+    error += check_resets(top, ipobjs, xbarobjs)
+
     ## MODULE check
 
     ## MEMORY check