วันอาทิตย์ที่ 5 เมษายน พ.ศ. 2558

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


การทดลองที่ 6
การใช้ IP core สำหรับ 16x2 LCD เพื่อแสดงข้อความ "Hello World!"

วัตถุประสงค์
1.เพื่อเพิ่มความเข้าใจเกี่ยวกับการแสดงผลบน LCD 16x2 บน FPGA มากขึ้น
2.สามารถเขียน code VHDL สั่งงานให้ข้อความที่กำหนดไปแสดงผลบนจอได้อย่างถูกต้อง
3.สามารถประยุกต์ความรู้ที่ได้เข้ากับวงจรอื่นๆได้อย่างเหมาะสม

โจทย์การทดลอง
เขียน VHDL เพื่อสั่งงานวงจรให้แสดงข้อความ "Hello World" บน 16x2 LCD ผ่านทาง IP Core

อุปกรณ์
1.บอร์ด FPGA CYCLOne 3 ชิปหมายเลข EP3C10E144C8 1 บอร์ด




2. ออสซิโลสโคป 1 เครื่อง




3. สายไฟ

4. คอมพิวเตอร์ที่มีโปรแกรม Altera 10.1d (Quartus II 13.1)


โค้ดการทดลอง
library ieee;
use ieee.std_logic_1164.all;

entity lcd16x2_ctrl_demo is
  port (
    clk    : in  std_logic;
    lcd_e  : out std_logic;
    lcd_rs : out std_logic;
    lcd_rw : out std_logic;
    lcd_db : out std_logic_vector(7 downto 4));
end entity lcd16x2_ctrl_demo;

architecture behavior of lcd16x2_ctrl_demo is
  signal timer : natural range 0 to 100000000 := 0;
  signal switch_lines : std_logic := '0';
  signal line1 : std_logic_vector(127 downto 0);
  signal line2 : std_logic_vector(127 downto 0);

  constant CLK_PERIOD_NS : positive := 10;  -- 100 Mhz

  signal rst          : std_logic;
  signal line1_buffer : std_logic_vector(127 downto 0);
  signal line2_buffer : std_logic_vector(127 downto 0);
begin
  DUT : entity work.lcd16x2_ctrl
    generic map (
      CLK_PERIOD_NS => CLK_PERIOD_NS)
    port map (
      clk          => clk,
      rst          => rst,
      lcd_e        => lcd_e,
      lcd_rs       => lcd_rs,
      lcd_rw       => lcd_rw,
      lcd_db       => lcd_db,
      line1_buffer => line1_buffer,
      line2_buffer => line2_buffer);

  rst <= '0';

  -- see the display's datasheet for the character map
  line1(127 downto 120) <= X"20";
  line1(119 downto 112) <= X"20";
  line1(111 downto 104) <= X"48";  -- H
  line1(103 downto 96)  <= X"65";  -- e
  line1(95 downto 88)   <= X"6c";  -- l
  line1(87 downto 80)   <= X"6c";  -- l
  line1(79 downto 72)   <= X"6f";  -- o
  line1(71 downto 64)   <= X"20";
  line1(63 downto 56)   <= X"57";  -- W
  line1(55 downto 48)   <= X"6f";  -- o
  line1(47 downto 40)   <= X"72";  -- r
  line1(39 downto 32)   <= X"6c";  -- l
  line1(31 downto 24)   <= X"64";  -- d
  line1(23 downto 16)   <= X"21";  -- !
  line1(15 downto 8)    <= X"20";
  line1(7 downto 0)     <= X"20";

  line2(127 downto 120) <= X"30";
  line2(119 downto 112) <= X"31";
  line2(111 downto 104) <= X"32";
  line2(103 downto 96)  <= X"33";
  line2(95 downto 88)   <= X"34";
  line2(87 downto 80)   <= X"35";
  line2(79 downto 72)   <= X"36";
  line2(71 downto 64)   <= X"37";
  line2(63 downto 56)   <= X"38";
  line2(55 downto 48)   <= X"39";
  line2(47 downto 40)   <= X"3a";
  line2(39 downto 32)   <= X"3b";
  line2(31 downto 24)   <= X"3c";
  line2(23 downto 16)   <= X"3d";
  line2(15 downto 8)    <= X"3e";
  line2(7 downto 0)     <= X"3f";

  line1_buffer <= line2 when switch_lines = '1' else line1;
  line2_buffer <= line1 when switch_lines = '1' else line2;

  -- switch lines every second
  process(clk)
  begin
    if rising_edge(clk) then
      if timer = 0 then
        timer <= 100000000;
        switch_lines <= not switch_lines;
      else
        timer <= timer - 1;
      end if;
    end if;
   
  end process;
end architecture behavior;





Test Bench

library ieee;
use ieee.std_logic_1164.all;

entity lcd16x2_ctrl_tb is
end entity lcd16x2_ctrl_tb;

architecture behavior of lcd16x2_ctrl_tb is
  constant CLK_PERIOD_NS : positive := 20;

  signal clk          : std_logic := '1';
  signal rst          : std_logic;
  signal lcd_e        : std_logic;
  signal lcd_rs       : std_logic;
  signal lcd_rw       : std_logic;
  signal lcd_db       : std_logic_vector(3 downto 0);
  signal line1_buffer : std_logic_vector(127 downto 0);
  signal line2_buffer : std_logic_vector(127 downto 0);

begin

  DUT: entity work.lcd16x2_ctrl
    generic map (
      CLK_PERIOD_NS => CLK_PERIOD_NS)
    port map (
      clk          => clk,
      rst          => rst,
      lcd_e        => lcd_e,
      lcd_rs       => lcd_rs,
      lcd_rw       => lcd_rw,
      lcd_db       => lcd_db,
      line1_buffer => line1_buffer,
      line2_buffer => line2_buffer);

  -- clock generation
  Clk <= not Clk after 10 ns;
  rst <= '0';
  line1_buffer <= (others => '1');
  line2_buffer <= (others => '0');

  -- waveform generation
  WaveGen_Proc: process
  begin
    -- insert signal assignments here
 
    wait until Clk = '1';
  end process WaveGen_Proc;

end architecture behavior;

configuration lcd16x2_ctrl_tb_behavior_cfg of lcd16x2_ctrl_tb is
  for behavior
  end for;
end lcd16x2_ctrl_tb_behavior_cfg;


ผลการจำลองการทำงานโดยโปรแกรม Model Sim


ภาพการทดลอง



ภาพจอแสดงผลตัวอักษร "Hello Word "

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

การทดลองที่ 5 การสร้างวงจรดิจิทัลเพื่อส่งตัวอักษร 'a' ผ่าน U-ART ไปยังคอมพิวเตอร์

วัตถุประสงค์
  • ฝึกทำษะในการออกแบบโปรแกรมในภาษา vhdl
  • ศึกษาการทำงานของการส่งสัญญาณ ผ่าน U-ART
  • สามารถนำความรู้ที่ได้จากการทดลองนี้ไปประยุกต์ใช้ในวงจรอื่นๆได้ อย่างถูกต้องเหมาะสม
โจทย์ปฎิบัติ
         สร้างวงจรดิจิทัลเพื่อส่งตัวอักษร 'a' ผ่าน UART ไปยังคอมพิวเตอร์ เมื่อกดปุ่มแล้วปล่อยในแต่ละครั้ง โดยใช้ค่า baudrate เท่ากับ 9600 (เน้นส่งข้อมูลไบต์จาก FPGA ไปยังคอมพิวเตอร์เท่านั้น ยังไม่ต้องรับข้อมูล)

อุปกรณ์ 
1.บอร์ด FPGA CYCLOne 3 ชิปหมายเลข EP3C10E144C8 1 บอร์ด

2. ออสซิโลสโคป  1 เครื่อง
3. สายไฟ
4. คอมพิวเตอร์ที่มีโปรแกรม Altera 10.1d (Quartus II 13.1)
แนวคิด
       u art เริ่มต้นจาก Start Bit เป็น Logic 0 จากนั้นจะตามด้วย Data ตัว 'a' [00110001] แล้วจะถูกปิดด้วย Stop Bit เป็น Logic 1 ดังภาพ

และทำการออกแบบการเขียนโค้ดให้แบ่งเป็น  state 

โค้ด


อธิบายโค้ด






ผลการใช้งานของโปรแกรมเมื่อรันผ่าน Quartus

ผลการทดลองจากโปรแกรม Model - sim
  • เมื่อไม่ได้กดปุ่ม  PB = '0'
  • เมื่อ กดปุ่ม  PB = ' 1' แล้วโปรแกรมจะเริ่มเปลี่ยน state

ภาพการทดลอง


รูปสัญญาณเมื่อต่อกับออสซิโลสโคป

ภาพการต่ออุปกรณ์


ภาพหน้าจอเมื่อกดส่งตัวอักษร 'a'


วีดีโอการทดลอง




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

การทดลองที่ 4
สร้างวงจรดิจิทัลเพื่ออ่านค่าจาก 4x4 keypad แล้วแสดงผลด้วย LEDs

จุดประสงค์
1.เพื่อให้เข้าใจหลักการทำงานของ 4x4 Keypad และสามารถนำมาสร้างเป็นวงจรได้
2.เพื่อให้เข้าใจฟังก์ชั่นการทำงานของ FPGA ขึ้น
3.เพื่อสามารถนำความรุ็ที่ได้จากการทดลองนี้มาประยุกต์ใช้กับวงจรอื่นๆได้อย่างเหมาะสม

โจทย์คำสั่ง
เขียน VHDL ที่ใช้ควบคุมการอ่านค่าจาก 4x4 Keypad เพื่อมาแสดงผลที่ LED ทั้ง 8 ดวง บน FPGA โดยที่แสดงผลเป็นเลขฐานสองของค่าเลขฐานสิบที่อ่านได้จากปุ่มกดแต่ละปุ่ม

อุปกรณ์
1.บอร์ด FPGA CYCLOne 3 ชิปหมายเลข EP3C10E144C8 1 บอร์ด


2. ออสซิโลสโคป 1 เครื่อง

3. สายไฟ

4. คอมพิวเตอร์ที่มีโปรแกรม Altera 10.1d (Quartus II 13.1)

5. 4x4 keypad 1 อัน
















โค้ด
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity Botton is
port( PB_colum : in std_logic_vector (3 downto 0);
PB : out std_logic_vector (3 downto 0);
clk : in std_logic;
Response_LED:out std_logic_vector (7 downto 0);
Buzzer : out std_logic :='0');
end Botton;

architecture bahavioral of Botton is 
type state is (s0,s1,s2,s3);
signal stateCheck : state :=s0;
signal time_check : integer := 0;

begin 
process(clk,PB_colum)
begin

if rising_edge (clk) then
time_check <= time_check + 1;
if ((time_check > 20000) and (time_check < 30000)) then
stateCheck <= s0;
elsif ((time_check > 30000) and (time_check < 40000)) then
stateCheck <= s1;
elsif ((time_check > 40000) and (time_check < 50000)) then
stateCheck <= s2;
elsif ((time_check > 50000) and (time_check < 60000)) then
stateCheck <= s3;
time_check <= 0;
end if;

case stateCheck is
when s0 =>
PB <= "0111";
for i in 0 to 3 loop
if PB_colum(i) = '0' then
if i = 0 then
response_LED <= "00000001"; --1
Buzzer <= '1';
end if;
if i = 1 then
response_LED <= "00000101"; --5
Buzzer <= '1';
end if;
if i = 2 then
response_LED <= "00001001"; --9
Buzzer <= '1';
end if;
if i = 3 then
response_LED <= "00001101";  --13
Buzzer <= '1';
end if;
end if;
end loop;

when s1 =>
PB <= "1011";
for i in 0 to 3 loop
if PB_colum(i) = '0' then
if i = 0 then
response_LED <= "00000010"; --2
Buzzer <= '1';
end if;
if i = 1 then
response_LED <= "00000110"; --6
Buzzer <= '1';
end if;
if i = 2 then
response_LED <= "00001010"; --10
Buzzer <= '1';
end if;
if i = 3 then
response_LED <= "00001110";  --14
Buzzer <= '1';
end if;
end if;
end loop;

when s2 =>
PB <= "1101";
for i in 0 to 3 loop
if PB_colum(i) = '0' then
if i = 0 then
response_LED <= "00000011"; --3
Buzzer <= '1';
end if;
if i = 1 then
response_LED <= "00000111"; --7
Buzzer <= '1';
end if;
if i = 2 then
response_LED <= "00001011"; --11
Buzzer <= '1';
end if;
if i = 3 then
response_LED <= "00001111";  --15
Buzzer <= '1';
end if;
end if;
end loop;

when s3 =>
PB <= "1110";
for i in 0 to 3 loop
if PB_colum(i) = '0' then
if i = 0 then
response_LED <= "00000100"; --4
Buzzer <= '1';
end if;
if i = 1 then
response_LED <= "00001000"; --8
Buzzer <= '1';
end if;
if i = 2 then
response_LED <= "00001100"; --12
Buzzer <= '1';
end if;
if i = 3 then
response_LED <= "00010000";  --16
Buzzer <= '1';
end if;
end if;
end loop;
Buzzer <= '0';
end case;
end if;
end process;

end bahavioral;

ผลการจำลองการทำงานด้วยโปรแกรม Model Sim

ภาพการทดลอง



ภาพการต่อวงจร
 วิดีโอการทดลอง




วันอังคารที่ 3 มีนาคม พ.ศ. 2558

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

ออกแบบวงจรดิจิทัลสร้างสัญญาณ 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) เป็นอินพุตจากปุ่มกด ปุ่ม ทำงานแบบ Active-low เพื่อใช้ในการเปลี่ยนสีของ WS2812 RGB LED จำนวน ดวง
- DATA (output) เป็นเอาต์พุตสำหรับนำไปควบคุมการทำงานของ WS2812 RGB LED เพียง ดวง ซึ่งเป็นสัญญาณตามข้อกำหนดของชิป 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;
ผลการทดสอบโปรแกรมจากโปรแกรม model-sim

ผลการจำลองจากการกดครั้งที่ 1 : 0x000000

ผลการจำลองจากการกดครั้งที่ 2 : 0x0000FF

ผลการจำลองจากการกดครั้งที่ 3 : 0x00FF00

ผลการจำลองจากการกดครั้งที่ 4 : 0xFF0000 

ผลการทดลอง



เมื่อกดปุ่มจะแสดงค่าสี ตาม bit ที่เลื่อน

วีดีโอผลการทดลอง