【问题标题】:VHDL - synthesis results is not the same as behavioralVHDL - 综合结果与行为不同
【发布时间】:2016-01-09 13:47:35
【问题描述】:

我必须用 VHDL 编写程序,使用牛顿法计算 sqrt。我编写了在我看来没问题的代码,但它不起作用。 行为模拟提供适当的输出值,但后合成(并在硬件上启动)没有。 程序被实现为状态机。输入值为整数(使用格式为std_logic_vector),输出为定点(用于计算 目的输入值乘以 64^2 所以输出值有 6 个 LSB 位是小数部分)。
我使用函数将 vhdl 与 vhdlguru blogspot 分开。 在行为模拟中计算 sqrt 大约需要 350 ns (Tclk=10 ns),但在后期合成中仅需要 50 ns。

使用代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

        entity moore_sqrt is
port (clk : in std_logic;
      enable : in std_logic;
      input : in std_logic_vector (15 downto 0);
      data_ready : out std_logic;
      output : out std_logic_vector (31 downto 0)
  );
end moore_sqrt;

architecture behavioral of moore_sqrt is
------------------------------------------------------------
function  division  (x : std_logic_vector; y : std_logic_vector) return std_logic_vector is
variable a1 : std_logic_vector(x'length-1 downto 0):=x;
variable b1 : std_logic_vector(y'length-1 downto 0):=y;
variable p1 : std_logic_vector(y'length downto 0):= (others => '0');
variable i : integer:=0;
    begin
        for i in 0 to y'length-1 loop
            p1(y'length-1 downto 1) := p1(y'length-2 downto 0);
            p1(0) := a1(x'length-1);
            a1(x'length-1 downto 1) := a1(x'length-2 downto 0);
            p1 := p1-b1;
            if(p1(y'length-1) ='1') then
                a1(0) :='0';
                p1 := p1+b1;
            else
                a1(0) :='1';
            end if;
        end loop;
return a1;
end division;
-------------------------------------------------------------- 
type state_type is (s0, s1, s2, s3, s4, s5, s6);  --type of state machine
signal current_state,next_state: state_type;  --current and next state declaration

signal xk : std_logic_vector (31 downto 0);
signal temp : std_logic_vector (31 downto 0);
signal latched_input : std_logic_vector (15 downto 0);
signal iterations : integer := 0;
signal max_iterations : integer := 10;  --corresponds with accuracy

begin

process (clk,enable)
begin
if enable = '0' then
    current_state <= s0; 
elsif clk'event and clk = '1' then
    current_state <= next_state;   --state change
end if;
end process;

--state machine
process (current_state)
begin
  case current_state is
    when s0 =>          -- reset       
        output <= "00000000000000000000000000000000";
        data_ready <= '0';
        next_state <= s1;
    when s1 =>          -- latching input data
        latched_input <= input;
        next_state <= s2;        
     when s2 =>         -- start calculating
        -- initial value is set as a half of input data
        output <= "00000000000000000000000000000000";
        data_ready <= '0';
        xk <= "0000000000000000" & division(latched_input, "0000000000000010");
        next_state <= s3;
        iterations <= 0;
    when s3 =>         -- division
        temp <= division ("0000" & latched_input & "000000000000", xk);
        next_state <= s4;
    when s4 =>          -- calculating 
        if(iterations < max_iterations) then
            xk <= xk + temp;
            next_state <= s5;
            iterations <= iterations + 1;
        else
            next_state <= s6;
        end if;
    when s5 =>          -- shift logic right by 1
            xk <= division(xk, "00000000000000000000000000000010");
            next_state <= s3;       
    when s6 =>             -- stop - proper data
--          output <= division(xk, "00000000000000000000000001000000");  --the nearest integer value
            output <= xk;    -- fixed point 24.6, sqrt = output/64;
            data_ready <= '1';
    end case;
end process;
end behavioral;

下面是行为和综合后模拟结果的屏幕截图:

Behavioral simulation

Post-synthesis simulation

我对 VHDL 的经验很少,我不知道我可以做些什么来解决问题。我试图排除其他用于计算的过程,但它也不起作用。

我希望你能帮助我。 平台:Zynq ZedBoard IDE:Vivado 2014.4

问候, 迈克尔

【问题讨论】:

  • 你检查过合成中的所有警告吗?如果综合设计的行为与设计不等效,因此与仿真不等效,则综合工具通常会发出警告。因此,请认真对待警告,即使综合工具接受代码并在没有错误的情况下完成。

标签: vhdl state-machine synthesis vivado zynq


【解决方案1】:

如果以similar to this 的模式以单进程形式重写状态机,则可以消除很多问题。这将消除不需要的锁存器,以及由灵敏度列表错误引起的模拟/综合不匹配。

我相信您还必须以状态机的形式使用其循环重写除法函数 - 一个单独的状态机,与主状态机握手以启动除法并发出完成信号,或者作为一部分单个分层状态机as described in this Q&A

【讨论】:

    【解决方案2】:

    此代码既不适合模拟也不适合综合。

    模拟问题:

    • 您的敏感度列表不完整,因此模拟没有显示合成硬件的正确行为。如果进程没有计时,则应包括所有右侧信号。

    综合问题:

    • 您的代码会产生大量的锁存器。只有一个寄存器叫做current_state。除非您确切知道自己在做什么,否则应避免闩锁。
    • 如果您想保持电路的正确频率,则不能以使用该功能的方式除数。
      => 所以检查你的 Fmax 报告和
      => 资源利用的 RTL 原理图或综合报告。
    • 不要使用该设备来移位位。如果一个值移动了 2 的幂,那么在软件中编译器都不会实现除法。使用移位操作来移位一个值。

    需要重新考虑的其他事项:

    • enable 是低电平有效异步复位。同步复位更适合 FPGA 实现。

    【讨论】:

    • 所有优点,除了异步重置。同步/异步复位都有其优点。不能说一个比另一个好。可以说异步复位更通用,因为相同的设计将在 SRAM FPGA 以及 ASIC 或基于闪存的 FPGA 中运行良好。它允许在时钟可用之前在启动时进行可靠的复位。同步复位的优点是允许对设计进行可靠的部分复位。
    • @TimmyBrolin 同步重置可以是(逻辑)优化的一部分。异步永远不可能。
    • 所有 FPGA 和 ASIC 库都具有本机异步复位输入的触发器。这是最优化的解决方案,因此不需要优化。本地并不总是支持同步复位,从而导致性能下降,因为同步复位必须在 D 输入上进行门控,从而导致更大的逻辑深度。您可以在此处阅读有关异步和同步重置之间差异的更多信息:sunburst-design.com/papers/CummingsSNUG2003Boston_Resets.pdf
    【解决方案3】:

    VHDL 代码可以是可综合的,也可以是不可综合的,综合结果可以表现为仿真,也可以不是。这取决于代码、合成器和目标平台,很正常。

    行为代码适用于测试平台,但通常无法合成。

    在这里我看到了您的代码最明显的问题:

    process (current_state)
    begin
    [...]
                 iterations <= iterations + 1;
    [...]
    end process;
    

    您正在迭代一个未出现在进程敏感度列表中的信号。这对于像软件一样执行流程块的模拟器来说可能没问题。另一方面,合成结果是完全不可预测的。但是向敏感度列表添加迭代是不够的。你最终会得到一个异步设计。您的目标平台是时钟设备。状态变化可能只发生在时钟的触发边沿。 您需要告诉合成器如何映射在时钟周期内执行此计算所需的迭代。最安全的方法是将行为代码分解为 RTL 代码 (https://en.wikipedia.org/wiki/Register-transfer_level#RTL_in_the_circuit_design_cycle)。

    【讨论】:

    • @KrzysztofB 如果您对硬件设计和 VHDL 很认真,我强烈建议您阅读并学习这本书:Peter J. Ashenden,The Designer's Guide to VHDL。 (第 2 版中的旧书非常便宜!)您的挣扎不在于 VHDL 语言,而在于如何理解如何用该语言描述有用的电路。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多