02 การใช้งานพอร์ทอนุกรม
บล็อกไดอะแกรม
บอร์ด MOJO ใช้ชิป ATmega32u4 (3.3V, 8MHz) โดยทำหน้าที่หลักเป็นตัวโปรแกรมชิป FPGA และสามารถเชื่อมต่อผ่านขา Tx/Rx และ SPI กับ FPGA ได้
โมดูลสำหรับการเชื่อมต่อระหว่าง FPGA กับ ATmega32u4 คือ avr_interface ซึ่งอยู่ในตัวอย่าโปรแกรม Mojo-Base-VHDL-1.1.zip จาก http://sourceforge.net/projects/mojovhdl/
avr_interface มีรายละเอียดดังบล็อกไดอะแกรมตามรูป
avr_interface ประกอบด้วยโมดูลย่่อยๆ
spi_slave
serial_tx
serial_rx
cclk_detector
ทั้งนี้ให้ลองสังเกต การเรียกใช้โมดูลย่อยเหล่านี้ของภาษา VHDL รุ่นนี้ไม่ได้ใช้คำสั่ง component แต่ใช้การเรียกใช้จาก library work และบอกการเชื่อมต่อสัญญาณพร้อมเลย
avr_interface : entity work.avr_interface
port map (........
........
........
);
ดังนั้นเราสามารถรับ-ส่งข้อมูลระหว่าง FPGA กับ PC ผ่านทางพอร์ทอนุกรมได้
การทดลองใช้พอร์ทอนุกรม
ให้ไป ดาวน์โหลดโปรแกรม Mojo-Base-VHDL-1.1.zip จาก http://sourceforge.net/projects/mojovhdl/
ขยายไฟล์ จะได้โฟลด์เดอร์ Mojo-Base-VHDL
ให้ดับเบิลคลิกไฟล์ Mojo-Base-VHDL.xise ใน sub flodder Mojo-Base-VHDL\ise_files เพื่อรัน ise
ทำการแปลโปรแกรมจนได้ mojo_top.bin แล้วนำไปโปรแรมลงชิพ FPGA บนบอร์ด MOJO ด้วยโปรแกรม Mojoloader
รันโปรแกรม terminal (ในตัวอย่างนี้ใช้โปรแกรม Serial Monitor ของโปรแกรม Arduino 1.6.2 ) เพื่อทดลองการทำงาน
การทำงาน
เมื่อพิมพ์ตัวอักษรอะไรลงในช่องเพื่อส่งข้อมูลแล้วกด Enter
ข้อมูลจะถูกส่งออกจาก PC ผ่านพอร์อนุกรม (USB) เข้าสู่บอร์ด Mojo ผ่านชิพ AVR เข้าสู่ FPGA
FPGA รับข้อมูลแล้วส่งข้อมูลนั้นกลับออกทางพอร์ทอนุกรม คืนสู่ PC ออกแสดงผลที่โปรแกรม Terminal
อธิบายโปรแกรม (บางส่วน)
โปรแกรมทั้งหมดเก็บอยู่ใน โฟลดเดอร์ Mojo-Base-VHDL\src
โปรแกรมหลักคือ mojo_top.vhd
----------------------------------------------------------------------------------
-- Mojo_top VHDL
-- Translated from Mojo-base Verilog project @ http://embeddedmicro.com/frontend/files/userfiles/files/Mojo-Base.zip
-- by Xark
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
กำหนดขาสัญญาณ
---------------------------------------------------------------------------------
entity mojo_top is
port (
clk : in std_logic; -- 50Mhz clock
rst_n : in std_logic; -- "reset" button input (negative logic)
cclk : in std_logic; -- configuration clock (?) from AVR (to detect when AVR ready)
led : out std_logic_vector(7 downto 0); -- 8 LEDs on Mojo board
spi_sck : in std_logic; -- SPI clock to from AVR
spi_ss : in std_logic; -- SPI slave select from AVR
spi_mosi : in std_logic; -- SPI serial data master out, slave in (AVR -> FPGA)
spi_miso : out std_logic; -- SPI serial data master in, slave out (AVR <- FPGA)
spi_channel : out std_logic_vector(3 downto 0); -- analog read channel (input to AVR service task)
avr_tx : in std_logic; -- serial data transmited from AVR/USB (FPGA recieve)
avr_rx : out std_logic; -- serial data for AVR/USB to receive (FPGA transmit)
avr_rx_busy : in std_logic -- AVR/USB buffer full (don't send data when true)
);
end mojo_top;
---------------------------------------------------------------------------------
architecture RTL of mojo_top is
signal rst : std_logic; -- reset signal (rst_n inverted for postive logic)
-- signals for avr_interface
signal channel : std_logic_vector(3 downto 0);
signal sample : std_logic_vector(9 downto 0);
signal sample_channel : std_logic_vector(3 downto 0);
signal new_sample : std_logic;
signal tx_data : std_logic_vector(7 downto 0);
signal rx_data : std_logic_vector(7 downto 0);
signal new_tx_data : std_logic;
signal new_rx_data : std_logic;
signal tx_busy : std_logic;
-- signals for UART echo test
signal uart_data : std_logic_vector(7 downto 0); -- data buffer for UART (holds last recieved/sent byte)
signal data_to_send : std_logic; -- indicates data to send in uart_data
-- signals for sample test
signal last_sample : std_logic_vector(9 downto 0);
begin
rst <= NOT rst_n; -- generate non-inverted reset signal from rst_n button
-- NOTE: If you are not using the avr_interface component, then you should uncomment the
-- following lines to keep the AVR output lines in a high-impeadence state. When
-- using the avr_interface, this will be done automatically and these lines should
-- be commented out (or else "multiple signals connected to output" errors).
--spi_miso <= 'Z'; -- keep AVR output lines high-Z
--avr_rx <= 'Z'; -- keep AVR output lines high-Z
--spi_channel <= "ZZZZ"; -- keep AVR output lines high-Z
-- instantiate the avr_interface (to handle USB UART and analog sampling, etc.)
เรียกใช้โมดูล avr_interface และทำการเชื่อมต่อสัญญาณเข้ากับระบบ
---------------------------------------------------------------------------------
avr_interface : entity work.avr_interface
port map (
clk => clk, -- 50Mhz clock
rst => rst, -- reset signal
-- AVR MCU pin connections (that will be managed)
cclk => cclk,
spi_miso => spi_miso,
spi_mosi => spi_mosi,
spi_sck => spi_sck,
spi_ss => spi_ss,
spi_channel => spi_channel,
tx => avr_rx,
tx_block => avr_rx_busy,
rx => avr_tx,
-- analog sample interface
channel => channel, -- set this to channel to sample (0, 1, 4, 5, 6, 7, 8, or 9)
new_sample => new_sample, -- indicates when new sample available
sample_channel => sample_channel, -- channel number of sample (only when new_sample = '1')
sample => sample, -- 10 bit sample value (only when new_sample = '1')
-- USB UART tx interface
new_tx_data => new_tx_data, -- set to set data in tx_data (only when tx_busy = '0')
tx_data => tx_data, -- data to send
tx_busy => tx_busy, -- indicates AVR is not ready to send data
-- USB UART rx interface
new_rx_data => new_rx_data, -- set when new data is received
rx_data => rx_data -- received data (only when new_tx_data = '1')
);
---------------------------------------------------------------------------------
-- The following is simple test that will transmit any bytes received on UART and show upper 8-bits of analog 0 sample on LEDs
echo: process(clk, rst)
begin
if rst = '1' then -- set signals to default on reset
tx_data <= (others => '0');
uart_data <= (others => '0');
data_to_send <= '0';
new_tx_data <= '0';
channel <= "0000"; -- use channel 0 for this test
last_sample <= (others => '0');
led <= "11111111"; -- flash LEDs on reset
elsif rising_edge(clk) then
if data_to_send = '1' and tx_busy = '0' then -- if there is data to send and UART is not busy then
tx_data <= uart_data; -- set tx_data input
new_tx_data <= '1'; -- signal there is data to tx
data_to_send <= '0'; -- clear our send flag
else
new_tx_data <= '0'; -- else, we have no new tx data
end if;
if new_rx_data = '1' then -- if there is new received data then
uart_data <= rx_data; -- put it into uart_data register
data_to_send <= '1'; -- set flag that we have data to send
end if;
if new_sample = '1' then -- if there is a new sample available then
last_sample <= sample; -- put it into last_sample register
end if;
led <= last_sample(9 downto 2); -- display upper 8-bits of last 10-bit analog sample reading
end if;
end process echo;
end RTL;
หมายเหตุ
โปรแกรมที่เป็นสีแดงคือส่วนที่ใช้ติดต่อกับพอร์ทอนุกรม
โปรแกรมสีน้ำเงิน ใช้ติดต่อกับพอร์ทอนาลอก
เราสามารถใช้โปรแกรมนี้ (mojo_top.vhd) เป็นโปรแกรมหลักสำหรับทำงานอื่นๆได้ โดยการ copy ทั้งโปรเจค (เอาเฉพาะ source ที่ยังไม่ได้แปล ไปแก้ไขเพื่อให้ทำงานอื่นๆได้ ดังตัวอย่างที่จะเขียนต่อไป
โปรดติดตาม