วัตถุประสงค์การทดลอง
1.สามารถใช้ภาษา VHDL
ในการออกแบบการสร้างสัญญาณ PWM โดยเปลี่ยนค่าตามปุ่มกดได้
2.สามารถใช้งาน
ออสซิลโลสโคป ในการวัดสัญญาณเอาต์พุต จากบอร์ด FPGA
รายการอุปกรณ์
1.บอร์ด FPGA 1 บอร์ด
2.โปรแกรม Quartus
II
วิธีการทดลอง
1. ออกแบบวงจรดิจิทัลโดยใช้ภาษา
VHDL สำหรับบอร์ด FPGA ที่ทำงานได้ตามข้อกำหนดต่อไป
- มีอินพุต CLK ความถี่ 50MHz
- มีอินพุต nRESET ทำงานแบบ active-low (ได้จากวงจรปุ่มกด) ไว้สำหรับรีเซตการทำงานของวงจร
- มีอินพุตจากวงจรปุ่มกด PB ทำงานแบบ active-low
- มีเอาต์พุต PWM
- สร้างสัญญาณ PWM ออกที่ขา PWM ซึ่งมีความถี่ 500Hz คงที่ เริ่มต้นมีค่า Duty Cycle 0%
- เมื่อกดปุ่ม PB แล้วปล่อยหนึ่งครั้ง จะทำให้ค่า Duty Cycle เพิ่มขึ้นทีละ 5%
ถ้า Duty Cycle เท่ากับ 100% ต่อไปให้วนกลับไปเริ่มที่ 0%
2. ทดสอบและวัดสัญญาณเอาต์พุตด้วยออสซิลโลสโคป
3.เขียนรายงานการทดลอง- มีอินพุต CLK ความถี่ 50MHz
- มีอินพุต nRESET ทำงานแบบ active-low (ได้จากวงจรปุ่มกด) ไว้สำหรับรีเซตการทำงานของวงจร
- มีอินพุตจากวงจรปุ่มกด PB ทำงานแบบ active-low
- มีเอาต์พุต PWM
- สร้างสัญญาณ PWM ออกที่ขา PWM ซึ่งมีความถี่ 500Hz คงที่ เริ่มต้นมีค่า Duty Cycle 0%
- เมื่อกดปุ่ม PB แล้วปล่อยหนึ่งครั้ง จะทำให้ค่า Duty Cycle เพิ่มขึ้นทีละ 5%
ถ้า Duty Cycle เท่ากับ 100% ต่อไปให้วนกลับไปเริ่มที่ 0%
2. ทดสอบและวัดสัญญาณเอาต์พุตด้วยออสซิลโลสโคป
ผลการทดลอง
VHDL CODE
--
File: duty_pwm.vhd
--
Target Board: Cyclone III,EP3C10E144C8
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity duty_pwm is
generic (
PERIOD : integer := 100; -- count period for PWM
STEP
: integer := 5 --increment
step for duty cycle
);
port(--ใช้กำหนดขาหรือสัญญาณ
CLK
: in std_logic;
nRESET : in std_logic;
PB
: in std_logic;
Q
: out std_logic );
end duty_pwm;
--เป็นส่วนที่ใช้สำหรับบรรยายถึงฟังก์ชันการทำงานของ duty_pwm
architecture behave of
duty_pwm is
signal duty_cycle, new_duty_cycle :
integer range 0 to (PERIOD+ STEP) := 0; --ประกาศตัวแปร ชนิด signal ขนาด
PERIOD+ STEP เริ่มต้นที่ 0
signal cnt : integer range 0 to (PERIOD-1) := 0; --ประกาศตัวแปร
ชนิด signal ขนาด PERIOD-1 เริ่มต้นที่ 0
signal ff : std_logic;
signal D : std_logic;
begin
process (CLK)
Variable count : Integer range 0 to 50000 := 0; --ประกาศ Variable ชื่อ count ชนิด integer ขนาด0 ถึง 50000
เริ่มต้นที่ 0
begin
if nRESET = '0' then --active low ค่า reset เป็น 0
new_duty_cycle <= 0; --ให้ค่า duty
cycle เป็น 0(reset ค่า)
elsif rising_edge(CLK) then --หากค่า reset เป็น 1 และเป็นสัญญาณขอบขาขึ้นของ
clk
if count = 50000 then –-ใช้เงื่อนไขถ้า count = 50000
if PB = '1' then -- แล้วปุ่มกดมีสถานะเป็น
1
D <= PB; -- นำค่า PB ไป assignment
ให้ D
end if; -- จบเงื่อนไข PB = 1
elsif PB = '0' then --หากค่า PB เป็น 0 ให้ นำค่า PB มาเทียบกับ D ถ้าต่างกัน
ff <= (PB xor
D);
--นำค่า ไป assignment ให้ ff
if ff = '1' then --ถ้า ff มีค่าเป็น 1 ก็ มาเช็คว่า
if (new_duty_cycle+ STEP) >
PERIOD then -–ค่า duty cycle
มากกว่า period หรือไม่
new_duty_cycle <= 0;--ถ้ามากกว่า ให้ ค่า
duty
เป็น 0
else --ถ้าไม่ใช่
new_duty_cycle <=
new_duty_cycle + STEP; --increment duty cycle
end if; --จบเงื่อนไข กำหนด ค่า
duty
cycle
count := 0; --ให้ count เป็น 0
end if; --จบเงื่อนไข ff = 1
D <= PB; --นำค่า PB ที่เท่ากับ 0ไปเก็บ ใน ตัวแปร D
end if;
count :=count +1; --กำหนดให้ค่า count เพิ่มทีละ 1;
end if; --จบเงื่อนไข nRESET
end process; --จบ process
process (CLK) begin
if rising_edge(CLK) and nRESET = '1' then –-ทำงานที่ขอบขาขึ้นของ clk และ ค่า reset เป็น 1
if cnt = (PERIOD-1) then --ถ้า ค่า cnt เท่ากับ ค่าคาบลบ 1
cnt <= 0; --ให้ cnt เป็น 0(reset ค่า)
duty_cycle <= new_duty_cycle; --update
duty cycle
else
--ถ้าไม่ใช่ ค่า cnt น้อยกว่า ค่าคาบลบ 1
cnt <= cnt + 1; --ให้ค่า cnt บวกทีละ 1
end if; --จบเงื่อนไข cnt
end if; --จบเงื่อนไขขอบขาขึ้น
clk
end process; --จบ process
Q <= '1' when (cnt < duty_cycle) else '0'; --ถ้าค่า cnt น้อยกว่า ค่า duty cycle ให้ เอาต์พุตเป็น 1 ถ้าไม่ใช่เป็น 0
end behave;
---------------------------------------------------------------------
|
-- File: tb_pwm_duty.vhd
library
ieee;
use
ieee.std_logic_1164.all;
use
ieee.numeric_std.all;
entity
tb_pwm_duty is
-- no ports
end
tb_pwm_duty;
architecture
testbench of tb_pwm_duty is
component duty_pwm is
generic ( PERIOD : integer := 100; STEP :
integer := 5 );
port(
CLK : in std_logic;
nRESET
: in std_logic;
PB
: in std_logic;
Q
: out std_logic );
end component;
constant PERIOD : integer := 20;
constant STEP : integer := 1;
constant CLK_PERIOD : time := 20 ns;
signal t_CLK, t_nReset, t_PB, t_Q :
std_logic;
begin
DUT: duty_pwm
generic map( PERIOD => PERIOD, STEP
=> STEP )
port map (CLK => t_CLK, nRESET =>
t_nReset, PB => t_PB, Q => t_Q );
process begin -- a process for generating
the clock signal (50MHz)
t_CLK <= '1'; wait for 10 ns;
t_CLK <= '0'; wait for 10 ns;
end process;
process begin -- a process for generating
the nReset input signal
t_nReset <= '1';
wait until rising_edge(t_CLK);
t_nReset <= '0';
for i in 1 to 9 loop
wait until rising_edge(t_CLK);
end loop;
end process;
process begin -- a process for generating
the PB input signal
t_PB <= '0'; wait for 100 ns;
for i in 0 to 100 loop
wait until rising_edge(t_CLK);
t_PB <= '1';
wait until rising_edge(t_CLK);
t_PB <= '0';
wait for (((i*3+7) mod 53) +
10*PERIOD)*CLK_PERIOD;
end loop;
wait; -- wait forever
end process;
end testbench;
-------------------------------------------------------------------
|
ผลการ จำลองการทำงานโดยใช้โปรแกรม ModelSim-AlteraStarter Edition
ผลที่ได้คือ เมื่อ กดปล่อย ปุ่ม PB ครั้ง ค่า
duty cycle จะเพิ่มขึ้นทีละ 5 % เมื่อค่า duty cycle เท่ากับ 100
%จะวนกลับไปเริ่มที่
0
- กำหนด clk มีคาบเวลาเท่ากับ
20
ns และ PB เปลี่ยนจาก
0
เป็น 1 มีคาบเวลา 2us
วิดีโอผลการทดลอง
:
ไม่มีความคิดเห็น:
แสดงความคิดเห็น