วันศุกร์ที่ 26 กุมภาพันธ์ พ.ศ. 2559

divider

จากโจทย์การทดลองให้ออกแบบวงจรหารแบบ 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

ไม่มีความคิดเห็น:

แสดงความคิดเห็น