diff options
| author | Väinö Kauppila <vaino@vke.fi> | 2026-04-20 18:21:28 +0300 |
|---|---|---|
| committer | Väinö Kauppila <vaino@vke.fi> | 2026-04-20 18:21:28 +0300 |
| commit | 7af8820d2dbd441f95cb5c8bde74e4649878383c (patch) | |
| tree | 46775e7fc08137d8d40a69d70be4e2d76265cc66 /hdl/rom.py | |
| parent | bada76e705a4219fe2da27bb59c32dbdd0601514 (diff) | |
| download | vhdl_pic-7af8820d2dbd441f95cb5c8bde74e4649878383c.tar.gz vhdl_pic-7af8820d2dbd441f95cb5c8bde74e4649878383c.zip | |
prog rom generation using Amaranth
Diffstat (limited to 'hdl/rom.py')
| -rw-r--r-- | hdl/rom.py | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/hdl/rom.py b/hdl/rom.py new file mode 100644 index 0000000..d370e7d --- /dev/null +++ b/hdl/rom.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +""" +Convert an Intel HEX file to a Verilog ROM module using Amaranth. +Usage: + python3 hex2rom_amaranth.py program.hex > prog_rom.v +Produces a module 'prog_rom' with: + input clk, input [12:0] addr, output [13:0] data +Depth defaults to 4096 (8192/2). +""" +import sys +import argparse +from amaranth import * +from amaranth.back import verilog + +DEPTH = 8192 // 2 +DATA_WIDTH = 14 +ADDR_WIDTH = 13 # external addr width + +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() + + clk = Signal() + 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, clk, addr, data + +def render_verilog(words, module_name="prog_rom"): + m, clk, addr, data = make_rom_module(words) + v = verilog.convert(m, ports=[clk, 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) |
