วันศุกร์ที่ 4 มีนาคม พ.ศ. 2559

การออกแบบวงจรหารด้วยภาษา VHDL

การออกแบบวงจรหาร
Cr. http://cpre.kmutnb.ac.th/esl


Cr. http://cpre.kmutnb.ac.th/esl


Simulation




หลักการ ให้ r เป็น a ถ้า a น้อยกว่า b จะ shift b ไปทางขวา และ shift left q และ ให้ 0 ไว้ท้าย ถ้า a มากว่าเท่ากับ b จะเอา b ลบ r และ shift left q และ ใส่ 1 ไว้ท้าย และ shift right b เพื่อเลื่อนหลัก

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

Output:
   q เป็น ผลหารขนาด 16 bit
   r เป็น เศษผลหารขนาด 16 bit
   done ตัวบอกสถานะการทางานการหาร
Division Code 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 division is
generic (WIDTH :integer := 32);
 port ( clk : in std_logic;
   START : in std_logic;
   a : in std_logic_vector(WIDTH-1 downto 0);
   b : in std_logic_vector((WIDTH/2)-1 downto 0);
DONE : out std_logic;
   q,r : out std_logic_vector((WIDTH/2)-1 downto 0)
   
 );
end division;

architecture Behavioral of division 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 done_1 : std_logic := '1';  -- เอาไว้ตรวจสอบดูว่าหารเสร็จหรือยัง
signal count : integer := 0;

begin
 process(clk)
  begin
   if rising_edge(clk) then
    done <= done_1;
    if START = '1' then
     temp_r <= a;
     temp_b <= b&conv_std_logic_vector(0,WIDTH/2);--conv_std_logic_vector แปลงฐาน10 เป็นฐาน2
     done_1 <= '0';  -- done_1เป็น 0 คือกำลังหารอยู่
   
    elsif count = (WIDTH/2)+1 then
     count <= 0;  -- เริ่มนับ countใหม่
     done_1 <= '1';  -- หารเสร็จเเล้ว
    
    elsif temp_r >= temp_b and done_1 = '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 done_1 = '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 done_1 = '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 Behavioral;



การออกแบบวงวรคูณ โดยภาษา VHDL

การออกแบบวงวรคูณ
 cr. http://cpre.kmutnb.ac.th/esl

cr. http://cpre.kmutnb.ac.th/esl








หลักการ เอา ตัวขวาสุดของ a ถ้าเป็น 1 ให้ เอา b มาบวกกับ product ถ้า a ตัวขวาสุดเป็น 0 ก็ไม่ต้องมาบวกกับ product แล้ว shift a ไปทางขา shift b ไปทางซ้าย


Input :
clk สัญญาณสาหรับควบคุมการทางานของของระบบ
a เลขฐาน2ขนาด 16 bit
b เลขฐาน2ขนาด 16 bit
 START ตัวบังคับการทางาน

Output:
P ผลการคูณ
DONE ตัวบอกการทางานการคูณ


                                                              Multiplication CODE VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;


entity mul is
Port (
                 clk : in std_logic;
                  a ,b: in std_logic_vector(15 downto 0);
                 START : in std_logic;
                   P : out std_logic_vector(31 downto 0);
                   DONE : out std_logic);
 end mul;
architecture Behavioral of mul is
signal keepA,keepB : std_logic_vector(31 downto 0) ; --รับค่า a และ b
signal count : integer := 0 ;
signal result : std_logic_vector(31 downto 0) ;
signal product : std_logic_vector(31 downto 0) ;
begin
    process(clk)
          begin
           if (rising_edge(clk) ) then
             if( START = '1' )then
                   keepA <= "0000000000000000"&a; -- ให้keepA รับค่าจาก a
                    keepB <= "0000000000000000"&b; -- ให้keepB รับค่าจาก b
                   DONE <= '0'; -- ให้ done เป้น 0 คือกาลังคูณอยู่
             elsif(keepA (0)='1')then
                    result <= keepB ;
                    product <= result + product;
                    keepA(30 downto 0) <= keepA(31 downto 1);--shift_right
                    keepA(31) <= '0';
                    keepB(31 downto 1) <= keepB(30 downto 0);--shift_left
                    keepB(0) <= '0';
                  count <= count +1 ;
             elsif(keepA (0)='0')then
                      result <= "00000000000000000000000000000000";
                      keepA(30 downto 0) <= keepA(31 downto 1);--shift_right
                      keepA(31) <= '0';
                      keepB(31 downto 1) <=keepB(30 downto 0);--shift_left
                      keepB(0) <= '0';
                      product <= result + product;
              end if;
           end if;
   end process;
P <= product;
end Behavioral;