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
|
#!/usr/bin/env python3
"""
Make the correct ROM using Amaranth into Verilog.
"""
import sys
import argparse
from amaranth import *
from amaranth.back import verilog
DEPTH = 4096
DATA_WIDTH = 14
ADDR_WIDTH = 13
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])
for i in range(0, len(data) - 1, 2):
word_addr = (address + i) // 2
if 0 <= word_addr < DEPTH:
words[word_addr] = (data[i] | (data[i+1] << 8)) & ((1 << DATA_WIDTH) - 1)
return words
def make_rom_module(words):
m = Module()
addr = Signal(ADDR_WIDTH)
data = Signal(DATA_WIDTH)
mem = Memory(width=DATA_WIDTH, depth=DEPTH, init=words)
rd = mem.read_port(transparent=False)
m.submodules += rd
m.d.comb += [
rd.addr.eq(addr),
data.eq(rd.data)
]
return m, addr, data
def render_verilog(words, module_name="prog_rom"):
m, addr, data = make_rom_module(words)
v = verilog.convert(m, ports=[addr, data], name=module_name)
return v.replace("(* top = 1 *)\n", "(* top = 0 *)\n")
class ComponentWrapper(Elaboratable):
def __init__(self, module_obj, ports, name="prog_rom"):
self._module = module_obj
self._ports = ports
self._name = name
def elaborate(self, platform=None):
return self._module
def name(self):
return self._name
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('hexfile')
parser.add_argument('--module-name', default='prog_rom')
args = parser.parse_args()
words = parse_ihex(args.hexfile)
v = render_verilog(words, module_name=args.module_name)
sys.stdout.write(v)
|