วันจันทร์ที่ 26 มกราคม พ.ศ. 2558

การทดลองที่ 1

การสร้างสัญญาณ PWM ช่องสัญญาณ สำหรับ RGB LED

วัตถุประสงค์
1.ศึกษาการทำงานของบอร์ด FPGA
2.สามารถออกแบบการทำงานของวงจรดิจิทัลได้
3.เข้าใจและสามารถอธิบายการทำงานของวงจรได้
อุปกรณ์
1.บอร์ด FPGA CYCLOne 3   ชิปหมายเลข EP3C10E144C8  1 บอร์ด
2. ออสซิโลสโคป  1 เครื่อง
3. สายไฟ
4. คอมพิวเตอร์ที่มีโปรแกรม QuartUS
ข้อกำหนดในการทดลอง
จงออกแบบวงจรดิจิทัล โดยใช้ภาษา VHDL สำหรับนำไปสร้างเป็นวงจรในชิป FPGA โดยใช้บอร์ดที่มีอยู่ในห้องแล็ป
   1) วงจรดิจิทัลมี I/O ดังนี้
          - CLK (input) มีความถี่ 50MHz ใช้สำหรับกำหนดจังหวะการทำงานของวงจรทั้งหมด (เป็นการออกแบบวงจรดิจิทัลแบบ Synchronous Design)
          - RST_B (input) เป็นอินพุตสำหรับใช้รีเซตแบบ Asynchronous สำหรับการทำงานของวงจรโดยรวม (ทำงานแบบ Active-Low) ซึ่งได้จากวงจรปุ่มกด (Push Button)
          - PB[2:0] (input) เป็นอินพุตจากปุ่มกด 3 ปุ่ม ทำงานแบบ Active-low เพื่อใช้ในการเปลี่ยนค่า Duty Cycle โดยเพิ่มทีละ 10 ในช่วง 0 ถึง 100 สำหรับสัญญาณ PWM(2:0) ที่มี 3 ช่องสัญญาณ
          - PWM[2:0] (output) เป็นเอาต์พุตสำหรับนำไปควบคุมการทำงานของ RGB LED
จำนวน 1 ดวง
   2) พฤติกรรมการทำงานเป็นดังนี้
          - เมื่อเริ่มต้นหรือกดปุ่มรีเซต RST_B ค่า PWM [2:0] จะเป็นลอจิก 0 ทั้ง 3 ช่องสัญญาณ และมีค่า Duty Cycle สำหรับสัญญาณ PWM[i], i=0,1,2 เป็น 0
          - เมื่อกดปุ่มใดๆ PB[i], i=0,1,2, แล้วปล่อยในแต่ละครั้ง จะเพิ่มค่า Duty Cycle ของสัญญาณ PWM สำหรับช่องสัญญาณ i ทีละ 10 แต่ถ้าถึง 100 จะกลับไปเริ่มต้นที 0 ใหม่
          - สัญญาณ PWM แต่ละช่อง ต้องมีความถี่เท่ากันและคงที่ และสามารถเลือกใช้ความถี่ได้ในช่วง 500Hz ถึง 1kHz
3) แนวทางการออกแบบและทดสอบ
          - ออกแบบวงจรโดยใช้ภาษา VHDL
          - เขียน VHDL Testbench เพื่อทดสอบการทำงาน และจำลองการทำงาน
          - ทดสอบการทำงานในบอร์ด FPGA แล้ววัดสัญญาณโดยใช้ออสซิลโลสโคป
(ไม่ต้องต่อวงจร RGB LED จริง)
          - บันทึกผลและเขียนรายงานการทดลอง
แนวทางการออกแบบ
สร้าง delay ปุ่มกดประมาณครึ่งวินาที แล้วจึงสั่งให้ทำงานโดยที่ clk ขอบขาขึ้นให้ ใช้ตัวนับ duty เพิ่มขึ้นทีละ 10% duty เรื่อยๆ เมื่อกดปุ่มแต่ละครั้ง
Code VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;


entity test is
          port(clk,RST_B:in std_logic ;
          PB : in std_logic_vector(2 downto 0);
          pwm:out std_logic_vector(2 downto 0));
end test;
architecture behavioral of test is
          type duty_array is array (0 to 2)of integer ;
          type duty_update_array is array (0 to 2 )of integer ;
          type count_botton_array is array (0 to 2) of integer ;
          signal count_freq : integer:=0;
          signal count_botton : count_botton_array :=(0,0,0);

          signal duty : duty_array := (0,0,0);
begin
process(clk)
begin
          if(RST_B='0')then --set to reset Asynchronus
                             duty <= (0,0,0);

          elsif rising_edge(clk)then
                             for i in 0 to 2 loop
                                      if (PB(i) = '0')then --botton delay
                                                          count_botton(i) <= count_botton(i)+1;         
                                      elsif(PB(i)='1')and count_botton(i)>100000 then
                                                          count_botton(i) <=0;  
                                                                   if(duty(i)<=100000)then
                   duty(i) <= duty(i)+10000;
--adding 10% of duty
           else    duty(i) <= 0;
          end if;
                  duty_update(i) <= duty(i); --update duty      
           end if;
          end loop;

if (count_freq < 100000) then --count_freq less than 100% duty
    count_freq <= count_freq+1;
                   else
                             count_freq <= 0;
                   end if;
          end if;
end process;
          pwm(0) <= '1' when duty_update(0) > count_freq
          else '0';
          pwm(1) <= '1' when duty_update(1) > count_freq
          else '0';
          pwm(2) <= '1' when duty_update(2) > count_freq
else '0';

Testbench
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.all;
entity tb_lab1 is
end tb_lab1;     
architecture testbench of tb_lab1 is
                component labb1
                                port(
                                                clk:in std_logic
                                                RST_B :in std_logic_vector(2 downto 0); --reset "000"
                                                PB : in std_logic_vector(2 downto 0);
                                                pwm : out std_logic_vector(2 downto 0)--output
                                );
                end component ;
                signal tb_clk  : std_logic;
                signal tb_reset  : std_logic_vector(2 downto 0) := ('0','0','0');
                signal tb_pb  : std_logic_vector(2 downto 0);
                signal tb_pwm  : std_logic_vector(2 downto 0);

                signal count  : integer range 0 to 7 := 0;
begin
                                DUT : labb1 port map(
                                clk=>tb_clk,RST_B=>tb_reset,PB=>tb_pb,pwm => tb_pwm
                                );
                                process
                                                constant period : TIME := 20 ns;
                                                begin
                                                tb_clk <= '1';
                                                wait for (period/2);
                                                tb_clk <= '0';
                                                wait for (period/2);                        
                                end process ;
                                process begin
                                                tb_reset <= '0';
                                                '1' after period;
                                                '0' after (period*2);
                                end process;
                                process begin
                                                tb_pb <= std_logic_vector(count,3);
                                                if count < 7 then
                                                                count <= count+1;
                                                else
                                                                count <= 0;
                                                end if;
                                                wait for 100000 s;
                                end process;

end testbench;


ผลการทดสอบโปรแกรมจากโปรแกรม model-sim

ผลการทดลอง

ภาพการทดลองตอนวัดคลื่นสัญญาณ


รูปคลื่นจากออสซิโลสโคป
  กด 1 ครั้ง duty เพิ่มขึ้นทีละ 10 % เป็น 10%

    กด 3 ครั้ง duty เพิ่มขึ้นทีละ 10 % เป็น 30%

  กด 8 ครั้ง duty เพิ่มขึ้นทีละ 10 % เป็น 80%



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

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