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)を計算している。