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

multiple

จากโจทย์การทดลองให้ออกแบบวงจรคูณแบบ Sequential สำหรับเลขจำนวนเต็ม Unsigned Integers ขนาด 16 bit

# Unsigned Integers คือ เลขจำนวนเต็มที่ไม่มี sign bit บอกว่าบวกหรือลบ ค่าที่ได้จะมีแต่ค่าบวก

ขา input มี
clk คือ สัญญาณ clk สำหรับควบคุมการทำงานของของระบบ
a ตัวตั้งขนาด 16 bit
b ตัวคูณขนาด 16 bit
start ขา บังคับการทำงาน เมื่อให้เป็น 1 จะเริ่มการคูณ

ขา output มี
p เป็น ผลคูณขนาด 32 bit
done เป็น เมื่อเปลี่ยนจาก 0 เป็น 1 หมายถึงเสร็จกระบวนการคูณแล้ว

โดยหลักการที่ใช้คือ 
ให้ a เป็น 0101 คือ 5
ให้ b เป็น 0011 คือ 3

เราจะดูตำแหน่งตรง ตัวขวาสุดของ b ถ้าเป็น 1 ให้ เอา a มาบวกกับ product แล้วทำการ shift a ไปทางซ้ายเพื่อเป็นการเลื่อนหลัก และ shift b ไปทางขวาเพื่อเช็ค bit ถัดไป

ถ้าขวาสุดของ b เป็น 0 จะไม่เอา a มาบวกกับ product เพิ่ม จะ shift a กับ b อย่างเดียว

โดยที่จำนวนรอบในการเช็ค b จะวนแค่ เท่ากับขนาดของ ตัว b หรือเมื่อจนกว่าค่าของตัว b จะเป็น 0 ทั้งหมด เมื่อนับครบแล้วก็จะทำการ latch ข้อมูลผลคูณออกมาเป็น 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 multiplier is
generic(WIDTH :integer := 32);
port( 
clk : in std_logic;
start : in std_logic;
done : out std_logic;
a : in std_logic_vector((WIDTH/2)-1 downto 0);
b : in std_logic_vector((WIDTH/2)-1 downto 0);
p : out std_logic_vector(WIDTH-1 downto 0)
);
end multiplier;

architecture behave of multiplier is
signal temp_a : std_logic_vector(WIDTH-1 downto 0);
signal temp_b : std_logic_vector((WIDTH/2)-1 downto 0);
signal count : integer := 0;
signal operate : std_logic := '1';  -- เอาไว้ตรวจสอบดูว่าคูณเสร็จหรือยัง
signal product : std_logic_vector(WIDTH-1 downto 0);
  
begin
process(clk)
begin
if rising_edge(clk) then
done <= operate;  
if start = '1' then
temp_a <= conv_std_logic_vector(0,WIDTH/2)&a;
temp_b <= b;
operate <= '0';  -- assign ให้เป็น 0 เพื่อให้รู้ว่ากำลังทำการคูณอยู่

elsif count = WIDTH/2 then
count <= 0;  -- reset count
operate <= '1';  -- สิ้นสุดการคูณ

elsif temp_b(0) = '1' and operate = '0' then
product <= product+temp_a;
temp_b <= '0'&temp_b((WIDTH/2)-1 downto 1);  -- shift_right
temp_a <= temp_a(WIDTH-2 downto 0)&'0';  -- shift_left
count <= count + 1;
elsif temp_b(0) = '0' and operate = '0' then
temp_b <= '0'&temp_b((WIDTH/2)-1 downto 1);  -- shift_right
temp_a <= temp_a(WIDTH-2 downto 0)&'0';  -- shift_left
count <= count + 1;
elsif operate = '1' or (temp_b = conv_std_logic_vector(0,WIDTH/2)) then -- ถ้า คูณครบจำนวน bit หรือ ตัวคูณ b เป็น 0 ทั้งหมดให้ latch ข้อมูลออกเป็น output
p <= product;
end if;
end if;
end process;
end behave;

รูป Vhdl Testbench (จำลองการทำงาน)



ทดลอง ให้ a และ b เป็น 12 ได้ ผลลัพธ์ 144





ทดลอง ให้ a และ b เป็น 23 กับ 12 ได้ ผลลัพธ์ 276


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

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