ออกแบบวงจรดิจิทัลสร้างสัญญาณ PWM ควบคุมการทำงานของ WS2812 RGB โดยใช้ภาษา VHDL
(Components)
วัตถุประสงค์
1.ศึกษาการทำงานของบอร์ด FPGA
2.สามารถออกแบบการทำงานของวงจรดิจิทัลโดยเขียนเป็นรุปแบบ component ได้
3.เข้าใจและสามารถอธิบายการทำงานของ code VHDL และการทำงานวงจรได้
อุปกรณ์
1.บอร์ด FPGA CYCLOne 3 ชิปหมายเลข EP3C10E144C8 1 บอร์ด
2. ออสซิโลสโคป 1 เครื่อง
3. สายไฟ
4. คอมพิวเตอร์ที่มีโปรแกรม Altera 10.1d (Quartus II 13.1)
5. WS2812 RGB LED
ข้อกำหนดในการทดลอง
จงออกแบบวงจรดิจิลัทโดยใช้ภาษา VHDL สำหรับนำไปสร้างเป็นวงจรในชิป FPGA โดยใช้บอร์ดที่มีอยู่ในห้องแล็ป วงจรดิจิทัลมี I/O ดังนี้
- CLK (input) มีความถี่ 50MHz ใช้สำหรับกำหนดจังหวะการทำงานของวงจรทั้งหมด (เป็นการออกแบบวงจรดิจิทัลแบบ Synchronous Design)
- RST_B (input) เป็นอินพุตสำหรับใช้รีเซตแบบ Asynchronous สำหรับการทำงานของวงจรโดยรวม (ทำงานแบบ Active-Low) ซึ่งได้จากวงจรปุ่มกด (Push Button)
- PB (input) เป็นอินพุตจากปุ่มกด 1 ปุ่ม ทำงานแบบ Active-low เพื่อใช้ในการเปลี่ยนสีของ WS2812 RGB LED จำนวน 1 ดวง
- DATA (output) เป็นเอาต์พุตสำหรับนำไปควบคุมการทำงานของ WS2812 RGB LED เพียง 1 ดวง ซึ่งเป็นสัญญาณตามข้อกำหนดของชิป WS2812 เพื่อส่งข้อมูลจำนวน 24 บิต พฤติกรรมการทำงานเป็นดังนี้- เมื่อเริ่มต้นหรือกดปุ่มรีเซต (RST_B) จะทำให้ค่าสีเป็น 0x000000 (24 บิต) และส่งออกไปยัง WS2812 RGB LED หนึ่งครั้ง- เมื่อมีการกดปุ่ม PB แล้วปล่อยในแต่ละครั้ง จะมีการเปลี่ยนค่าสี 24 บิต แล้วส่งออกไปยัง RGB LED ใหม่หนึ่งครั้ง ตามลำดับดังนี้ 0x000000 -> 0x0000FF -> 0x00FF00 -> 0xFF0000 แล้ววนซ้ำ
แนวทางการออกแบบ
ออกแบบวงจรโดยแยกเป็นแต่ละองค์ประกอบ ดังนี้
1. วงจรที่เป็นปุ่มกด
2. วงจรที่ใช้สร้างสัญญาณ
3. วงจรที่ใช้ในการเลื่อนสัญญาณ
4. วงจรที่ใช้ในการรวมแต่ละส่วนประกอบเข้าด้วยกัน
Code
component 1 (component_PB):
ประกาศ library ที่ใช้ในโปรแกรม
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
กำหนด input/output ที่ใช้ใน component ได้แก่ pb, clk , rst ,data_out
entity component_PB is
port(clk,RST_B:in std_logic ;
PB : in std_logic;
data_send: out std_logic
);
end component_PB;
กำหนดชนิดตัวแปรที่นำไปใช้
architecture behavioral of component_PB is
type state is(s0,s1,s2,s3);
signal state_pb :state := s0 ;
signal st_PB, count_botton, i,count_pwm: integer:=0;
signal duty : std_logic_vector(23 downto 0) := x"000000";
signal send_data : std_logic;
signal pwm : std_logic;
signal s : std_logic;
เริ่ม process โดย clk และ reset
begin
process(clk, RST_B)
begin
case state_pb is
when s0 =>
s <= '0';
when s1 => //state s1 ให้ check สถานะ ปุ่มกด และ ทำการตั้งค่าที่สถานะเริ่มต้น พร้อมทั้งให้มีการนับ delay เพื่อป้องกันการผิดพลาดของปุ่มกด
s <= '1';
if (PB = '0')then --botton delay
send_data <= '0';
state_pb <= s1;
elsif(PB ='1')and (s = '1') then -- s= state
send_data <= '1';
state_pb <= s0;
end if;
end case;
end process;
data_send <= send_data;
end behavioral;
--------------------------------------------------------------------------------------------------------
component 2 (component_Data):
ประกาศ library ที่ใช้ในโปรแกรม
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
กำหนด input/output ที่ใช้ในการกำหนดค่าให้ Data ได้แก่ pb, clk , rst ,duty,data
entity component_Data is
port(clk,RST_B:in std_logic ;
duty : in std_logic_vector(23 downto 0);
Data: out std_logic
);
end component_Data;
architecture behavioral of component_Data is
type state is(s0,s1,s2,s3);
signal statecheck :state := s0 ;
signal count_freq, count_botton, i,count_pwm: integer:=0;
--signal duty : std_logic_vector(23 downto 0) := x"000000";
signal cheak : std_logic;
signal pwm : std_logic;
ให้การทำงานโดยมีการทำงานขึ้นอยู่กับการทำงานของ clk
begin
process(clk, RST_B)
begin
if(RST_B='0')then --set to reset Asynchronus
statecheck <= s0;
i<=1;
elsif rising_edge(clk)then
count_pwm<=count_pwm+1;
--check state
เป็นการกำหนดค่า data 24 bit
case statecheck is
when s0 => --check data
if i=24 then
statecheck <= s3;
else
if duty(i)='0' then -- logic '1'
statecheck <=s1;
else -- logic '0'
statecheck <=s2;
end if;
end if;
when s1 => -- output 40 + 18
if (count_pwm < 58) then--count_pwm <= count_pwm + 1;
Data<='1';
if(count_pwm >18)then
Data <= '0';
end if;
count_pwm <= count_pwm + 1;
else
i <= i+1;
count_pwm <= 0;
statecheck <= s0;
end if ;
when s2 => output 30+35
if (count_pwm < 65)then
Data <= '0';
if(count_pwm > 35)then
Data<='1';
end if ;
else
i <= i+1;
count_pwm <=0;
statecheck <= s0;
end if;
when s3 =>
if(count_pwm > 10000)then
statecheck <= s0;
count_pwm <= 0;
i<= 0;
else
count_pwm <= count_pwm+1;
Data <= '0';
end if;
end case;
end if;
end process;
end behavioral;
--------------------------------------------------------------------------------------------------------
component 3 (component_Shift):
ประกาศ library ที่ต้องการใช้
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity component_Shift is
port(clk,RST_B:in std_logic ;
data_pb : in std_logic;
signal_out : out std_logic_vector(23 downto 0)
);
end component_Shift;
architecture behavioral of component_Shift is
type state is(s0,s1,s2,s3);
signal shift_data :state := s0 ;
signal count_freq, count_botton, i,count_pwm,t: integer:=0;
signal duty : std_logic_vector(23 downto 0) := x"000000";
signal cheak : std_logic;
signal pwm : std_logic;
กำหนดค่าเมื่อ shift bit
begin
process(clk, RST_B)
begin
if(RST_B = '0')then
duty <=x"000000";
shift_data <= s0;
elsif rising_edge(clk) then
case shift_data is
when s0 =>
duty <=x"000000";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s1;
t <= 0;
end if;
when s1 =>
duty <=x"0000FF";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s2;
t <= 0;
end if;
when s2 =>
duty <=x"00FF00";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s3;
t <= 0;
end if;
when s3 =>
duty<=x"FF0000";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s0;
t <= 0;
end if;
end case;
end if ;
end process;
signal_out <= duty;
end behavioral;
--------------------------------------------------------------------------------------------------------
component 4 (component_lab3):
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity component_lab3 is
port(clk,RST_B:in std_logic ;
PB : in std_logic;
Data: out std_logic
);
end component_lab3;
architecture structural of component_lab3 is
component component_PB
port(
clk : in std_logic;
PB : in std_logic;
--Data : out std_logic;
data_send : out std_logic
);
end component;
component component_Shift
port(
clk,RST_B : in std_logic;
data_pb : in std_logic;
--Data : out std_logic;
signal_out : out std_logic_vector(23 downto 0)
);
end component;
component component_Data
port(
clk,RST_B:in std_logic ;
duty : in std_logic_vector(23 downto 0);
Data: out std_logic
);
end component;
signal p_data_out_24: std_logic_vector(23 downto 0); -- component Component_DATA is
signal p_signal_out: std_logic;
begin
cmp1_inst: component_PB
port map(clk => clk, PB => PB,data_send => p_signal_out);
--end generate;
cmp2_inst: component_Shift
port map(clk => clk, RST_B => RST_B , data_pb => p_signal_out , signal_out => p_data_out_24 );
cmp3_inst: component_Data
port map(clk => clk, RST_B => RST_B,duty => p_data_out_24, data => data);
end structural;
4. คอมพิวเตอร์ที่มีโปรแกรม Altera 10.1d (Quartus II 13.1)
5. WS2812 RGB LED
จงออกแบบวงจรดิจิลัทโดยใช้ภาษา VHDL สำหรับนำไปสร้างเป็นวงจรในชิป FPGA โดยใช้บอร์ดที่มีอยู่ในห้องแล็ป วงจรดิจิทัลมี I/O ดังนี้
- CLK (input) มีความถี่ 50MHz ใช้สำหรับกำหนดจังหวะการทำงานของวงจรทั้งหมด (เป็นการออกแบบวงจรดิจิทัลแบบ Synchronous Design)
- RST_B (input) เป็นอินพุตสำหรับใช้รีเซตแบบ Asynchronous สำหรับการทำงานของวงจรโดยรวม (ทำงานแบบ Active-Low) ซึ่งได้จากวงจรปุ่มกด (Push Button)
- PB (input) เป็นอินพุตจากปุ่มกด 1 ปุ่ม ทำงานแบบ Active-low เพื่อใช้ในการเปลี่ยนสีของ WS2812 RGB LED จำนวน 1 ดวง
- DATA (output) เป็นเอาต์พุตสำหรับนำไปควบคุมการทำงานของ WS2812 RGB LED เพียง 1 ดวง ซึ่งเป็นสัญญาณตามข้อกำหนดของชิป WS2812 เพื่อส่งข้อมูลจำนวน 24 บิต พฤติกรรมการทำงานเป็นดังนี้- เมื่อเริ่มต้นหรือกดปุ่มรีเซต (RST_B) จะทำให้ค่าสีเป็น 0x000000 (24 บิต) และส่งออกไปยัง WS2812 RGB LED หนึ่งครั้ง- เมื่อมีการกดปุ่ม PB แล้วปล่อยในแต่ละครั้ง จะมีการเปลี่ยนค่าสี 24 บิต แล้วส่งออกไปยัง RGB LED ใหม่หนึ่งครั้ง ตามลำดับดังนี้ 0x000000 -> 0x0000FF -> 0x00FF00 -> 0xFF0000 แล้ววนซ้ำ
- RST_B (input) เป็นอินพุตสำหรับใช้รีเซตแบบ Asynchronous สำหรับการทำงานของวงจรโดยรวม (ทำงานแบบ Active-Low) ซึ่งได้จากวงจรปุ่มกด (Push Button)
- PB (input) เป็นอินพุตจากปุ่มกด 1 ปุ่ม ทำงานแบบ Active-low เพื่อใช้ในการเปลี่ยนสีของ WS2812 RGB LED จำนวน 1 ดวง
- DATA (output) เป็นเอาต์พุตสำหรับนำไปควบคุมการทำงานของ WS2812 RGB LED เพียง 1 ดวง ซึ่งเป็นสัญญาณตามข้อกำหนดของชิป WS2812 เพื่อส่งข้อมูลจำนวน 24 บิต พฤติกรรมการทำงานเป็นดังนี้- เมื่อเริ่มต้นหรือกดปุ่มรีเซต (RST_B) จะทำให้ค่าสีเป็น 0x000000 (24 บิต) และส่งออกไปยัง WS2812 RGB LED หนึ่งครั้ง- เมื่อมีการกดปุ่ม PB แล้วปล่อยในแต่ละครั้ง จะมีการเปลี่ยนค่าสี 24 บิต แล้วส่งออกไปยัง RGB LED ใหม่หนึ่งครั้ง ตามลำดับดังนี้ 0x000000 -> 0x0000FF -> 0x00FF00 -> 0xFF0000 แล้ววนซ้ำ
1. วงจรที่เป็นปุ่มกด
2. วงจรที่ใช้สร้างสัญญาณ
3. วงจรที่ใช้ในการเลื่อนสัญญาณ
4. วงจรที่ใช้ในการรวมแต่ละส่วนประกอบเข้าด้วยกัน
Code
ประกาศ library ที่ใช้ในโปรแกรม
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
กำหนด input/output ที่ใช้ใน component ได้แก่ pb, clk , rst ,data_out
entity component_PB is
port(clk,RST_B:in std_logic ;
PB : in std_logic;
data_send: out std_logic
);
end component_PB;
กำหนดชนิดตัวแปรที่นำไปใช้
architecture behavioral of component_PB is
type state is(s0,s1,s2,s3);
signal state_pb :state := s0 ;
signal st_PB, count_botton, i,count_pwm: integer:=0;
signal duty : std_logic_vector(23 downto 0) := x"000000";
signal send_data : std_logic;
signal pwm : std_logic;
signal s : std_logic;
เริ่ม process โดย clk และ reset
begin
process(clk, RST_B)
begin
case state_pb is
when s0 =>
s <= '0';
when s1 => //state s1 ให้ check สถานะ ปุ่มกด และ ทำการตั้งค่าที่สถานะเริ่มต้น พร้อมทั้งให้มีการนับ delay เพื่อป้องกันการผิดพลาดของปุ่มกด
s <= '1';
if (PB = '0')then --botton delay
send_data <= '0';
state_pb <= s1;
elsif(PB ='1')and (s = '1') then -- s= state
send_data <= '1';
state_pb <= s0;
end if;
end case;
end process;
data_send <= send_data;
end behavioral;
--------------------------------------------------------------------------------------------------------
component 2 (component_Data):
ประกาศ library ที่ใช้ในโปรแกรม
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.numeric_std.all;
กำหนด input/output ที่ใช้ในการกำหนดค่าให้ Data ได้แก่ pb, clk , rst ,duty,data entity component_Data is port(clk,RST_B:in std_logic ; duty : in std_logic_vector(23 downto 0); Data: out std_logic ); end component_Data; architecture behavioral of component_Data is type state is(s0,s1,s2,s3); signal statecheck :state := s0 ; signal count_freq, count_botton, i,count_pwm: integer:=0; --signal duty : std_logic_vector(23 downto 0) := x"000000"; signal cheak : std_logic; signal pwm : std_logic;
ให้การทำงานโดยมีการทำงานขึ้นอยู่กับการทำงานของ clk begin process(clk, RST_B) begin if(RST_B='0')then --set to reset Asynchronus statecheck <= s0; i<=1; elsif rising_edge(clk)then count_pwm<=count_pwm+1; --check state
เป็นการกำหนดค่า data 24 bit case statecheck is when s0 => --check data if i=24 then statecheck <= s3; else if duty(i)='0' then -- logic '1' statecheck <=s1; else -- logic '0' statecheck <=s2; end if; end if; when s1 => -- output 40 + 18 if (count_pwm < 58) then--count_pwm <= count_pwm + 1; Data<='1'; if(count_pwm >18)then Data <= '0'; end if; count_pwm <= count_pwm + 1; else i <= i+1; count_pwm <= 0; statecheck <= s0; end if ; when s2 => output 30+35 if (count_pwm < 65)then Data <= '0'; if(count_pwm > 35)then Data<='1'; end if ; else i <= i+1; count_pwm <=0; statecheck <= s0; end if; when s3 => if(count_pwm > 10000)then statecheck <= s0; count_pwm <= 0; i<= 0; else count_pwm <= count_pwm+1; Data <= '0'; end if; end case; end if; end process; end behavioral;
--------------------------------------------------------------------------------------------------------
component 3 (component_Shift): ประกาศ library ที่ต้องการใช้
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity component_Shift is
port(clk,RST_B:in std_logic ;
data_pb : in std_logic;
signal_out : out std_logic_vector(23 downto 0)
);
end component_Shift;
architecture behavioral of component_Shift is
type state is(s0,s1,s2,s3);
signal shift_data :state := s0 ;
signal count_freq, count_botton, i,count_pwm,t: integer:=0;
signal duty : std_logic_vector(23 downto 0) := x"000000";
signal cheak : std_logic;
signal pwm : std_logic;
กำหนดค่าเมื่อ shift bit
begin
process(clk, RST_B)
begin
if(RST_B = '0')then
duty <=x"000000";
shift_data <= s0;
elsif rising_edge(clk) then
case shift_data is
when s0 =>
duty <=x"000000";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s1;
t <= 0;
end if;
when s1 =>
duty <=x"0000FF";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s2;
t <= 0;
end if;
when s2 =>
duty <=x"00FF00";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s3;
t <= 0;
end if;
when s3 =>
duty<=x"FF0000";
t <= t+1;
if(data_pb = '1' and t = 1)then--?? ?????? state
shift_data <=s0;
t <= 0;
end if;
end case;
end if ;
end process;
signal_out <= duty;
end behavioral;
--------------------------------------------------------------------------------------------------------
component 4 (component_lab3):
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.numeric_std.all; entity component_lab3 is port(clk,RST_B:in std_logic ; PB : in std_logic; Data: out std_logic ); end component_lab3; architecture structural of component_lab3 is component component_PB port( clk : in std_logic; PB : in std_logic; --Data : out std_logic; data_send : out std_logic ); end component; component component_Shift port( clk,RST_B : in std_logic; data_pb : in std_logic; --Data : out std_logic; signal_out : out std_logic_vector(23 downto 0) ); end component; component component_Data port( clk,RST_B:in std_logic ; duty : in std_logic_vector(23 downto 0); Data: out std_logic ); end component; signal p_data_out_24: std_logic_vector(23 downto 0); -- component Component_DATA is signal p_signal_out: std_logic; begin cmp1_inst: component_PB port map(clk => clk, PB => PB,data_send => p_signal_out); --end generate; cmp2_inst: component_Shift port map(clk => clk, RST_B => RST_B , data_pb => p_signal_out , signal_out => p_data_out_24 ); cmp3_inst: component_Data port map(clk => clk, RST_B => RST_B,duty => p_data_out_24, data => data); end structural;







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