【问题标题】:VHDL - ModelSim testbench simulation freezes when sending "run"VHDL - 发送“运行”时,ModelSim 测试台仿真冻结
【发布时间】:2015-01-09 21:30:01
【问题描述】:

我正在为用于计算傅立叶变换的硬件蝶形算法开发的测试平台遇到问题。

我正在尝试做的是读取一系列输入数据文件(32 位向量)并将输出写入其他一些输出文件。

输入文件有Ar.txt、Ai.txt、Br.txt、Bi.txt、Wr.txt和Wi.txt。

输出文件为Ar_OUT_TB.txt、Ai_OUT_TB.txt、Br_OUT_TB.txt、Bi_OUT_TB.txt。

但是当我尝试使用 ModelSim 进行仿真时,程序只是冻结:我仍然可以做一些事情,比如打开另一个项目/文件等,但是没有波形显示,而且命令行也丢失了。我还尝试模拟我的一个较旧的 VHDL 项目,它确实模拟了,所以我猜问题出在这段代码中。

这些是主要过程(编辑:我还添加了其余的代码,以便理解):

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE STD.TEXTIO.ALL;

ENTITY BUTTERFLY_TESTBENCH IS
END BUTTERFLY_TESTBENCH;

ARCHITECTURE DEVICE OF BUTTERFLY_TESTBENCH IS

COMPONENT progetto_butterfly
        GENERIC(N_IN, N_OUT: INTEGER := 32;
                  N_BUSES: INTEGER := 63);
        PORT(START, CLK, MAIN_RST_N: IN STD_LOGIC;
              DATA_IN, Wr_IN, Wi_IN: IN SIGNED(N_IN-1 DOWNTO 0);
              DATA_OUT: OUT SIGNED(N_IN-1 DOWNTO 0);
              DONE: OUT STD_LOGIC);

END COMPONENT;

CONSTANT N_IN: INTEGER := 32;
CONSTANT N_OUT: INTEGER := 32;

SIGNAL TEST_DATA_IN, TEST_Wr_IN, TEST_Wi_IN: SIGNED(N_IN-1 DOWNTO 0);
SIGNAL TEST_OUTPUT: SIGNED(N_OUT-1 DOWNTO 0);
SIGNAL CLK: STD_LOGIC;
SIGNAL TEST_START, TEST_RST, TEST_DONE: STD_LOGIC;

FILE Ar_IN_FILE: TEXT OPEN READ_MODE IS "Ar.txt";
FILE Ai_IN_FILE: TEXT OPEN READ_MODE IS "Ai.txt";
FILE Br_IN_FILE: TEXT OPEN READ_MODE IS "Br.txt";
FILE Bi_IN_FILE: TEXT OPEN READ_MODE IS "Bi.txt";
FILE WR_FILE: TEXT OPEN READ_MODE IS "Wr.txt";
FILE WI_FILE: TEXT OPEN READ_MODE IS "Wi.txt";
FILE Ar_OUT: TEXT OPEN WRITE_MODE IS "Ar_OUT_TB.txt";
FILE Ai_OUT: TEXT OPEN WRITE_MODE IS "Ai_OUT_TB.txt";
FILE Br_OUT: TEXT OPEN WRITE_MODE IS "Br_OUT_TB.txt";
FILE Bi_OUT: TEXT OPEN WRITE_MODE IS "Bi_OUT_TB.txt";

BEGIN

    BUTTERFLY_TEST_COMPONENT: progetto_butterfly PORT MAP(START => TEST_START, CLK => CLK, MAIN_RST_N => TEST_RST, 
                                                                            DATA_IN => TEST_DATA_IN, Wr_IN => TEST_Wr_IN, Wi_IN => TEST_Wi_IN,
                                                                            DATA_OUT => TEST_OUTPUT, DONE => TEST_DONE);``

DATA_IN_PROCESS: PROCESS
VARIABLE DATA_BUFFER: LINE;
VARIABLE DATA_STIMULUS: BIT_VECTOR(N_IN-1 DOWNTO 0);
BEGIN
    IF NOT (ENDFILE(Br_IN_FILE)) THEN
        IF(TEST_START = '1' AND TEST_RST = '1') THEN
            READLINE(Br_IN_FILE,DATA_BUFFER);
            READ(DATA_BUFFER,DATA_STIMULUS);
            TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
            WAIT UNTIL CLK'EVENT AND CLK = '1';
            READLINE(Bi_IN_FILE,DATA_BUFFER);
            READ(DATA_BUFFER,DATA_STIMULUS);
            TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
            WAIT UNTIL RISING_EDGE(CLK);
            READLINE(Ar_IN_FILE,DATA_BUFFER);
            READ(DATA_BUFFER,DATA_STIMULUS);
            TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
            WAIT UNTIL RISING_EDGE(CLK);
            READLINE(Ai_IN_FILE,DATA_BUFFER);
            READ(DATA_BUFFER,DATA_STIMULUS);
            TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
            WAIT FOR 12 ns;
        ELSE
            TEST_DATA_IN <= (OTHERS => '0');
        END IF;
    END IF;
END PROCESS;

WR_PROCESS: PROCESS
VARIABLE wr_buf: LINE;
VARIABLE WR_STIMULUS: BIT_VECTOR(N_IN-1 DOWNTO 0);
BEGIN
        WHILE NOT (ENDFILE(WR_FILE)) LOOP
            IF(TEST_START = '1' AND TEST_RST = '1') THEN
                READLINE(WR_FILE,wr_buf);
                READ(wr_buf,WR_STIMULUS);
                TEST_Wr_IN <= SIGNED(TO_STDLOGICVECTOR(WR_STIMULUS));
                WAIT FOR 20 ns;
            END IF;
        END LOOP;
END PROCESS;

WRITING_PROCESS: PROCESS
VARIABLE  STRING_LINE: STRING(N_OUT DOWNTO 1);
VARIABLE  OUT_LINE: LINE;
VARIABLE  I: INTEGER;
BEGIN
    WAIT FOR 12 ns;
    WHILE (TEST_START = '1' AND TEST_RST = '1') LOOP
        FOR I IN N_OUT-1 DOWNTO 0 LOOP
            IF(TEST_OUTPUT(I) = '0') THEN
                STRING_LINE(I+1) := '0';
            ELSE
                STRING_LINE(I+1) := '1';
            END IF;
        END LOOP;
        WRITE(OUT_LINE,STRING_LINE);
        WRITELINE(Br_OUT,OUT_LINE);
        WAIT UNTIL RISING_EDGE(CLK);
        FOR I IN N_OUT-1 DOWNTO 0 LOOP
            IF(TEST_OUTPUT(I) = '0') THEN
                STRING_LINE(I+1) := '0';
            ELSE
                STRING_LINE(I+1) := '1';
            END IF;
        END LOOP;
        WRITE(OUT_LINE,STRING_LINE);
        WRITELINE(Bi_OUT,OUT_LINE);
        WAIT UNTIL RISING_EDGE(CLK);
        FOR I IN N_OUT-1 DOWNTO 0 LOOP
            IF(TEST_OUTPUT(I) = '0') THEN
                STRING_LINE(I+1) := '0';
            ELSE
                STRING_LINE(I+1) := '1';
            END IF;
        END LOOP;
        WRITE(OUT_LINE,STRING_LINE);
        WRITELINE(Ar_OUT,OUT_LINE);
        WAIT UNTIL RISING_EDGE(CLK);
        FOR I IN N_OUT-1 DOWNTO 0 LOOP
            IF(TEST_OUTPUT(I) = '0') THEN
                STRING_LINE(I+1) := '0';
            ELSE
                STRING_LINE(I+1) := '1';
            END IF;
        END LOOP;
        WRITE(OUT_LINE,STRING_LINE);
        WRITELINE(Ai_OUT,OUT_LINE);
    END LOOP;
END PROCESS;
    CLK_PROCESS: PROCESS
    BEGIN
        CLK <= '1';
        WAIT FOR 2 ns;
        CLK <= '0';
        WAIT FOR 2 ns;
    END PROCESS;

    TEST_RST <= '0', '1' AFTER 2 ns;
    TEST_START <= '0', '1' AFTER 3 ns;

END ARCHITECTURE;

是不是做错了什么?我看不到我错过了什么。

【问题讨论】:

  • 有两件事可以阻止 VHDL 中的无错误仿真。您在所有驱动程序的预计输出波形中用完了预定事件,并且您将模拟时间提前到现在'高或者你遇到现在'高(这可能需要一段时间)。可以为 Modelsim 中的运行命令提供执行时间以在更短的时间间隔内运行。你没有展示你的整个模型,尤其是声明。这不是Minimal, Complete, and Verifiable example
  • 我添加了其余的代码。至于“now'high”,你能解释一下你是什么意思吗?

标签: io vhdl modelsim


【解决方案1】:

您的DATA_IN_PROCESS 进程是一个无限循环。只要不满足条件TEST_START = '1' AND TEST_RST = '1',进程就会继续运行,而不会增加模拟时间。它会消耗 simulator 时间,而 simuated 时间不会增加。

通过在else 子句中添加WAIT UNTIL RISING_EDGE(CLK); 来解决此问题。

您的代码的其他问题在此处列出:http://www.sigasi.com/vhdl-code-check?ID=27869561

【讨论】:

  • 是的,就是这样。我也删除了 WHILE 语句和 IF 语句。现在它运行了!非常感谢!
【解决方案2】:

您的流程需要敏感度列表或WAIT 声明。

【讨论】:

  • 我认为在测试平台中不需要情感列表。至于 WAIT 语句,我应该等待什么?时钟?在过程的哪个阶段?一开始?
  • 缺少敏感度列表和/或等待语句的进程需要立即一遍又一遍地执行其内部语句。这就是您的模拟器基本上按照您的要求尝试做的事情。
  • 所有进程都有wait 语句。但他们应该在 every 分支中有一个wait 语句。
【解决方案3】:

从您的示例构建 MVCe 后,我发现您正在读取的输入文件似乎太短,这表明您的两个进程(data_in_process 和 wr_process)存在错误。

library ieee;
use std.textio.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity sometb is
end entity;

architecture foo of sometb is
    constant n_in: integer := 8;
    signal test_start:  std_logic := '1';
    signal test_rst:    std_logic := '1';
    file br_in_file: text open READ_MODE is "Br.txt";
    signal test_data_in:    signed(n_in - 1 downto 0);
    signal clk:     std_logic := '0';
    file bi_in_file: text open READ_MODE is "Bi.txt";
    file ar_in_file: text open READ_MODE is "Ar.txt";
    file ai_in_file: text open READ_MODE is "Ai.txt";
    file wr_file:    text open READ_MODE is "Wr.txt";
    signal test_wr_in:      signed(n_in - 1 downto 0);
    constant n_out: integer:= 8;
    signal test_output: std_logic_vector(n_out - 1 downto 0);
    file br_out:    text open WRITE_MODE is "Br_OUT_TB.txt";
    file bi_out:    text open WRITE_MODE is "Bi_OUT_TB.txt";
    file ar_out:    text open WRITE_MODE is "Ar_OUT_TB.txt";
    file ai_out:    text open WRITE_MODE is "Bi_OUT_TB.txt";
begin
CLOCK:
    process
    begin
        wait for 6 ns;
        clk <= not clk;
    end process;
data_in_process:
    process
        variable data_buffer: line;
        variable data_stimulus: bit_vector(n_in-1 downto 0);
    begin
        if not endfile(br_in_file) then
            if test_start = '1' and test_rst = '1'  then
                readline(br_in_file,data_buffer);
                read(data_buffer,data_stimulus);
                test_data_in <= signed(to_stdlogicvector(data_stimulus));
                wait until clk'event and clk = '1';
                readline(bi_in_file,data_buffer);
                read(data_buffer,data_stimulus);
                test_data_in <= signed(to_stdlogicvector(data_stimulus));
                wait until rising_edge(clk);
                readline(ar_in_file,data_buffer);
                read(data_buffer,data_stimulus);
                test_data_in <= signed(to_stdlogicvector(data_stimulus));
                wait until rising_edge(clk);
                readline(ai_in_file,data_buffer);
                read(data_buffer,data_stimulus);
                test_data_in <= signed(to_stdlogicvector(data_stimulus));
                wait for 12 ns;
            else
                test_data_in <= (others => '0');
            end if;
        end if;
        wait until rising_edge(clk); -- added for endfile
    end process;

wr_process:
    process
        variable wr_buf: line;
        variable wr_stimulus: bit_vector(n_in-1 downto 0);
    begin
        while not endfile(wr_file) loop
            if test_start = '1' and test_rst = '1' then
                readline(wr_file,wr_buf);
                read(wr_buf,wr_stimulus);
                test_wr_in <= signed(to_stdlogicvector(wr_stimulus));
                wait for 20 ns;
            end if;
        end loop;
        wait for 20 ns; -- added for when endfile(wr_file) is TRUE.
    end process;

writing_process: 
    process
        variable  string_line: string(n_out downto 1);
        variable  out_line: line;
--        variable  i: integer;  -- the following are not my i
    begin
        wait for 12 ns;
        while test_start = '1' and test_rst = '1' loop
            for i in test_output'range loop -- n_out-1 downto 0 loop
                if test_output(i) = '0' then
                    string_line(i + 1) := '0';
                else
                    string_line(i + 1) := '1';
                end if;
            end loop;
            write(out_line, string_line);
            writeline(br_out, out_line);
            wait until rising_edge(clk);
            for i in test_output'range loop -- n_out-1 downto 0 loop
                if test_output(i) = '0' then
                    string_line(i + 1) := '0';
                else
                    string_line(i + 1) := '1';
                end if;
            end loop;
            write(out_line,string_line);
            writeline(bi_out,out_line);
            wait until rising_edge(clk);
            for i in test_output'range loop -- n_out-1 downto 0 loop
                if test_output(i) = '0'  then
                    string_line(i+1) := '0';
                else
                    string_line(i+1) := '1';
                end if;
            end loop;
            write(out_line,string_line);
            writeline(ar_out,out_line);
            wait until rising_edge(clk);
            for i in test_output'range loop -- n_out-1 downto 0 loop
                if test_output(i) = '0' then
                    string_line(i+1) := '0';
                else
                    string_line(i+1) := '1';
                end if;
            end loop;
            write(out_line,string_line);
            writeline(ai_out,out_line);
        end loop;
    end process;
end architecture;

我加了

        wait until rising_edge(clk); -- added for endfile

在 data_in_process 中的进程结束之前,否则如果 END_FILE(br_in_file) 为 TRUE,它将循环而不暂停。 (而且你真的应该有一个涵盖所有输入的测试或测试)。

我加了

        wait for 20 ns; -- added for when endfile(wr_file) is TRUE.

出于同样的原因到 wr_process。

writing_process 的更改用于发现 test_output 信号的工作范围。注意变量 i 的过程声明项可以被删除,它不被使用。 (循环常量中的 i 不是 i)。

我在 UNIX 环境 (OS X) 中触摸输入文件时发现了输入文件的问题,该输入文件创建的长度为零(在确保我的 VHDL 模拟器如果它们不存在会抱怨之后)。

【讨论】:

  • 选择中断选项后,modelsim 显示模拟在第 102 行中断,这是 WI_PROCESS 的 endfile 循环的结尾。我在循环结束后添加了一个 WAIT 语句(只是 WAIT)。它与您对输入文件长度的建议相关吗?不过,这对我来说仍然有点奇怪:出于调试目的,我确保所有文件只有 1 行,代表我的输入数据(Ar 为 1 行,Ai 为 1 行,等等)。这怎么可能?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多