VHDL报告语句被忽略

时间:2018-08-30 05:30:26

标签: vhdl quartus

要学习VHDL,我正在用VHDL实现自己的自定义CPU。

由于讨厌手动编写操作码位模式,我想创建一个非常简单的“汇编程序”来创建位模式。

这是这种汇编器的当前实现:

Issued_d

这是encode_unsigned和encode_signed函数的定义:

library ieee;
use ieee.std_logic_1164.all;
use work.utility.all;

package assembler is
    function encode_opcode(cmd: string; re: integer; rd: integer; ra: integer; rb: integer; imm: integer) return std_logic_vector;
end;

package body assembler is
    function to_lower(x: character) return character is
        constant posA: integer := character'pos('A');
        constant posZ: integer := character'pos('Z');
        constant posLowerA: integer := character'pos('a');
        constant posX: integer := character'pos(x);
    begin
        if posA <= posX and posX <= posZ then
            return character'val(posX - posA + posLowerA);
        else
            return x;
        end if;
    end;

    function to_lower(x: string) return string is
        variable r: string(x'range);
    begin
        for i in x'range loop
            r(i) := to_lower(x(i));
        end loop;
        return r;
    end;

    function encode_cmd(cmd: string) return std_logic_vector is
        constant cmd2: string(1 to cmd'length) := cmd;
        variable cmd3: string(1 to 5) := "-----";
    begin
        if cmd'length > 5 then
            report "Illegal command: " & cmd severity error;
            return "";
        end if;
        for i in cmd2'range loop
            cmd3(i) := cmd2(i);
        end loop;
        case to_lower(cmd3) is
            -- Group 1: Memory access (omitted)
            -- Group 2: Addition
            when "addu-" => return "00100000";
            when "subu-" => return "00100001";
            when "add--" => return "00100010";
            when "sub--" => return "00100011";
            -- Group 3: Multiplication
            when "multu" => return "00110000";
            when "divu-" => return "00110001";
            when "mult-" => return "00110010";
            when "div--" => return "00110011";
            -- Group 4: Bitwise (omitted)
            -- Group 5: Shift
            when "shf--" => return "01010000";
            when "shfu-" => return "01010001";
            when "rot--" => return "01010010";
            -- Group 6: Branch absolute (omitted)
            -- Group 7: Branch relative (omitted)
            when others =>
                report "Illegal command: " & cmd severity error;
                return "";
        end case;
    end;

    function encode_opcode(cmd: string; re: integer; rd: integer; ra: integer; rb: integer; imm: integer) return std_logic_vector is
    begin
        return encode_cmd(cmd) & encode_unsigned(re, 5) & encode_unsigned(rd, 5) & encode_unsigned(ra, 5) & encode_unsigned(rb, 5) & encode_signed(imm, 4);
    end;
end;

这是encode_opcode函数的用法:

function encode_unsigned(x: integer; n: integer) return std_logic_vector is
begin
    return std_logic_vector(to_unsigned(x, n));
end;

function encode_signed(x: integer; n: integer) return std_logic_vector is
begin
    return std_logic_vector(to_signed(x, n));
end;

每当我犯错并写了类似function rom_contents(addr: std_logic_vector) return std_logic_vector is begin case decode_unsigned(addr) is when 0 => return encode_opcode("ADDu", 0, 1, 0, 0, 2); when 1 => return encode_opcode("ADD", 0, 2, 0, 0, -8); when 2 => return encode_signed(11, 32); when 3 => return encode_opcode("MULT", 0, 3, 1, 2, 0); when 6 => return encode_opcode("ADD", 0, 4, 3, 0, 0); when 8 => return encode_opcode("ADD", 0, 16, 0, 0, -8); when 9 => return encode_signed(16#12345678#, 32); when 11 => return encode_opcode("ROT", 31, 30, 16, 0, 4); when 12 => return encode_opcode("ROT", 29, 28, 30, 0, 4); when others => return (31 downto 0 => '0'); end case; end; 之类的内容时,我都希望得到类似encode_opcode("ROTE", 31, 30, 16, 0, 4);之类的错误消息。但是,它不会创建任何错误消息,并且encode_opcode的返回值长度默默地变为24。 (如果没有错误,则长度应为32。)

使用枚举作为命令太困难了,因为某些命令看起来像Illegal command: ROTEANDXORGFu>

我正在使用Quartus Prime Lite Edition 18.0

更新:rom_contents的用法:

GT<=

当我输入错误的命令时,entity instruction_memory_controller is port ( clock: in std_logic; addr: in std_logic_vector(31 downto 0); q: out std_logic_vector(31 downto 0) ); end; architecture RTL of instruction_memory_controller is begin process(clock) begin if rising_edge(clock) then q <= rom_contents(addr); end if; end process; end; 由于大小不匹配(24对32)而标记为错误。

当我将非法命令的返回值从q <= rom_contnts(addr)更改为""时,它的编译没有任何错误/警告。 (我的期望是它会通过报告语句触发"XXXXXXXX"错误。)

1 个答案:

答案 0 :(得分:1)

  1. 关于返回向量的长度:当遇到非法操作码时,您的encode_cmd函数将返回一个空向量。因此,encode_opcode返回的向量的总长度不是32而是24 ...如果在所有情况下都希望获得32位,则返回"00000000"或任何其他8位长的向量。

  2. 关于缺少的错误消息:它与Modelsim一起显示。由于您没有显示对rom_contents的处理方式,因此我们无法猜测向量长度不匹配是否会引起模拟错误。如果是的话,是否可能是因为Quartus优先于report "Illegal command...并且从未解雇过后者?还是可能是您错过了错误消息,因为它不是最后打印的错误消息?

注意:

  • 如果您希望在遇到非法操作码时真正停止模拟,请尝试使用severity failure而不是severity error,或者找到模拟器的选项,以选择严重性级别,高于该严重性级别,模拟将停止。
  • 您使用std_logicstd_logic_vector这两个类型。考虑到您的设计,我怀疑您确实有多种驱动情况。您应该考虑使用std_ulogicstd_ulogic_vector,因为这样做会更安全。而且,您显然使用了VHDL 2008风格,因此可以用signedunsigned替代u_signedu_unsigned。总而言之,它带来的好处是不需要的多驱动器情况会引发错误。
交换评论后,

编辑

Quartus是一个合成器。因此,在门级仿真之前,它有可能综合您的设计。如果这是真的,那么您必须意识到一些重要的事情:report语句被合成过程忽略,因为它们没有等效的硬件。因此,您对Quartus所能期望的最好的结果就是它检测到始终到达report语句,并决定在综合过程中显示它。在某些情况下,这是可能的,因为合成器试图通过传播常量来简化设计:

constant condition: boolean := true;
...
if condition then
    report 'Foo bar';
end if;

成为:

report 'Foo bar';

不幸的是,在更复杂的示例中(例如您的示例),要检测到始终到达report语句要困难得多。这是因为只有在给定的时钟周期数之后,当您的地址到达错误的ROM条目时,它才会到达。不要指望逻辑合成器能够检测到这一点。

解决方案:

  1. 例如,使用真实的模拟器(例如GHDL或Modelsim)来验证您的设计。
  2. 实施真实的错误信号,而不是抽象的,面向模拟的report语句。在合成后仿真期间(以及在硬件目标上执行期间)监视此信号。这是迈向处理器真正无效指令异常的第一步。

关于VHDL 2008的说明:如果您将case语句中的'-'(无关紧要)值用作匹配任何值的方式,那么我认为您正在使用VHDL 2008。如果我还记得的话,它是在2008年推出的。在此之前,它是一个与其他任何值一样的值(ieee.numeric_std.std_match函数中除外)。

相关问题