#!/usr/bin/env python3 """把 $readmemh 格式的 hex 文件转换成 Verilog include 文件,供综合时初始化 ROM。 用法: python tools/hex2vh.py [ROM_WORDS] 输出内容形如(每行一条赋值,未用到的地址填 NOP 0x00000013): rom[0] = 32'h00001037; rom[1] = 32'h00100093; 配套 RTL 用法(见 board/cpu21_board_top.v,两者同目录,所以 include 能直接解析): initial begin for (i = 0; i < ROM_WORDS; i = i + 1) rom[i] = 32'h0000_0013; // NOP 填充 `include "cpu21_board_rom.vh" end 这样 ROM 内容直接跟着 RTL 走,不依赖综合时的当前工作目录, 避免了 $readmemh 相对路径在 Vivado 综合流程里找不到文件(且只报 warning)的坑。 """ import sys NOP = 0x00000013 def main(): src, dst = sys.argv[1], sys.argv[2] words_total = int(sys.argv[3]) if len(sys.argv) > 3 else 1024 words = [] with open(src, encoding="ascii") as f: for line in f: line = line.split("//")[0].strip() if not line: continue words.append(int(line, 16)) if len(words) > words_total: raise SystemExit( "程序 %d 个字,超过 ROM 容量 %d 个字" % (len(words), words_total) ) with open(dst, "w", encoding="utf-8") as f: f.write(" // generated by tools/hex2vh.py - do not edit by hand\n") f.write( " // source: %s (%d words, remaining entries filled with NOP)\n" % (src, len(words)) ) for addr in range(words_total): w = words[addr] if addr < len(words) else NOP f.write(" rom[%d] = 32'h%08X;\n" % (addr, w)) print("已生成 %s(%d 个字,源程序 %d 个字)" % (dst, words_total, len(words))) main()