blob: 3ddc5dc92a342a40127ff39f8147667be889f48d (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#!/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 = 4096
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(' clk : in std_logic;')
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(' signal 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(' attribute ram_style : string;')
lines.append(' attribute ram_style of rom : signal is "block";')
lines.append('begin')
lines.append(' process(clk)')
lines.append(' begin')
lines.append(' if rising_edge(clk) then')
lines.append(' data <= rom(to_integer(unsigned(addr(11 downto 0))));')
lines.append(' end if;')
lines.append(' end process;')
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='')
|