[fpga] Update slice to work with 32kB ROM

The 32kB ROM configuration uses 4-bit RAM cells which were previously
not supported by the slice scripts. This commit adds the following
changes:

* Update the Vivado rom.mmi generation script to support 4bit wide
  address ranges.
* Update the gen_vivado_mem_image.py to support swapping of byte
  nibbles. This is needed in order to match the expected bit order in
  the updatemem command.

Signed-off-by: Miguel Osorio <miguelosorio@google.com>
diff --git a/hw/ip/rom_ctrl/util/gen_vivado_mem_image.py b/hw/ip/rom_ctrl/util/gen_vivado_mem_image.py
index b4b7a84..5e2e612 100755
--- a/hw/ip/rom_ctrl/util/gen_vivado_mem_image.py
+++ b/hw/ip/rom_ctrl/util/gen_vivado_mem_image.py
@@ -23,11 +23,14 @@
 from mem import MemFile
 
 
-def swap_bytes(width: int, orig: int) -> int:
+def swap_bytes(width: int, orig: int, swap_nibbles: bool) -> int:
     num_bytes = math.ceil(width / 8)
     swapped = 0
     for i in range(num_bytes):
-        swapped |= (((orig >> (i * 8)) & 0xFF) << ((num_bytes - i - 1) * 8))
+        byte_value = ((orig >> (i * 8)) & 0xFF)
+        if swap_nibbles:
+            byte_value = ((byte_value << 4) | (byte_value >> 4)) & 0xFF
+        swapped |= (byte_value << ((num_bytes - i - 1) * 8))
     return swapped
 
 
@@ -35,6 +38,7 @@
     parser = argparse.ArgumentParser()
     parser.add_argument('infile', type=argparse.FileType('rb'))
     parser.add_argument('outfile', type=argparse.FileType('w'))
+    parser.add_argument('--swap-nibbles', dest='swap_nibbles', action='store_true')
 
     args = parser.parse_args()
 
@@ -62,7 +66,7 @@
         # Generate the address.
         addr = idx * math.ceil(width / 8)
         # Convert endianness.
-        data = swap_bytes(width, word)
+        data = swap_bytes(width, word, args.swap_nibbles)
         # Write to file.
         toks = [f'@{addr:0{addr_chars}X}']
         toks.append(f'{data:0{word_chars}X}')
diff --git a/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl b/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl
index 7bef3fb..cef67b8 100644
--- a/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl
+++ b/hw/top_earlgrey/util/vivado_hook_write_bitstream_pre.tcl
@@ -59,9 +59,9 @@
   set slice_begin [get_property ram_slice_begin [get_cells $inst]]
   set slice_end [get_property ram_slice_end [get_cells $inst]]
   # The scrambled Boot ROM is actually 39 bits wide but the updatemem tool segfaults
-  # for slice sizes not divisible by 8.
-  if {[expr {($slice_end - $slice_begin + 1) < 8}]} {
-    set slice_end [expr {$slice_begin + 7}]
+  # for slice sizes not divisible by 4.
+  if {[expr {($slice_end - $slice_begin + 1) < 4}]} {
+    set slice_end [expr {$slice_begin + 3}]
   }
   set addr_begin [get_property ram_addr_begin [get_cells $inst]]
   set addr_end [get_property ram_addr_end [get_cells $inst]]
diff --git a/util/fpga/splice_rom.sh b/util/fpga/splice_rom.sh
index fd0d9de..60787e3 100755
--- a/util/fpga/splice_rom.sh
+++ b/util/fpga/splice_rom.sh
@@ -102,7 +102,10 @@
 FPGA_BIT_NAME=lowrisc_systems_chip_${TARGET_TOP}_${TARGET_BOARD}_0.1
 
 # Create the Vivado image for splicing.
-hw/ip/rom_ctrl/util/gen_vivado_mem_image.py "${TARGET}${TARGET_FILE_EXT}" "${TARGET}.updatemem.mem"
+hw/ip/rom_ctrl/util/gen_vivado_mem_image.py \
+  "${TARGET}${TARGET_FILE_EXT}" \
+  "${TARGET}.updatemem.mem" \
+  --swap-nibbles
 
 # Splice the ROM.
 # The --debug flag is undocumented and causes updatemem to print out the INIT_XX