Verilog测试bench读取文件字符串转十六进制数值赋值问题
问题根因
你当前的错误本质是:$fgets读取到的A变量存储的是每行文本的ASCII编码值,直接对A做位选得到的是字符对应的ASCII码拼接结果,而非你需要的十六进制数值,同时你手动计算的位选区间偏移也很容易出错,最终导致赋值结果不符合预期。
最优解决方案:使用$fscanf系统函数读取
Verilog内置的$fscanf函数可以直接按照指定格式解析文本,自动将文本中的十六进制字符串转换为对应数值,不需要手动处理字符串位选,改造成本极低。
方案1:简化文本格式(推荐)
先把test.txt里的无用符号删除,去掉所有|和128'h/64'h前缀,每行保留三个用空格分隔的十六进制数即可,示例如下:
00000000000000000000000000000000 0000000000000008 2FFCE6557D7DC86C 00000000000000000000000000000000 0000000000000008 2FFCE6557D7DC86C 00000000000000000000000000000000 0000000000000008 2FFCE6557D7DC86C
然后修改测试bench的读取逻辑:
reg [63:0] ctxt; reg [127:0] key; reg [63:0] ptxt_expected; // 存储明文期望值,用于和设计输出ptxt比对 wire [63:0] ptxt; integer outfile0; integer scan_ret; // 存储读取返回值,用于校验读取是否成功 begin: READ_FILE outfile0 = $fopen("test.txt", "r"); // 加文件打开失败校验,避免路径错误导致的异常 if(outfile0 == 0) begin $display("Error: 测试文件打开失败,请检查路径"); $finish; end while (!$feof(outfile0)) begin @(posedge clk); // 按十六进制格式依次读取key、ctxt、明文期望值 scan_ret = $fscanf(outfile0, "%h %h %h", key, ctxt, ptxt_expected); #10; // 此处可添加结果比对逻辑,例如: // if(ptxt !== ptxt_expected) $display("Error: 输出不匹配,预期值%h,实际值%h", ptxt_expected, ptxt); end $fclose(outfile0); end
方案2:保留原始文本格式
如果不想修改原有的test.txt格式,只需要调整$fscanf的格式字符串,匹配原文本的固定结构即可,不需要修改其他逻辑:
scan_ret = $fscanf(outfile0, "| 128'h%h | 64'h%h | 64'h%h |", key, ctxt, ptxt_expected);
格式字符串会自动跳过固定的|、空格和前缀标识,直接读取后面的十六进制数值。
注意事项
- 不需要再定义大位宽的字符串变量
A,也不需要手动计算位选区间,避免人为偏移计算错误。 - 可以通过判断
scan_ret == 3来确认当前行读取成功,过滤空行或者格式错误的行,避免仿真异常。
内容的提问来源于stack exchange,提问作者Flank
相关产品推荐
相关产品推荐

