EDK tutorial 3
VHDL design i ISE 7.1 for virtex-4
En enkel steg-for-steg veiledning til implementasjon av en RS232 transmitter på en virtex-4 FPGA
Dette er en kort introduksjon til Xilinx ISE og vhdl design i EDK. Vi tar utgangspunkt i det samme prototypekortet (DS-BD-V4LX25MB) som i turtorail 1 og 2. Målet er å lage en enkelt RS232 transmitter som sender koden på DIP-bryterene til en terminal på PC'en. Du vil trenge hyperterminal eller et annet tilsvarende program til å lese COM porten på PC'en.
Lage nytt prosjekt
Start programmet "Project Navigator" under "Xilinx ISE 7.1i" menyen. Når du starter opp vil forrige prosjekt automatisk ligge der hvist noen har brukt ISE før deg. I tilfelle så lukker du prosjektet ved å velge "Close Project" under "File" menyen. Fra "file" menyen velger du så "New Project". Du vil nå få opp et vindu hvor du kan navngi prosjektet og velge plasering. Kall prosjektet "RS232" og finn en passende plasering for prosjektkatalogen. "Top Level Module Type" setter du til VHD. Trykk så "Next"
Du vil nå få opp et vindu hvor du kan velge hviken FPGA du vil bruke, samt vertøyvalg. Sett "Device Family" til Virtex4, "Device" til "xc4vlx25", "Package" til "ff668" og "Speed Grade til -10". "Synthesis Tool" settes til "XST", "Simulator" til "ISE simulator" og simuleringsspråk settes til VHDL. Trykk så "Next".
Du vil nå få opp ett vindu hvor du har muligheten til å få generert en kildefil til prosjektet. Trykk på "New Source".
Velg "VHDL Module" og gi den navnet "RS232_main". Pass på at boksen "Add to Project" er merket og trykk "Next".
Du kan nå legge til porter. Legg inn portene; clk, reset og send som "in". Legg til data som "in" og sett MSB til 7 og LSB til 0. Legg til port tx og opptatt som "out". Trykk så "Next".
Du får nå opp et vindu med et samendrag av kildefilen din. Trykk "Finish". Du kommer nå tilbake til vinduet hvor du kan legge til kildefiler. Trykk "Next".
Neste vindu lar deg legge til ferdige kilderfiler. Ta filene [[Media:rs232_clk.vhd">rs232_clk.vhd</a> og [[Media:rs232_tx.vhd">rs232_tx.vhd</a> og last dem ned på maskinen din.
--------------------------------- --Tor Aleksander Birk Danielsen-- -- klokke til RS232 -- -- 10.04.2005 -- --------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity rs232_clk is port( clk : in std_logic; --main clk 100MHz reset : in std_logic; --global reset clk_tx : inout std_logic; --sendeklokke 16*baudrate bit_send : out std_logic); --pulstog 1*baudrate end rs232_clk; architecture Behavioral of rs232_clk is --interne tellere signal clk_teller_1 : std_logic_vector(0 to 8); signal clk_teller_2 : std_logic_vector(0 to 3); begin --------------------------------------- --lage klokkefrekvens på 16xbaudraten-- -- clk/(budrate*16) = tellerverdi*2-- -- 100MHz/(9600*32) = 325 = 101000101-- --------------------------------------- process (clk) begin if clk'event and clk='1' then if reset = '1' then clk_teller_1 <= clk_teller_1 + 1; if clk_teller_1 = "101000101" then clk_tx <= not clk_tx; clk_teller_1 <= "000000000"; end if; else clk_teller_1 <= "000000000"; end if; end if; end process; --------------------------------------- --lage 1/16 puls av clk_tx til sender-- -- dvs pulstog med samme frekvens -- -- som baudraten -- --------------------------------------- process (reset, clk_tx) begin if reset = '0' then bit_send <= '0'; clk_teller_2 <= "0000"; elsif rising_edge(clk_tx) then clk_teller_2 <= clk_teller_2 + 1; if clk_teller_2 = "1111" then bit_send <= '1'; elsif clk_teller_2 = "0000" then bit_send <= '0'; end if; end if; end process; end Behavioral;
--------------------------------- --Tor Aleksander Birk Danielsen-- -- sender RS232 -- -- 10.04.2005 -- --------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity rs232_tx is port( clk_tx : in std_logic; --clk 16 * baudrateklokke reset : in std_logic; --global reset bit_send : in std_logic; --pulstog 1*baudrate send : in std_logic; --starter transmitt data : in std_logic_vector(7 downto 0); --data som skal sendes tx : out std_logic; --transmittpinne opptatt : out std_logic); --sender opptatt signal end rs232_tx; architecture Behavioral of rs232_tx is type tilstander is (idle, start_sending, sender, stop_send); signal sende_data : tilstander := idle; signal transmitt_buffer : std_logic_vector(9 downto 0); --transmitt buffer (10 bit) signal transmitt_data : std_logic_vector(7 downto 0); --inneholder databyte som skal sendes signal bit_teller: integer := 9; begin ------------------------- --senderutine for rs232-- ------------------------- sender_rs232: process (reset, clk_tx) begin if reset='0' then opptatt <= '0'; sende_data <= idle; transmitt_buffer <= (others=> '1'); elsif rising_edge(clk_tx) then case sende_data is when idle => if send = '0' then transmitt_data <= data; opptatt <= '1'; sende_data <= start_sending; else opptatt <= '0'; end if; when start_sending => if bit_send = '1' then sende_data <= sender; bit_teller <= 9; transmitt_buffer <= '1' & transmitt_data & '0'; end if; when sender => if bit_send = '1' then bit_teller <= bit_teller - 1; transmitt_buffer <= '1' & transmitt_buffer(transmitt_buffer'high downto 1); if bit_teller = 1 then sende_data <= stop_send; end if; end if; when stop_send => if bit_send = '1' then sende_data <= idle; end if; When others => sende_data <= idle; end case; end if; end process; tx <= transmitt_buffer(0); end Behavioral;
Trykk så "Add Source" og legg begge filene til prosjektet. På spørsmål om filtype velg "VHDL design file". Trykk så "Next".
Du vil nå få opp et sammendrag av prosjektet ditt. Trykk "Finish" og prosjektet vil bli generert.
Lage koden
Vi har nå en main fil samt en fil med klokkekode og en fil med transisjonskode. Neste steg bli å inkludere klokken og senderen i hovedfilene vår. Dobbeltklikk på filen "RS232_main.vhd" under "Module View" for å åpne filen for editering. Legg til følgende kodebit mellom "architecture .." og "begin":
--legger til komponenter component rs232_clk port ( clk : in std_logic; reset : in std_logic; clk_tx : out std_logic; bit_send : out std_logic); end component; component rs232_tx port ( clk_tx : in std_logic; reset : in std_logic; bit_send : in std_logic; send : in std_logic; data : in std_logic_vector(7 downto 0); tx : out std_logic; opptatt : out std_logic); end component; --definere interne signaler signal bit_send : std_logic; signal clk_tx : std_logic;
Etter begin legges følgende kodebit inn:
-- kobler klokke og tx signaler til rs232_main entity sig. klokke_gen: rs232_clk port map( clk, reset, clk_tx, bit_send); transmitt: rs232_tx port map( clk_tx, reset, bit_send, send, data, tx, opptatt);
Filen Media:RS232_main.vhd kan lastes ned ferdig hvis du er usikker på om du har lagt inn koden korrekt. Når du er ferdig med å redigere main filen tar du å lagrer prosjektet. Neste steg blir å test om koden er korekt. I "prosess View" vinduet går du til "Design Utilities" og dobbelklikker på "Check Syntax for Simulation". Har du gjort alt korekt skal du ikke få noen feilmelding nå. I "Module view" kan du også se at RS232_clk og RS232_tx har blitt underordnet RS232_main.
Legge til pinner
Neste steg er å legge til "user constraints" som i vårt tilfelle betyr å definere hvilke pinner som skal til hviken port. I "Module View" menyen markerer du filen RS232_main.vhd da det er denne filen du ønsker å legge "User Constraints" til. Når filen er markert går du til "Prosess View" vinduet og velger "User Constraints" menyen. Dobbeltklikk på "Assign Package Pins". Du vil nå få spørsmål om du vil legge til en UCF fil til prosjektet. Trykk "Yes". Du får nå opp et nytt vindu. I "Design Object List" vinduet har du en oversikt over alle IO porter i prosjektet ditt. Vi skal nå legge inn pinnr i "Loc" til hver av portene. Legg til følgene:
Når du er ferdig lagrer du og avslutter hele 2Xilinx Pace" vinduet. Du har nå fått generert en UCF fil til prosjektet ditt som inneholder følgende:
#PACE: Start of Constraints generated by PACE #PACE: Start of PACE I/O Pin Assignments NET "clk" LOC = "B13" ; NET "data<0>" LOC = "AD11" ; NET "data<1>" LOC = "AC12" ; NET "data<2>" LOC = "AC13" ; NET "data<3>" LOC = "AD13" ; NET "data<4>" LOC = "AC14" ; NET "data<5>" LOC = "AD14" ; NET "data<6>" LOC = "AC15" ; NET "data<7>" LOC = "AB7" ; NET "opptatt" LOC = "AE9" ; NET "reset" LOC = "AB9" ; NET "send" LOC = "AA11" ; NET "tx" LOC = "T7" ; #PACE: Start of PACE Area Constraints #PACE: Start of PACE Prohibit Constraints #PACE: End of Constraints generated by PACE
Sythesisering og Implementering
Neste steg blir å Synthesiserer og implementere deisgnet vårt. Marker igjen filen RS232_main.vhd i "Module View" vinduet og dobbeltklikk på "Genreate Programming File" i "Process View". Du vil nå få generert en bit fil som kan lastes over i FPGA'en.
Programmering og testing
Vi skal nå programmere FPGA'en. Sørg for at det er strøm på kortet og at programmeringsadapterert er koblet til. Start også hyperterminal med med en baudrate på 9600kbps. Gå til "Process View" og dobeltklikk på "Configure Device(iMPACT). Du åpner nå iMPACT programmet. På spørsmålom konfigurerig velg "Boundary-Scan mode". I neste vindu velger du automatisk tilkobling. Trykk så "Finish". iMPACT vil nå automatisk sjekke hvor mange og hvilke type FPGA'er som er koblet til programmeringsadapterert. Du vil få et vindu som sier at en enhet er funnet. Trykk "Ok". Du får nå opp et vindu der du blir bedt om å tilordne en new configureringsfil. Velg filen rs232_main.bit. Du får nå opp en advarsel. Ignorer denne og trykk "Ok". Høyreklikk på bildet av Virtex4 og velg "porgram...". Trykk så "Ok". Du vil nå programere FPGA'en.
Hvis du nå trykker "Push2" bryteren vil du få bittmønsteret til DIP-bryterene oversendt til hyperterminal som ASCII kode. Du har nå suksessfult laget og implementert VHDL kode med ISE.