- rtl/:12 个可综合的处理器源文件(顶层 cpu21_riscv_redirect_int_bpb.v,其余为各功能单元)。 - board/:板级顶层 cpu21_board_top.v、引脚约束 cpu21_board_top.xdc、片内 ROM 初始化 cpu21_board_rom.vh 与短延时版本 cpu21_board_rom_fast.vh。 - testbench/:保留三个测试平台;ROM 镜像统一放到 testbench/rom/,测试程序源码与期望值 仍在 testbench/programs/(其中的 .hex 是 RARS 原始输出,与 rom/ 里改过显示方式的版本 内容不同,两者都保留)。 - 同步更新:两个测试平台的 ROM 探测路径改为 testbench/rom/(并在头注释里补充说明: PowerShell 会把 -generic_top/--testplusarg 参数里的 "=" 拆开、Verilog 字符串中的 路径要用正斜杠);tools/hex2vh.py 的用法示例指向 board/cpu21_board_top.v; 说明文档新增“目录结构”一节并同步所有路径引用;.gitignore 补充 .Xil/。 - 清理:删除 *.hex.lst 中间文件与空的 .Xil/ 目录。 - 验证:isa_test 24/24、lui_test 4/4、mmio_test 5/5 三项回归通过;两个基线(5560 / 6003 周期)与整理前一致;板级仿真(默认 ROM 首次写入 LED=0001、快速 ROM 跑马灯循环)正常; Vivado 工程源文件路径同步到 rtl/ 与 board/ 后综合通过(LUT 5276、23 个引脚,与整理前 完全一致),因此已有 bit 文件仍然有效。
58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
#!/usr/bin/env python3
|
||
"""把 $readmemh 格式的 hex 文件转换成 Verilog include 文件,供综合时初始化 ROM。
|
||
|
||
用法: python tools/hex2vh.py <input.hex> <output.vh> [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()
|