平方根を求める / 回路全体を試す

pp.322-325
今度は回路全体を試す。

条件は下のとおりとする。

  • startパルスの入力時に計算を開始する。
  • startもxもクロックには非同期。
  • startパルスの長さは決まっていないので、シンクロナイザーを通したあとにワンショットパルス化する(p.55、figure 2.27a)。
  • xは、計算開始後に変化する可能性があるので、前の計算が終わるまで計算部へは通さないことにする。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity square_root_calculator is
    generic(
        NUM_BITS: natural := 8
    );
    port(
        clk, rst, start: in std_logic;

        x: in  unsigned(NUM_BITS-1 downto 0);
        y: out unsigned((NUM_BITS+1)/2-1 downto 0);

        done: out std_logic
    );
end entity;

architecture rtl of square_root_calculator is
    signal start_sync: std_logic;
    signal x_sync    : unsigned(x'range);
    signal n         : unsigned(y'range);
begin

   -- startパルスをクロックに同期化し、さらにワンショットパルス化する。
    process(clk)
        variable q: std_logic_vector(0 to 2);
    begin
        if rising_edge(clk) then
            q := start & q(0 to 1); -- これがシンクロナイザー
        end if;
        start_sync <= q(1) and not q(2) and done; -- q(1) and not q(2)でワンショットパルスを生成。
    end process;
    
    process(clk)
    begin
        if rising_edge(clk) then
            if start_sync then
                x_sync <= x;
            end if;
        end if;
    end process;
    
   -- ダウンカウンター
    process(clk, rst)
    begin
        if rst then
            n <= (others => '0');
        elsif rising_edge(clk) then
            if start_sync then
                n <= (others=> '1');
            elsif not done then
                n <= n - 1;
            end if;
        end if;
    end process;
    y <= n;
    
    process(clk)
    begin
        if falling_edge(clk) then
            if n*n <= x_sync then
                done <= '1';
            else
                done <= '0';
            end if;
        end if;
    end process;
    

end architecture;

今√x0A9 (=√169) =0b1101 (=13)を計算している。
f:id:ti-nspire:20210426071616j:plain