การทดลองที่ 2 ออกแบบวงจรดิจิทัล
สร้างสัญญาณ PWM ควบคุมการทำงานของ WS2812 RGB LED โดยใช้ภาษา VHDL
รายการอุปกรณ์
1. บอร์ด Altera FPGA (WARRIOR CYCLONE3 DEV) ชิปหมายเลข EP3C10E144C8 1 บอร์ด
2. สายดาวน์โหลด ByteBlaster II Cable หรือ สายดาวน์โหลดUSB Blaster Cable 1 ชุด
3. เครื่องคอมพิวเตอร์ 1 ชุด
4. ออสซิลโลสโคป 1 เครื่อง
5. สายวัด Logic Analyzer 1 เส้น
6. WS2812 RGB LED 1 ดวง
วิธีการทดลอง
จงออกแบบวงจรดิจิลัทโดยใช้ภาษา 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 แล้ววนซ้ำ
แนวทางการออกแบบและทดสอบ
- ออกแบบวงจรโดยใช้ภาษา VHDL
- เขียน VHDL Testbench เพื่อทดสอบการทำงาน และจำลองการทำงาน
- ทดสอบการทำงานในบอร์ด FPGA แล้ววัดสัญญาณโดยใช้ออสซิลโลสโคป
(ยังไม่ต้องต่อวงจร RGB LED จริง)
รูปแผนภาพ Block Diagram การทำงานของวงจร
โค้ดวงจรดิจิทัลภาษา VHDL
library ieee;
library work;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity shiftbit is
generic (
PWM0H: integer:= 18;
PWM0L: integer:= 39;
PWM1H: integer:= 35;
PWM1L: integer:= 30;
RES: integer:= 400
);
port(
clk, rst_b, pb : in std_logic;
data : out std_logic
);
end shiftbit;
architecture behave of shiftbit is
signal RGBbit : std_logic_vector(23 downto 0):= x"000000";
signal ti,index, count : integer:= 0;
signal check : std_logic := '0';
type state_type is (S0,S1,S2,S3);
signal state : state_type := S0;
begin
process(clk, rst_b) begin
if rst_b = '0' then
RGBbit <= x"000000";
end if;
if rising_edge(clk) then
case state is
when S0 =>
state <= S1;
if pb = '1' and ti > 1000 then
ti <= 0;
if RGBbit = x"000000" then
RGBbit <= x"0000FF";
elsif RGBbit = x"0000FF" then
RGBbit <= x"00FF00";
elsif RGBbit = x"00FF00" then
RGBbit <= x"FF0000";
elsif RGBbit = x"FF0000" then
RGBbit <= x"000000";
end if;
elsif pb = '0' then
ti <= ti+1;
end if;
when S1 =>
if RGBbit(index) = '0' then
if count < PWM0H then
data <= '1';
count <= count + 1;
elsif count < PWM0H+PWM0L then
data <= '0';
count <= count + 1;
else
if index < 23 then
index <= index + 1;
count <= 0;
end if;
end if;
state <= S3;
else
state <= S2;
end if;
when S2 =>
if RGBbit(index) = '1' then
if count < PWM1H then
data <= '1';
count <= count + 1;
elsif count < PWM1H+PWM1L then
data <= '0';
count <= count + 1;
else
if index < 23 then
index <= index + 1;
count <= 0;
end if;
end if;
end if;
state <= S3;
when S3 =>
if index = 23 then
if count > RES then
count <= 0;
index <= 0;
else
count <= count + 1;
end if;
end if;
state <= S0;
when others =>
state <= S0;
end case;
end if;
end process;
end behave;
|
โค้ด Testbench วงจร
library ieee;
library work;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity TB_shiftbit is
end TB_shiftbit;
architecture testbench of TB_shiftbit is
component shiftbit is
generic (
PWM0H: integer:= 18;
PWM0L: integer:= 39;
PWM1H: integer:= 35;
PWM1L: integer:= 30;
RES: integer:= 400
);
port(
clk, rst_b, pb : in std_logic;
data : out std_logic
);
end component;
constant PWM0H: integer:= 18;
constant PWM0L: integer:= 39;
constant PWM1H: integer:= 35;
constant PWM1L: integer:= 30;
constant RES: integer:= 400;
signal t_clk,t_rst_b,t_data,t_pb : std_logic;
begin
DUT: shiftbit
generic map(PWM0H => PWM0H, PWM0L => PWM0L,PWM1H => PWM1H,PWM1L => PWM1L, RES => RES)
port map(clk => t_clk, rst_b => t_rst_b, data => t_data ,pb => t_pb );
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 UP input signal
t_pb <= '1' ;wait for 4 ms;
t_pb <= '0' ;wait for 1 ms;
t_pb <= '1' ;wait for 4 ms;
t_pb <= '0' ;wait for 1 ms;
end process;
process begin
t_rst_b <= '1';
wait for 7 ms;t_rst_b <= '0';
wait for 5 ms;t_rst_b <= '1';
wait;
end process;
end testbench;
|
โค้ด component_button
library ieee;
library work;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity component_button is
port(
CLK, PB : in std_logic;
signal_out : out std_logic
);
end component_button;
architecture Behavior of component_button is
signal count: integer:=0;
signal check,signal_sent: std_logic:='0';
begin
process (CLK, PB) begin
if rising_edge(CLK) then
if(PB = '1')then
count <= 0;
signal_sent <= '0';
else
count <= count + 1;
end if;
if(count > 20000)then
check <= '1';
end if;
if(PB = '1')and(check = '1')then
signal_sent <= '1';
check <= '0';
end if;
end if;
end process;
signal_out <= signal_sent;
end Behavior;
|
โค้ด component_Data
library ieee;
library work;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity component_Data is
port(
CLK : in std_logic;
RGBbit : in std_logic_vector (23 downto 0) := x"000000";
data_out : out std_logic
);
end component_Data;
architecture Behavior of component_Data is
signal count,index: integer:=0;
signal datacheck: std_logic_vector(23 downto 0):=x"000000";
signal data,check: std_logic:='0';
begin
process (CLK) begin
if rising_edge(CLK) then
if index = 24 then
if count > 4000 then
count <= 0;
index <= 0;
else
count <= count + 1;
end if;
else
if RGBbit(index) = '0' then
if count < 18 then
data <= '1';
count <= count + 1;
elsif count < 47 then
data <= '0';
count <= count + 1;
else
index <= index + 1;
count <= 0;
end if;
else
if count < 35 then
data <= '1';
count <= count + 1;
elsif count < 65 then
data <= '0';
count <= count + 1;
else
index <= index + 1;
count <= 0;
end if;
end if;
end if;
end if;
end process;
data_out <= data;
end Behavior;
|
โค้ด component_fsm
library ieee;
library work;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity component_fsm is
port(
CLK,input_data,input_reset : in std_logic;
data_out : out std_logic_vector(23 downto 0)
);
end component_fsm;
architecture Behavior of component_fsm is
type state_type is (S0,S1,S2,S3);
signal state : state_type :=S0;
signal data_t: std_logic_vector(23 downto 0):=x"000000";
signal signal_t : std_logic:= '0';
begin
process (CLK, input_data,input_reset) begin
if input_reset = '0' then
state <= S0;
data_t <= x"000000";
elsif rising_edge(CLK) then
case state is
when S0 =>
data_t <= x"000000";
if input_data = '1' then
state <= S1;
elsif input_data = '0' then
state <= S0;
end if;
when S1 =>
data_t <= x"0000FF";
if input_data = '1' then
state <= S2;
elsif input_data = '0' then
state <= S1;
end if;
when S2 =>
data_t <= x"00FF00";
if input_data = '1' then
state <= S3;
elsif input_data = '0' then
state <= S2;
end if;
when S3 =>
data_t <= x"FF0000";
if input_data = '1' then
state <= S0;
elsif input_data = '0'then
state <= S3;
end if;
end case;
end if;
end process;
data_out <= data_t;
end Behavior;
|
โค้ด เรียกใช้ component ทั้งหมด
library ieee;
library work;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity componentwork2 is
port(
CLK,PB,RESET : in std_logic;
Data : out std_logic
);
end componentwork2;
architecture structural of componentwork2 is
component component_button
port(
CLK, PB : in std_logic;
signal_out : out std_logic
);
end component;
component component_fsm
port(
CLK,input_data,input_reset : in std_logic;
data_out : out std_logic_vector(23 downto 0)
);
end component;
component component_Data is
port(
CLK : in std_logic;
RGBbit : in std_logic_vector (23 downto 0) := x"000000";
data_out : out std_logic
);
end component;
signal dataout24: std_logic_vector(23 downto 0);
signal signal_out: std_logic;
begin
cmp1_inst: component_button
port map(CLK => CLK, PB => PB, signal_out => signal_out);
cmp2_inst: component_fsm
port map(CLK => CLK, input_reset => RESET, input_data => signal_out, data_out => dataout24);
cmp3_inst: component_Data
port map(CLK => CLK, RGBbit => dataout24, data_out => Data);
end structural;
|
ผลการทดลอง
ผลการสังเคราะห์VHDL เป็นวงจรในชิปและการใช้ทรัพยากรของบอร์ด FPGA
ผลการจำลองการทำงานด้วย Modelsim
สัญญาณ 0x000000
สัญญาณ 0x0000FF
สัญญาณ 0x00FF00
สัญญาณ 0xFF0000

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