summaryrefslogtreecommitdiffstats
path: root/hex2rom.py
diff options
context:
space:
mode:
Diffstat (limited to 'hex2rom.py')
-rw-r--r--hex2rom.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/hex2rom.py b/hex2rom.py
new file mode 100644
index 0000000..52610c7
--- /dev/null
+++ b/hex2rom.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+"""Convert a SDCC/gputils Intel HEX file to a prog_rom.vhd constant.
+
+Usage:
+ python3 hex2rom.py program.hex > PIC/prog_rom.vhd
+ python3 hex2rom.py blink.hex > PIC/prog_rom.vhd
+"""
+
+import sys
+import argparse
+
+DEPTH = 1024
+INST_BITS = 14
+
+def parse_ihex(path):
+ words = [0] * DEPTH
+ with open(path) as f:
+ for line in f:
+ line = line.strip()
+ if not line.startswith(':'):
+ continue
+ byte_count = int(line[1:3], 16)
+ address = int(line[3:7], 16)
+ record_type = int(line[7:9], 16)
+ if record_type != 0:
+ continue
+ data = bytes.fromhex(line[9:9 + byte_count * 2])
+ # PIC16: two bytes per 14-bit word, little-endian, address in bytes
+ for i in range(0, len(data) - 1, 2):
+ word_addr = (address + i) // 2
+ if word_addr < DEPTH:
+ words[word_addr] = (data[i] | (data[i+1] << 8)) & 0x3FFF
+ return words
+
+def render(words):
+ lines = []
+ lines.append('library ieee;')
+ lines.append('use ieee.std_logic_1164.all;')
+ lines.append('use ieee.numeric_std.all;')
+ lines.append('')
+ lines.append('entity prog_rom is')
+ lines.append(' generic (')
+ lines.append(f' DEPTH : positive := {DEPTH}')
+ lines.append(' );')
+ lines.append(' port (')
+ lines.append(' addr : in std_logic_vector(12 downto 0);')
+ lines.append(' data : out std_logic_vector(13 downto 0)')
+ lines.append(' );')
+ lines.append('end entity prog_rom;')
+ lines.append('')
+ lines.append('architecture rtl of prog_rom is')
+ lines.append(f' type rom_t is array (0 to {DEPTH} - 1) of std_logic_vector(13 downto 0);')
+ lines.append(' constant rom : rom_t := (')
+ for i, w in enumerate(words):
+ bits = format(w, f'014b')
+ sep = ',' if i < DEPTH - 1 else ' '
+ lines.append(f' {i:4d} => "{bits}"{sep}')
+ lines.append(' );')
+ lines.append('begin')
+ lines.append(' data <= rom(to_integer(unsigned(addr(9 downto 0))));')
+ lines.append('end architecture rtl;')
+ return '\n'.join(lines) + '\n'
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('hexfile')
+ args = parser.parse_args()
+ words = parse_ihex(args.hexfile)
+ print(render(words), end='')