2

我实现了一些 VHDL 代码以在编译时导出 FSM 状态编码,这些代码可由 Xilinx ChipScope 读回。此功能已使用 Xilinx ISE 14.7、iSim 14.7 和 Mentor Graphic 的 QuestaSim 10.2c 进行了测试。我的设计也可以与 Altera FPGA 的替代顶层进行综合,但 Quartus II 似乎在return line.all;.

Quartus II (14.0) 错误信息:

  • 错误 (10351):sata_PhysicalLayer.vhdl(504) 处的 VHDL 子程序主体错误:函数“dbg_GenerateEncodings”并不总是返回值
  • 错误 (10346):debug.vhdl(47) 处的 VHDL 错误:正式端口或参数“编码”必须具有实际值或默认值
  • 错误 (10657):sata_PhysicalLayer.vhdl(514) 处的 VHDL 子程序错误:未能详细调用子程序“dbg_ExportEncoding”

下面,我将描述我的代码。


VHDL 代码

该设计使用 3 个函数来导出 FSM 状态编码:

  1. 将当前本地 FSM 状态编码为二进制值 -> dbg_EncodeState
    (此函数的结果连接到 ILA 端口)
  2. 将本地 FSM 的所有状态转换为分号分隔的字符串 -> dbg_GenerateEncodings
  3. 格式化此字符串并将其元素写入令牌文件-> dbg_ExportEncoding
    (此函数位于包中)

FSM 声明:

TYPE T_STATE IS (
    ST_HOST_RESET,
    ST_HOST_SEND_COMRESET,
    ST_HOST_SEND_COMRESET_WAIT,
    [...]
    ST_HOST_SEND_ALIGN,
    ST_HOST_TIMEOUT,
    ST_HOST_LINK_OK
);

-- OOB-Statemachine
SIGNAL State                    : T_STATE       := ST_HOST_RESET;
SIGNAL NextState                : T_STATE;

局部函数 - 每个实体函数

function dbg_EncodeState(st : T_STATE) return STD_LOGIC_VECTOR is
begin
    return to_slv(T_STATE'pos(st), log2ceilnz(T_STATE'pos(T_STATE'high) + 1));
end function;

function dbg_GenerateEncodings return string is
  variable l : STD.TextIO.line;
begin
    for i in T_STATE loop
        STD.TextIO.write(l, str_replace(T_STATE'image(i), "st_host_", ""));
        STD.TextIO.write(l, ';');
    end loop;
    return  l.all;
end function;

全局函数 - 在 debug.pkg.vhdl 中定义:

impure function dbg_ExportEncoding(Name : STRING; encodings : string; tokenFileName : STRING) return BOOLEAN is
    file        tokenFile : TEXT open WRITE_MODE is tokenFileName;

    variable cnt, base : integer;
    variable l : line;
begin
    report "Exporting encoding of '" & Name & "' to '" & tokenFileName & "'..." severity note;
    report "dbg_ExportEncoding: '" & encodings & "'" severity note;

    -- write file header
    write(l, "# Encoding file for '" & Name & "'"); writeline(tokenFile, l);
    write(l, "#");                                  writeline(tokenFile, l);
    write(l, "# ChipScope Token File Version");     writeline(tokenFile, l);
    write(l, "@FILE_VERSION=1.0.0");                writeline(tokenFile, l);
    write(l, "#");                                  writeline(tokenFile, l);
    write(l, "# Default token value");              writeline(tokenFile, l);
    write(l, "@DEFAULT_TOKEN=");                    writeline(tokenFile, l);
    write(l, "#");                                  writeline(tokenFile, l);

    -- write state entires
    cnt  := 0;
    base := encodings'left;
    for i in encodings'range loop
        if encodings(i) = ';' then
            -- Leave the str_trim call in!
            -- Otherwise, the new parser of ISE 14.7 fails to slice properly.
            write(l, str_trim(encodings(base to i-1)));
            write(l, character'('='));
          write(l, raw_format_nat_hex(cnt));
            writeline(tokenFile, l);
            cnt  := cnt + 1;
            base := i+1;
        end if;
    end loop;

    file_close(tokenFile);
    return true;
end function;

代码的最后一部分是实体中的一个虚拟常量,它调用导出函数:

CONSTANT test : boolean := dbg_ExportEncoding("OOBControl (Host)", dbg_GenerateEncodings, MY_PROJECT_DIR & "CSP/FSM_OOB_Host.tok");

使用的辅助功能:

  • log2ceilnz(x) 计算以二进制编码 x 符号所需的位
  • to_slv 将所有内容转换为 std_logic_vector;在这种情况下,一个整数到 slv
  • str_replace 用字符串替换字符串
  • str_trim 返回从 str'low 到第一次出现 NUL 的字符串
  • raw_format_nat_hex 将自然格式化为十六进制字符串

附加说明:
所有 vhdl 文件都标记为 VHDL-2008。


我的问题:

  1. 有人在 Quartus 环境中使用过 line.all 吗?
  2. 有解决方法吗?
  3. 有没有更好的解决方案来实现导出任务而不使用恒定长度的字符串?

解决方法:

我将函数 dbg_GenerateEncodings 包装在生成语句中:

genXilinx : if (VENDOR = VENDOR_XILINX) generate
  function dbg_GenerateEncodings return string is
  [...]

  constant test : boolean := dbg_ExportEncoding("OOBControl (Host)", dbg_GenerateEncodings, MY_PROJECT_DIR & "CSP/FSM_OOB_Host.tok");
begin
end generate;

与 XST 相比,Quartus 不检查生成块内的函数。

4

1 回答 1

1

参见Quartus II VHDL Support,Section 14 Predefined language environment,表条目 14.3,Construct TEXTIO,最右边一列 VHDL 1993 Support:

支持的。文件 I/O 无法合成;因此,对 TEXTIO 函数的调用将被忽略。

如果您不能使用 TEXTIO 进行综合,您可以想象指向行缓冲区的指针也可能没有任何用处。

有一个关于如何从 FPGA 写入文件的问题。无需了解主机操作系统或指定物理接口。

您可以通过使用 translate off 和 translate on 指令来围绕不受支持的结构来合成设计的其余部分。请参阅VHDL 综合属性和指令

于 2014-11-20T22:55:34.777 回答