0

Newton 法を使用して sqrt を計算する VHDL でプログラムを作成する必要があります。大丈夫だと思われるコードを書きましたが、機能しません。ビヘイビアー シミュレーションでは適切な出力値が得られますが、合成後 (およびハードウェアで起動) では得られません。プログラムはステートマシンとして実装されました。入力値は整数 (使用される形式は std_logic_vector) で、出力は固定小数点です (計算目的で入力値に 64^2 を掛けたので、出力値の LSB ビットは小数部になります)。
関数を使用して、vhdlguru blogspot から vhdl を分割しました。ビヘイビア シミュレーションでは、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;

以下のビヘイビアおよび合成後のシミュレーション結果のスクリーンショット:

行動シミュレーション

合成後のシミュレーション

私は VHDL の経験がほとんどなく、問題を解決するために何ができるかわかりません。計算用の他のプロセスを除外しようとしましたが、うまくいきませんでした。

あなたが私を助けてくれることを願っています。プラットフォーム: Zynq ZedBoard IDE: Vivado 2014.4

よろしく、ミハル

4

3 に答える 3

1

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 )。

于 2016-01-09T15:14:38.817 に答える