Vous êtes sur la page 1sur 20

Perancangan Komponen Terprogram

Tugas Perancangan Komponen Terprogram

Perancangan Program pembacaan sensor ultrasonic dan ADC 8 bit menggunakan komunikasi serial 2 FPGA

Dikerjakan Oleh: Ahmad Cecep Sofyan H. Aminudin Ridwan Iqbal Aditya Sammy 2208 100 053 2209 100 xxx 2209 100 xxx 2209 100 xxx 2209 100 xxx 2209 100 xxx Angkatan 2008 Angkatan 2009 Angkatan 2009 Angkatan 2009 Angkatan 2009 Angkatan 2009

INSTITUT TEKNOLOGI SEPULUH NOPEMBER SURABAYA 2012

Perancangan Program pembacaan sensor ultrasonic dan ADC 8 bit menggunakan komunikasi serial 2 FPGA
A. PROJECT FPGA1
-- ----------------------------------------------------- UART module -- ---------------------------------------------------LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; -- ---------------------------------------------------Entity UARTS is -- ---------------------------------------------------Port (clk : In std_logic; rst : In std_logic; Baud : In std_logic_vector (2 downto 0); Rx : In std_logic; LD : In std_logic; Din : In std_logic_vector (7 downto 0); Tx : Out std_logic; TxBusy : Out std_logic; RxRDY : Out std_logic; RxErr : Out std_logic; Dout : Out std_logic_vector (7 downto 0) ); end UARTS; Architecture RTL of UARTS is type State_Rx_Type is (Idle, Start_Rx, Edge_Rx, Shift_Rx, Stop_Rx, RxOVF); signal RxFSM : State_Rx_Type; type State_Tx_Type is (Idle, Load_Tx, Shift_Tx, Stop_Tx); signal TxFSM : State_Tx_Type; signal parity : boolean; signal Divisor : integer range 0 to 383; signal Top16 : std_logic; signal TopTx : std_logic; signal TopRx : std_logic; signal ClrDiv : std_logic; signal RxRdyi : std_logic; signal ClkDiv : unsigned (3 downto 0); signal Div16 : integer range 0 to 383; signal RxDiv : integer range 0 to 7; signal TxBitCnt : integer range 0 to 15; signal RxBitCnt : integer range 0 to 15; constant NDBits : integer := 9; signal RegDin : std_logic_vector (7 downto 0); signal Tx_Reg : std_logic_vector (9 downto 0); signal Rx_Reg : std_logic_vector (7 downto 0); begin -- --------------------------

-- Baud rate selection -- -------------------------process (RST, CLK) begin if RST='0' then Divisor <= 0; elsif rising_edge(CLK) then case Baud is when "000" => Divisor <= 0; when "001" => Divisor <= 7; when "010" => Divisor <= 15; when "011" => Divisor <= 23; when "100" => Divisor <= 47; when "101" => Divisor <= 95; when "110" => Divisor <= 191; when "111" => Divisor <= 383; when others => Divisor <= 0; end case; end if; end process; -- --------------------------- Clk16 Clock Generation -- -------------------------process (RST, CLK) begin if RST='0' then Top16 <= '0'; Div16 <= 0; elsif rising_edge(CLK) then Top16 <= '0'; if Div16 = Divisor then Div16 <= 0; Top16 <= '1'; else Div16 <= Div16 + 1; end if; end if; end process; -- --------------------------- Tx Clock Generation -- -------------------------process (RST, CLK) begin if RST='0' then TopTx <= '0'; ClkDiv <= (others=>'0'); elsif rising_edge(CLK) then TopTx <= '0'; if Top16='1' then ClkDiv <= ClkDiv + 1; if ClkDiv = 15 then TopTx <= '1'; end if;

-- 921.600 -- 115.200 -- 57.600 -- 38.400 -- 19.200 -- 9.600 -- 4.800 -- 2.400 -- n.u.

end if; end if; end process; -- ------------------------------- Rx Sampling Clock Generation -- -----------------------------process (RST, CLK) begin if RST='0' then TopRx <= '0'; RxDiv <= 0; elsif rising_edge(CLK) then TopRx <= '0'; if ClrDiv='1' then RxDiv <= 0; elsif Top16='1' then if RxDiv = 7 then RxDiv <= 0; TopRx <= '1'; else RxDiv <= RxDiv + 1; end if; end if; end if; end process; -- --------------------------- Transmit State Machine -- -------------------------parity <= FALSE; Tx <= Tx_Reg(0); Tx_FSM: process (RST, CLK) begin if RST='0' then Tx_Reg <= (others => '1'); TxBitCnt <= 0; TxFSM <= Idle; TxBusy <= '0'; RegDin <= (others=>'0'); elsif rising_edge(CLK) then TxBusy <= '1'; -- except when explicitly '0' case TxFSM is when Idle => if LD='1' then -- latch the input data immediately. RegDin <= Din; TxBusy <= '1'; TxFSM <= Load_Tx; else TxBusy <= '0'; end if; when Load_Tx =>

if TopTx='1' then TxFSM <= Shift_Tx; if parity then -- start + data + parity TxBitCnt <= (NDBits + 2); --Tx_Reg = make_parity(RegDin,even) & Din & '0'; else TxBitCnt <= (NDBits + 1); -- start + data Tx_reg <= '1' & RegDin & '0'; end if; end if; when Shift_Tx => if TopTx='1' then TxBitCnt <= TxBitCnt - 1; Tx_reg <= '1' & Tx_reg (Tx_reg'high downto 1); if TxBitCnt=1 then TxFSM <= Stop_Tx; end if; end if; when Stop_Tx => if TopTx='1' then TxFSM <= Idle; end if; when others => TxFSM <= Idle; end case; end if; end process; -- ------------------------- RECEIVE State Machine -- -----------------------Rx_FSM: process (RST, CLK) begin if RST='0' then Rx_Reg <= (others => '0'); Dout <= (others => '0'); RxBitCnt <= 0; RxFSM <= Idle; RxRdyi <= '0'; ClrDiv <= '0'; RxErr <= '0'; elsif rising_edge(CLK) then ClrDiv <= '0'; -- default value -- reset error when a word has been received Ok: if RxRdyi='1' then RxErr <= '0'; RxRdyi <= '0'; end if; case RxFSM is when Idle => -- wait on start bit RxBitCnt <= 0; if Top16='1' then if Rx='0' then

RxFSM <= Start_Rx; ClrDiv <='1'; -- Synchronize the divisor end if; -- else false start, stay in Idle end if; when Start_Rx => -- wait on first data bit if TopRx = '1' then if Rx='1' then -- framing error RxFSM <= RxOVF; report "Start bit error." severity note; else RxFSM <= Edge_Rx; end if; end if; when Edge_Rx => -- should be near Rx edge if TopRx = '1' then RxFSM <= Shift_Rx; if RxBitCnt = NDbits-1 then RxFSM <= Stop_Rx; else RxFSM <= Shift_Rx; end if; end if; when Shift_Rx => -- Sample data ! if TopRx = '1' then RxBitCnt <= RxBitCnt + 1; -- shift right : Rx_Reg <= Rx & Rx_Reg (Rx_Reg'high downto 1); RxFSM <= Edge_Rx; end if; when Stop_Rx => -- during Stop bit if TopRx = '1' then Dout <= Rx_reg; RxRdyi <='1'; RxFSM <= Idle; --assert (debug 1) --report "Character received in decimal is : " & integer'image(to_integer(unsigned(Rx_Reg))) --severity note; end if; when RxOVF => -- Overflow / Error RxErr <= '1'; if Rx='1' then RxFSM <= Idle; end if; end case; RxRDY <= RxRDYi; end if; end process; end RTL;

skematik

B. Pembacaan ADC 0804

Pembacaan ADC 0804

C. Pembacaan Sensor Ultrasonic SRF04

Project Slave FPGA2


A.Menampilkan LCD
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity FinalProject is port( num1, num2 clk, rst tx LCD_RW LCD_ON LCD_E, LCD_RS end FinalProject; architecture behavior of FinalProject is signal tx_byte : STD_LOGIC_VECTOR(7 downto 0); TYPE STATE_TYPE IS (HOLD, C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26, TOGGLE_E, RESET, FUNC_SET, DISPLAY_OFF, DISPLAY_ON, DISPLAY_CLEAR, MODE_SET, SECOND_LINE, RETURN_HOME); SIGNAL state, next_command: STATE_TYPE; SIGNAL CLK_COUNT_500HZ: integer range 0 to 50000; SIGNAL CLK_COUNT_10HZ: integer range 0 to 20; SIGNAL rst_count: integer range 0 to 2; SIGNAL RAT11, RAT22, PUL11, PUL22, SAT11, SAT22: STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL CLK_500HZ : STD_LOGIC; begin LCD_RW <= '0'; --write only LCD_ON <= '1';

: in STD_LOGIC_VECTOR(7 downto 0); : in bit; : inout STD_LOGIC_VECTOR(7 downto 0); : BUFFER STD_LOGIC; : out STD_LOGIC; : out bit);

--The following "with" statements simplify the process of adding and removing states. --register select, command or ascii with state select LCD_RS <= '0' when RESET|FUNC_SET|DISPLAY_OFF|DISPLAY_ON|DISPLAY_CLEAR|MODE_SET|SECOND_LINE|RETURN_HOM E, '1' when others; --register LCD enable with state select LCD_E <= '0' when TOGGLE_E|HOLD, '1' when others; --what byte to transmit to lcd --refer to datasheet for an explanation of these values with state select tx_byte <= "00111000" when RESET|FUNC_SET, "00001000" when DISPLAY_OFF, "00001100" when DISPLAY_ON, "00000001" when DISPLAY_CLEAR, "00000110" when MODE_SET, "11000000" when SECOND_LINE, "10000000" when RETURN_HOME, "0011"&RAT11 when C11, "0011"&PUL11 when C12, "0011"&SAT11 when C13, "0011"&RAT22 when C24, "0011"&PUL22 when C25, "0011"&SAT22 when C26, "01000001" when C7|C16,--char_A, "01000011" when C18,--char_C, "01000100" when C17,--char_D, "01001100" when C4,--char_L, "01010010" when C6,--char_R, "01010011" when C1|C14,--char_S, "01010100" when C5,--char_T, "01010101" when C3,--char_U, "00101110" when C2|C15,--char_dot, "10100000" when C8|C10|C19|C20|C21|C23,--char_space, "00111010" when C9|C22,--char_:, "00000000" when others; -- tristate when not write tx <= tx_byte WHEN LCD_RW = '0'; PROCESS(clk) BEGIN IF rst = '1' THEN if (clk'EVENT AND clk= '1') then if (CLK_COUNT_500HZ<=49999) then CLK_COUNT_500HZ<=CLK_COUNT_500HZ+1; ELSE CLK_COUNT_500HZ <= 0;

CLK_500HZ <= NOT CLK_500HZ; END IF; END IF; end if; END PROCESS; PROCESS (CLK_500HZ, rst) BEGIN IF rst = '0' THEN state <= RESET; ELSIF CLK_500HZ'EVENT AND CLK_500HZ = '1' THEN -- SEND TIME TO LCD CASE state IS -- Set Function to 8-bit transfer and 2 line display with 5x8 Font size -- see Hitachi HD44780 family data sheet for LCD command and timing details WHEN RESET => state <= TOGGLE_E; if (rst_count<2) then next_command <= RESET; rst_count<=rst_count+1; else next_command <= FUNC_SET; rst_count<=0; end if; -- EXTRA STATES ABOVE ARE NEEDED FOR RELIABLE PUSHBUTTON RESET OF LCD WHEN FUNC_SET => state <= TOGGLE_E; next_command <= DISPLAY_OFF; -- Turn off Display and Turn off cursor WHEN DISPLAY_OFF => state <= TOGGLE_E; next_command <= DISPLAY_CLEAR; -- Turn on Display and Turn off cursor WHEN DISPLAY_CLEAR => state <= TOGGLE_E; next_command <= DISPLAY_ON; -- Turn on Display and Turn off cursor WHEN DISPLAY_ON => state <= TOGGLE_E; next_command <= MODE_SET; -- Set write mode to auto increment address and move cursor to the right WHEN MODE_SET => state <= TOGGLE_E; next_command <= C1; -- Write ASCII hex per-character in first line of LCD WHEN C1 => state <= TOGGLE_E; next_command <= C2; WHEN C2 => state <= TOGGLE_E; next_command <= C3;

WHEN C3 => state <= TOGGLE_E; next_command <= C4; WHEN C4 => state <= TOGGLE_E; next_command <= C5; WHEN C5 => state <= TOGGLE_E; next_command <= C6; WHEN C6 => state <= TOGGLE_E; next_command <= C7; WHEN C7 => state <= TOGGLE_E; next_command <= C8; WHEN C8 => state <= TOGGLE_E; next_command <= C9; WHEN C9 => state <= TOGGLE_E; next_command <= C10; WHEN C10 => state <= TOGGLE_E; next_command <= C11; WHEN C11 => state <= TOGGLE_E; next_command <= C12; WHEN C12 => state <= TOGGLE_E; next_command <= C13; WHEN C13 => state <= TOGGLE_E; next_command <= SECOND_LINE; -- go to second line WHEN SECOND_LINE => state <= TOGGLE_E; next_command <= C14; -- Write ASCII hex per-character in first line of LCD WHEN C14 => state <= TOGGLE_E; next_command <= C15; WHEN C15 => state <= TOGGLE_E; next_command <= C16; WHEN C16 => state <= TOGGLE_E; next_command <= C17; WHEN C17 => state <= TOGGLE_E; next_command <= C18; WHEN C18 =>

state <= TOGGLE_E; next_command <= C19; WHEN C19 => state <= TOGGLE_E; next_command <= C20; WHEN C20 => state <= TOGGLE_E; next_command <= C21; WHEN C21 => state <= TOGGLE_E; next_command <= C22; WHEN C22 => state <= TOGGLE_E; next_command <= C23; WHEN C23 => state <= TOGGLE_E; next_command <= C24; WHEN C24 => state <= TOGGLE_E; next_command <= C25; WHEN C25 => state <= TOGGLE_E; next_command <= C26; WHEN C26 => state <= TOGGLE_E; next_command <= RETURN_HOME; -- Return write address to first character postion WHEN RETURN_HOME => state <= TOGGLE_E; next_command <= C1; -- The next two states occur at the end of each command to the LCD -- Toggle E line - falling edge loads inst/data to LCD controller WHEN TOGGLE_E => state <= HOLD; -- Hold LCD inst/data valid after falling edge of E line WHEN HOLD => state <= next_command; END CASE; END IF; END PROCESS; process (num1, num2) variable temp1 : integer range 0 to 255; variable temp2 : integer range 0 to 255; begin temp1 :=conv_integer(num1(7 downto 0)); temp2 :=conv_integer(num2(7 downto 0)); RAT11 <= conv_std_logic_vector(temp1 / 100, 4); PUL11 <= conv_std_logic_vector((temp1 mod 100) / 10, 4); SAT11 <= conv_std_logic_vector(temp1 mod 10, 4); RAT22 <= conv_std_logic_vector(temp2 / 100, 4); PUL22 <= conv_std_logic_vector((temp2 mod 100) / 10, 4); SAT22 <= conv_std_logic_vector(temp2 mod 10, 4);

end process; end behavior;

B.KOMUNIKASI UART2
-- ----------------------------------------------------- UART module -- ---------------------------------------------------LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; -- ---------------------------------------------------Entity UARTS is -- ---------------------------------------------------Port ( clk : In std_logic; rst : In std_logic; Baud : In std_logic_vector (2 downto 0); Rx : In std_logic; LD : In std_logic; Din : In std_logic_vector (7 downto 0); Tx : Out std_logic; TxBusy : Out std_logic; RxRDY : Out std_logic; RxErr : Out std_logic; Dout : Out std_logic_vector (7 downto 0) ); end UARTS; Architecture RTL of UARTS is type signal type signal State_Rx_Type is (Idle, Start_Rx, Edge_Rx, Shift_Rx, Stop_Rx, RxOVF); RxFSM : State_Rx_Type; State_Tx_Type is (Idle, Load_Tx, Shift_Tx, Stop_Tx); TxFSM : State_Tx_Type;

signal parity signal Divisor signal Top16 signal TopTx signal TopRx signal ClrDiv signal RxRdyi signal ClkDiv signal Div16 signal RxDiv signal TxBitCnt signal RxBitCnt constant NDBits signal RegDin

: boolean; : integer range 0 to 383; : std_logic; : std_logic; : std_logic; : std_logic; : std_logic; : unsigned (3 downto 0); : integer range 0 to 383; : integer range 0 to 7; : integer range 0 to 15; : integer range 0 to 15; : integer := 9; : std_logic_vector (7 downto 0);

signal Tx_Reg signal Rx_Reg begin

: std_logic_vector (9 downto 0); : std_logic_vector (7 downto 0);

-- --------------------------- Baud rate selection -- -------------------------process (RST, CLK) begin if RST='0' then Divisor <= 0; elsif rising_edge(CLK) then case Baud is when "000" => Divisor <= 0; -- 921.600 when "001" => Divisor <= 7; -- 115.200 when "010" => Divisor <= 15; -- 57.600 when "011" => Divisor <= 23; -- 38.400 when "100" => Divisor <= 47; -- 19.200 when "101" => Divisor <= 95; -- 9.600 when "110" => Divisor <= 191; -- 4.800 when "111" => Divisor <= 383; -- 2.400 when others => Divisor <= 0; -- n.u. end case; end if; end process; -- --------------------------- Clk16 Clock Generation -- -------------------------process (RST, CLK) begin if RST='0' then Top16 <= '0'; Div16 <= 0; elsif rising_edge(CLK) then Top16 <= '0'; if Div16 = Divisor then Div16 <= 0; Top16 <= '1'; else Div16 <= Div16 + 1; end if; end if; end process; -- --------------------------- Tx Clock Generation -- -------------------------process (RST, CLK) begin if RST='0' then TopTx <= '0'; ClkDiv <= (others=>'0'); elsif rising_edge(CLK) then TopTx <= '0'; if Top16='1' then

ClkDiv <= ClkDiv + 1; if ClkDiv = 15 then TopTx <= '1'; end if; end if; end if; end process; -- ------------------------------- Rx Sampling Clock Generation -- -----------------------------process (RST, CLK) begin if RST='0' then TopRx <= '0'; RxDiv <= 0; elsif rising_edge(CLK) then TopRx <= '0'; if ClrDiv='1' then RxDiv <= 0; elsif Top16='1' then if RxDiv = 7 then RxDiv <= 0; TopRx <= '1'; else RxDiv <= RxDiv + 1; end if; end if; end if; end process; -- --------------------------- Transmit State Machine -- -------------------------parity <= FALSE; Tx <= Tx_Reg(0); Tx_FSM: process (RST, CLK) begin if RST='0' then Tx_Reg <= (others => '1'); TxBitCnt <= 0; TxFSM <= Idle; TxBusy <= '0'; RegDin <= (others=>'0'); elsif rising_edge(CLK) then TxBusy <= '1'; -- except when explicitly '0' case TxFSM is when Idle => if LD='1' then -- latch the input data immediately. RegDin <= Din; TxBusy <= '1'; TxFSM <= Load_Tx;

else TxBusy <= '0'; end if; when Load_Tx => if TopTx='1' then TxFSM <= Shift_Tx; if parity then -- start + data + parity TxBitCnt <= (NDBits + 2); --Tx_Reg = make_parity(RegDin,even) & Din & '0'; else TxBitCnt <= (NDBits + 1); -- start + data Tx_reg <= '1' & RegDin & '0'; end if; end if; when Shift_Tx => if TopTx='1' then TxBitCnt <= TxBitCnt - 1; Tx_reg <= '1' & Tx_reg (Tx_reg'high downto 1); if TxBitCnt=1 then TxFSM <= Stop_Tx; end if; end if; when Stop_Tx => if TopTx='1' then TxFSM <= Idle; end if; when others => TxFSM <= Idle; end case; end if; end process;

-- ------------------------- RECEIVE State Machine -- -----------------------Rx_FSM: process (RST, CLK) begin if RST='0' then Rx_Reg <= (others => '0'); Dout <= (others => '0'); RxBitCnt <= 0; RxFSM <= Idle; RxRdyi <= '0'; ClrDiv <= '0'; RxErr <= '0'; elsif rising_edge(CLK) then ClrDiv <= '0'; -- default value

-- reset error when a word has been received Ok: if RxRdyi='1' then RxErr <= '0'; RxRdyi <= '0'; end if; case RxFSM is when Idle => -- wait on start bit RxBitCnt <= 0; if Top16='1' then if Rx='0' then RxFSM <= Start_Rx; ClrDiv <='1'; -- Synchronize the divisor end if; -- else false start, stay in Idle end if; when Start_Rx => -- wait on first data bit if TopRx = '1' then if Rx='1' then -- framing error RxFSM <= RxOVF; report "Start bit error." severity note; else RxFSM <= Edge_Rx; end if; end if; when Edge_Rx => -- should be near Rx edge if TopRx = '1' then RxFSM <= Shift_Rx; if RxBitCnt = NDbits-1 then RxFSM <= Stop_Rx; else RxFSM <= Shift_Rx; end if; end if; when Shift_Rx => -- Sample data ! if TopRx = '1' then RxBitCnt <= RxBitCnt + 1; -- shift right : Rx_Reg <= Rx & Rx_Reg (Rx_Reg'high downto 1); RxFSM <= Edge_Rx; end if; when Stop_Rx => -- during Stop bit if TopRx = '1' then Dout <= Rx_reg; RxRdyi <='1'; RxFSM <= Idle; --assert (debug 1) --report "Character received in decimal is : " & integer'image(to_integer(unsigned(Rx_Reg))) --severity note; end if;

when RxOVF => -- Overflow / Error RxErr <= '1'; if Rx='1' then RxFSM <= Idle; end if; end case; RxRDY <= RxRDYi; end if; end process; end RTL;

Vous aimerez peut-être aussi