diff options
Diffstat (limited to 'hex2rom.py')
| -rw-r--r-- | hex2rom.py | 69 |
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='') |
