จากโจทย์การทดลองให้ออกแบบวงจรหารแบบ Sequential สำหรับเลขจำนวนเต็ม Unsigned Integers ขนาด 32 bit
# Unsigned Integers คือ เลขจำนวนเต็มที่ไม่มี sign bit บอกว่าบวกหรือลบ ค่าที่ได้จะมีแต่ค่าบวก
ขา input มี
clk คือ สัญญาณ clk สำหรับควบคุมการทำงานของระบบตามขอบขาขึ้นของสัญญาณ
a ตัวตั้งขนาด 32 bit
b ตัวหารขนาด 16 bit
start ขา บังคับการทำงาน เมื่อให้เป็น 1 จะเริ่มการหาร
ขา output มี
q เป็น ผลหารขนาด 16 bit
r เป็น เศษผลหารขนาด 16 bit
done เป็น เมื่อเปลี่ยนจาก 0 เป็น 1 หมายถึงเสร็จกระบวนการหารแล้ว
โดยหลักการที่ใช้คือ
ให้ a เป็น 1000 คือ 8
ให้ b เป็น 0010 คือ 2
เราจะให้ remainder เป็น a และ ดูว่า ถ้า remainder มากกว่า b ให้เอา b ลบ remainder และ shift quantient ไป ทางซ้าย และ ใส่ 1 ไว้ท้าย และ shift right b เพื่อเลื่อนหลัก
ถ้า remainder น้อยกว่า b ก็จะไม่ลบ remainder ด้วย b แต่จะ shift b ไปทางขวา และ shift left quantient และ assign 0 ไว้ท้าย
ทำแบบนี้ไปเรื่อยๆ จนกว่า remainder จะเป็น 0 ทั้งหมด หรือ เช็คไปจนครบ ขนาด quantient+1 รอบ
เช่น quantient ขนาด 32 bit ก็วนลูปเช็ค 33 รอบ หลังจากนั้นเมื่อตรงเงื่อนไขแล้วก็ latch ข้อมูล ให้ quatntient และ remainder ออกมาเป็น output
pseudocode
โจทย์ตัวอย่าง
เมื่อนำหลักการนี้มาออกแบบวงจรด้วย quartus เขียนด้วยภาษา vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use IEEe.STD_LOGIc_ARITH.ALL;
use IEEE.std_logic_unsigned.all;
entity divider is
generic (WIDTH :integer := 32);
port ( clk : in std_logic;
start : in std_logic;
done : out std_logic;
a : in std_logic_vector(WIDTH-1 downto 0);
b : in std_logic_vector((WIDTH/2)-1 downto 0);
q : out std_logic_vector((WIDTH/2)-1 downto 0);
r : out std_logic_vector((WIDTH/2)-1 downto 0)
);
end divider;
architecture behave of divider is
signal temp_b : std_logic_vector(WIDTH-1 downto 0);
signal temp_q : std_logic_vector((WIDTH/2)-1 downto 0);
signal temp_r : std_logic_vector(WIDTH-1 downto 0);
signal operate : std_logic := '1'; -- เอาไว้ตรวจสอบดูว่าหารเสร็จหรือยัง
signal count : integer := 0;
begin
process(clk)
begin
if rising_edge(clk) then
done <= operate;
if start = '1' then
temp_r <= a;
temp_b <= b&conv_std_logic_vector(0,WIDTH/2);
operate <= '0'; -- assign ให้เป็น 0 เพื่อให้รู้ว่ากำลังทำการหารอยู่
elsif count = (WIDTH/2)+1 then
count <= 0; -- reset count
operate <= '1'; -- สิ้นสุดการหาร
elsif temp_r >= temp_b and operate = '0' then
temp_r <= temp_r-temp_b;
temp_q <= temp_q((WIDTH/2)-2 downto 0)&'1'; -- shift left
temp_b <= '0'&temp_b(WIDTH-1 downto 1); -- shift right
count <= count + 1;
elsif temp_b >= temp_r and operate = '0' then
temp_q <= temp_q((WIDTH/2)-2 downto 0)&'0'; -- shift left
temp_b <= '0'&temp_b(WIDTH-1 downto 1); -- shift right
count <= count + 1;
elsif operate = '1' or (temp_r = conv_std_logic_vector(0,WIDTH)) then
q <= temp_q;
r <= temp_r((WIDTH/2)-1 downto 0);
end if;
end if;
end process;
end behave;
รูป Vhdl Testbench (จำลองการทำงาน)
ทดลองหารแบบมีเศษเหลือ
126/8 ได้ 15เศษ6
4
ทดลองหารแบบลงตัว
250/5 ได้ 50เศษ0
ไม่มีความคิดเห็น:
แสดงความคิดเห็น