亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

用 VHDL TEXTIO 库从文本文件初始化 FPGA 块 RAM

从 ASCII 文件读取二进制或十六进制字面量预填充块 RAM 是最高效方法。此技术也可创建 ROM,因为 FPGA ROM 只是只读的 RAM。

下文示例在 VHDL 文件声明区声明以下常量和 RAM 类型:

constant ram_depth : natural := 256; constant ram_width : natural := 32; type ram_type is array (0 to ram_depth - 1) of std_logic_vector(ram_width - 1 downto 0);

本文属 TEXTIO 系列。测试平台用 TEXTIO 读激励文件 | 用 TEXTIO 读 BMP 位图

用 TEXTIO 读行与数据

标准 std 库的 TEXTIO 包提供文件 I/O 所需子程序。自动可用,只需导入:

use std.textio.all;

RAM 数据存 ASCII 文件,每行代表一个存储字。READLINE 过程读单行到 LINE 对象。原型:

procedure READLINE (file F: TEXT; L: inout LINE); type LINE is access STRING; -- pointer to a dynamically allocated string

VHDL‑2008 引入 OREAD、HREAD、BREAD 从 LINE 对象提取八进制、十六进制、二进制值。为简洁聚焦十六进制和二进制读。相关声明:

procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];

旧版 VHDL (pre‑2008) 必须用标准 READ 过程,不直接支持十六进制。此时需自定义转换例程。

加载十六进制数据

十六进制方便,每对十六进制位直接映射一字节。样例 ram_content_hex.txt 含 256 行,每行 8 字符十六进制串,从 00000001 到 00000100:

1
2
…
255
256
00000001
00000002
…
000000FF
00000100

下面非纯函数读文件返回全初始化 ram_type 数组。适用 VHDL‑2008 及更新版:

impure function init_ram_hex return ram_type is file text_file : text open read_mode is "ram_content_hex.txt"; variable text_line : line; variable ram_content : ram_type; begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); hread(text_line, ram_content(i)); end loop; return ram_content; end function;

定义函数后,用初始内容实例化 RAM 信号:

signal ram_hex : ram_type := init_ram_hex;

旧版 VHDL:手动实现 HREAD

HREAD 不可用时(如 VHDL‑93 或 VHDL‑2002),可在初始化函数内嵌手动转换例程。下例演示此法:

impure function init_ram_hex return ram_type is file text_file : text open read_mode is "ram_content_hex.txt"; variable text_line : line; variable ram_content : ram_type; variable c : character; variable offset : integer; variable hex_val : std_logic_vector(3 downto 0); begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); offset := 0; while offset < ram_content(i)'high loop read(text_line, c); case c is when '0' => hex_val := "0000"; when '1' => hex_val := "0001"; when '2' => hex_val := "0010"; when '3' => hex_val := "0011"; when '4' => hex_val := "0100"; when '5' => hex_val := "0101"; when '6' => hex_val := "0110"; when '7' => hex_val := "0111"; when '8' => hex_val := "1000"; when '9' => hex_val := "1001"; when 'A' | 'a' => hex_val := "1010"; when 'B' | 'b' => hex_val := "1011"; when 'C' | 'c' => hex_val := "1100"; when 'D' | 'd' => hex_val := "1101"; when 'E' | 'e' => hex_val := "1110"; when 'F' | 'f' => hex_val := "1111"; when others => hex_val := "XXXX"; assert false report "Found non-hex character '" & c & "'"; end case; ram_content(i)(ram_content(i)'high - offset downto ram_content(i)'high - offset - 3) := hex_val; offset := offset + 4; end loop; end loop; return ram_content; end function;

虽可定义专用 HREAD 过程,但多数综合工具(如 Xilinx Vivado)不支持接受 LINE 参数的过程。下面错误说明此限制:

Vivado 报错:
[Synth 8-27] Procedure argument of type ‘line’ is not supported [init_ram_tb.vhd:15]

读取二进制数据

若 RAM 宽度非 8 倍数,二进制字面量可能更优。样例 ram_content_bin.txt 含 256 行,每行 32 位二进制串:

1
2
…
255
256
00000000000000000000000000000001
00000000000000000000000000000010
…
00000000000000000000000011111111
00000000000000000000000100000000

VHDL‑2008 可用 BREAD 过程直接读二进制值:

impure function init_ram_bin return ram_type is file text_file : text open read_mode is "ram_content_bin.txt"; variable text_line : line; variable ram_content : ram_type; begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); bread(text_line, ram_content(i)); end loop; return ram_content; end function;

实例化 RAM:

signal ram_bin : ram_type := init_ram_bin;

旧版 VHDL:用 READ 读二进制

VHDL‑2002 或 VHDL‑93 必须用 READ 过程。因其返回 bit 向量,结果经 To_StdLogicVector 转为 std_logic_vector:

impure function init_ram_bin return ram_type is file text_file : text open read_mode is "ram_content_bin.txt"; variable text_line : line; variable ram_content : ram_type; variable bv : bit_vector(ram_content(0)'range); begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); read(text_line, bv); ram_content(i) := To_StdLogicVector(bv); end loop; return ram_content; end function;

回溯现代 TEXTIO 特性

若不想改旧代码,可导入第三方 std_logic_1164_additions 包。该库将 HREAD 和 BREAD 回溯到旧 VHDL 版本,代价是额外依赖。

更多详细示例和延伸阅读,见本系列配套文章。

VHDL

  1. 千分尺详解:读数方法与精密测量应用指南
  2. 通过 OPC UA 客户端调用 PLC 功能块:实用指南
  3. 保护铝材防腐蚀:持久耐用的专家策略
  4. 金属元素与非金属元素:核心差异详解
  5. CNC 图纸识读精通:现代机工必备技能
  6. 构建您的第一个AWS CloudFormation模板——实操指南
  7. 云计算 vs 传统计算:实战对比与选择指南
  8. C 语言注释完全指南:编写清晰高效的代码备注
  9. 设计基于 FPGA 的 RC 舵机控制器:精准 PWM 实现
  10. 利用块 RAM 中正弦波实现 LED 呼吸效果
  11. Python 计算平均值:从循环到 NumPy 的四种实战方法
  12. Java BufferedReader 读取文件:实战指南与示例