summaryrefslogtreecommitdiffstats
path: root/hdl/rom.py
blob: 866de67dbe2a42a855b1a7f21731a550ec256ab4 (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
#!/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 = 8192
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)