VHDL:有错误编码的除法,但在 Quartus II 上编译时有错误,但在 Xilinx ISE 上没有

Posted

技术标签:

【中文标题】VHDL:有错误编码的除法,但在 Quartus II 上编译时有错误,但在 Xilinx ISE 上没有【英文标题】:VHDL: Division with error coding but there are errors in compiling on Quartus II but not on Xilinx ISE 【发布时间】:2017-08-18 03:25:44 【问题描述】:

我对 VHDL 很陌生,我想得到一些帮助。你看,我们的导师告诉我们编写二进制除法(首先将二进制转换为整数),如果除数为零,则输出误差波形将显示在模拟中。这是我的代码:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity division_in is
    Port ( A : in  STD_LOGIC_VECTOR (7 downto 0);
           B : in  STD_LOGIC_VECTOR (7 downto 0);
           clk : in  STD_LOGIC;
           Y : out  STD_LOGIC_VECTOR (7 downto 0);
           err : out  STD_LOGIC);
end division_in;

architecture Behavioral of division_in is

begin

  process(clk)
  begin
    if clk='1' and clk'event then -- error here
      Y <= conv_std_logic_vector(conv_integer(A)/conv_integer(B),8);
      err <= '0';
    elsif B = 0 then
      err <= '1';
    end if;
  end process;

end Behavioral;

当我尝试在 Xilinx ISE 9.1i(大学使用的)中使用“检查语法”时,成绩单上没有显示语法错误。我什至可以毫无问题地使用测试台波形来模拟它。 但是,当我将此代码导入 Quartus II 时,我在消息中收到 5 个错误,尤其是在这个:

错误 (10818):无法在 division_in.vhd(45) 推断“err”寄存器,因为它在时钟边沿之外没有保持其值

我不知道在将确切的代码从 Xilinx 复制到 Quartus 时我做错了什么,但非常感谢我在 Quartus II 上出现此错误但在 Xilinx ISE 9.1i 上没有出现此错误的原因。由于 Xilinx ISE 已经不再兼容我的笔记本电脑,我只使用 Quartus II 代替,因为它还具有“矢量波形文件”仿真的仿真功能。

【问题讨论】:

您的代码在语法上是正确的,但没有描述真实的硬件,所以它是不可综合的。尝试使用 B=0 作为 err 寄存器的同步设置信号。 如果我一开始对此很陌生,请原谅我,但“可合成”是什么意思?合成与模拟有什么不同?感谢您的回答:D 这段代码不可能在 ISE 中“工作”(出于多种原因,您的“教练”不应该让您进行这样的练习 - 这是什么课程??)考虑这一点 - 您的进程clk 更改时触发。然后你的逻辑是这样的:如果有上升沿,执行假除法并将err 设置为 0;否则(即,如果有 下降 边沿)并且如果 B 在该下降沿上为 0,则将 err 设置为 1。不是你想要的。 @c2s1 "synthesizable" 意味着您描述的电路行为可以映射到目标 FPGA 上的可用硬件结构。在您的代码中,您描述了 err 信号的某种奇怪行为,这些行为无法映射到真实的硬件结构。 VHDL中有很多语言结构,只能用于仿真,不能用于综合。在 VHDL 被发明的那些日子里,甚至没有人考虑使用它来进行综合 :-) @Juergen 现在我明白了合成的含义。嗯,谢谢你的信息。看起来我将更多地关注模拟而不是综合,因为在我们使用基本 vhdl 编码的课程中,只能对 VHDL 编码进行模拟,但 Verilog HDL 编码将用于我们的 FPGA 板的硬件实现。 【参考方案1】:

好的,第一件事是第一,不要use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL。您应该使用use ieee.numeric_std.all,它为您提供了使用signedunsigned 类型的算术,以及std_logic_vectorinteger 的强制转换和转换函数。

现在让我们看看你的代码:

if clk='1' and clk'event then -- error here
  Y <= conv_std_logic_vector(conv_integer(A)/conv_integer(B),8);
  err <= '0';
elsif B = 0 then
  err <= '1';
end if;

仅查看err 信号,这说明在时钟上升沿,将err 设置为'0'否则如果B = 0,则设置err'1'。您提到这在模拟中有效,但对于综合,您需要考虑这在真实硬件中意味着什么。您如何想象没有检测到时钟沿的情况?答案是不能。

目前尚不清楚您想要实现的具体目标,但在对上述软件包进行更改后,两种可行的替代方案是:

if rising_edge(clk) then -- Use rising_edge() function
  Y <= std_logic_vector(signed(A)/signed(B));
  err <= '0'; -- Synchronous clear of `err`
end if;
if signed(B) = 0 then -- Asynchronous set of `err`
  err <= '1';
end if;

if rising_edge(clk) then
  Y <= std_logic_vector(signed(A)/signed(B));
  if signed(B) = 0 then
    err <= '1'; -- Synchronous control of `err`
  else
    err <= '0';
  end if;
end if;

如果您为端口提供它们实际的类型,即signed,则代码将需要更少的类型转换。您的流程的核心将如下所示:

if rising_edge(clk) then
  Y <= A / B;
  if B = 0 then
    err <= '1'; -- Synchronous control of `err`
  else
    err <= '0';
  end if;
end if;

我希望你能看到这篇文章是多么容易阅读。

【讨论】:

那么这是否意味着 Xilinx ISE 中使用的库约定与 Quartus II 不同? :) 感谢您的回复,我可以使用您的代码建议作为很好的参考。 @c2s1 这些库可以使用不同的工具给出不同的结果,但我认为这不是你的问题。您必须查看赛灵思工具的综合输出才能了解它的作用。

以上是关于VHDL:有错误编码的除法,但在 Quartus II 上编译时有错误,但在 Xilinx ISE 上没有的主要内容,如果未能解决你的问题,请参考以下文章

使用Quartus13进行VHDL工程的编写与仿真

软件:Quartus II,语言:VHDL或verilog HDL?

vhdl中怎么实现多行注释掉,就是暂时不用那一块

quartus II 13中功能仿真应该怎么仿啊

Quartus II 上手攻略

关于quartus ii 7.2的使用问题