Sunteți pe pagina 1din 22

Page 1 of 22

Digital System Design using VHDL and the Spartan-3E FPGA Board
Gennadiy Chernyavskiy Tech 499 12/06/06

Page 2 of 22

Contents
Chapter 2: A Design Example 2.1 Design Description..3 Chapter 3: Design Implementation using Xilinx 3.1 Introduction....4 3.2 Procedure for programming the Spartan-3E..5 References17 Appendix A: VHDL code.18 Appendix B: UCF.22

Page 3 of 22

Chapter 2
2.1 Design Description
The goal of the project is to design a digital system for controlling the tail lights of a 1965 Ford Thunderbird using VHDL and synthesizing the logic circuit into a Spartan-3E FPGA board. The sequence of the lights for a 1965 Ford Thunderbird is shown in Figure 1-1.

Figure 1-1: The sequence of the lights for a 1965 Ford Thunderbird. In order to get this project functioning, we first wrote a VHDL file called tail_light.vhd (copy of this file is provided in Appendix A). The board has a 50MHz oscillator (see [2] pages 22-23); therefore, the clock signal is so fast that the human eye is unable to see the sequence of the flashing lights. As a consequence, we have to add an additional file called counter.vhd (copy of this file is provided in Appendix A), which will slow the incoming clock down. In order for these two files to work together, we have to write the top_level.vhd (copy of this file is provided in Appendix A). A step by step tutorial will explain how to load this project into the Xilinx board. Note: First the user should apply power and then connect the USB cable to the Spartan3E board. If any change is done to the (vhdl) code, the user should first remove the USB cable, second remove power, third reapply power to the Spartan-3E board and last reconnect the USB cable. At this point it is safe to reload the modified code into the Xilinx board.

Page 4 of 22

Chapter 3
3.1 Introduction
In order to create a project to program the Spartan-3E FPGA, it is necessary to take a few preliminary steps. First, a project needs to be created in Xilinx. The project is named tail_light. Then the specific characteristics of the hardware that are being used are selected as shown in Figure 3-1.

Figure 3-1: Project Properties Window Finally, the source files counter.vhd, tail_light.vhd, and top_level.vhd are selected as the source code to be used to program the Spartan-3E FPGA.

Page 5 of 22

3.2 Procedure for Programming the Spartan-3E FPGA


STEP 1: Select the tail_light folder in the CD-ROM and copy to the C:\ drive of your computer. Then double click on the highlighted icon shown below. This will open the Xilinx Project Navigator window.

Figure 3-2: tail-light project Once the Xilinx Project Navigator window opens there will be 4 windows available for you to see.

Page 6 of 22

1 2 3

Figure 3-3: Four windows Window 1: The Sources Project window lists the name of files that constitutes the project tail_light. Window 2: Displays the files source code. Here the user can write new code or make changes to existing code. Window 3: The Processes window shows the different process that can be done to the selected code. Here the user can compile the source code, generate synthesis reports, generates a file for an FPGA, and download files to an FPGA. Window 4: The log window displays any messages from the processes window. For example, after Xilinx checks the syntax of a given source code, it will display the results of that process. STEP 2: The tail_light project requires the use of 7 LEDs and 4 switches. It is necessary to assign pins from the Spartan-3E FPGA to these components. For this project, switches SW1, SW2, SW3, and SW4 are used for input from the user as shown in Figure 3-4.

Page 7 of 22 Four Switches

Figure 3-4: Switches used for Left, Right, Hazard, and Reset signals Pin assignments for the switches: NET "SW<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ; NET "SW<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ; NET "SW<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ; NET "SW<3>" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP ; Taken from Spartan 3-E Starter User Guide (see Reference Manual pages 159-164)

Page 8 of 22 LEDs - LD1, LD2, LD3, LD4, LD6, LD7, and LD8 are used as output as shown in Figure 3-5. Eight Discrete LEDs

Figure 3-5: Eight LEDs UCF Constraints for Eight Discrete LEDs NET "LED<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 NET "LED<6>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 NET "LED<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 NET "LED<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 NET "LED<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 NET "LED<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 NET "LED<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 NET "LED<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 Taken from Spartan 3E Starter User Guide (see Reference Manual pages 159-164)

Page 9 of 22 Using the three pinout tables, it is possible to assign a switch or LED to a pin on the Spartan-3E. The clock signal comes from an oscillator found on the Spartan-3E board as shown in Figure 3-6. Pin C9 on the Spartan-3E is the designated pin for the clock signal input.

On-Board 50 MHz Oscillator CLK_50MHz: (C9)

Figure 3-6: 50 MHz Oscillator. STEP 3: Make sure that top_level-struct is selected in the Sources window. Then expand the User Constraints in the Processes window and double click Assign Package Pins. This is where you tell Xilinx which pins on the Spartan-3E will be used (see Figure 3-7).

Page 10 of 22

Figure 3-7: User Constrains A program named Xilinx PACE will open. In the Design Object List I/O Pins window type in the following pin assignments under the heading Loc (see Figure 3-8).

Page 11 of 22 Figure 3-8 When finished, click the save icon. This action will create the .ucf file for the top_levelstruct file and it will contain the pin assignments for the Spartan-3E. STEP 4: Again, make sure that top_level-struct is selected in the Sources window. Then, in the Processes window, expand the Synthesize-XST process and then double click it. This action will check the syntax of the source code for top_level-struct and convert the source code into a netlist of gates. A synthesis report will also be produced. When the synthesis is finished, green check marks should be displayed just like in Figure 3-9, indicating that top_level-struct has been compiled successfully.

Figure 3-9 STEP 5: Expand the Implement Design process and double click on it. This is where the netlist is translated, mapped, placed and routed into the logic circuits of the Spartan3E FPGA. After this process has been run, green check marks should be displayed just like in Figure 3-10.

Page 12 of 22

Figure 3-10 STEP 6: Expand the Generate Programming File process. Right click on Generate Programming File and select Create Bit File. Double click Generate Programming File. This process creates a bit file that is used to program the Spartan-3E chip. Again, after this process is finished, green check marks should be shown as in Figure 3-11.

Page 13 of 22

Figure 3-11 Step 7: Now you are ready to program the Spartan-3E chip. Plug in the USB cable to the computer. Connect the Spartan-3E board to power FIRST, and then connect the USB cable to the board. This order must be followed for the Spartan-3E chip to be programmed properly. Step 8: Now double click on Configure Device (iMPACT) under the Generate Programming File process. You will be asked how you want the device configured. Select Boundary Scan Mode and click Next. Then select Automatically connect to cable and identity Boundary Scan Chain and click Finish as shown in Figure 3-12.

Page 14 of 22

Figure 3-12. The following window will display and ask you to select a bit file (See Figure 3-13).

Page 15 of 22

Figure 3-13 Open the top_level.bit file. Should a warning appear declaring that the Startup Clock has been changed to the jtagclk, disregard the warning and click OK. Step 9: Right click on the depiction of the Spartan 2 chip and select Program (see Figure 3-14).

Page 16 of 22

Figure 3-14 A Programs Options window will open. Simply click OK and the top_level.bit file will be downloaded to the Spartan-3E chip. If the download is successful, the message

will display. Also, LD should be blinking. This is the output from the counter and is used for testing purposes. Step 10: Now it is time to test the program. Turn on the reset button (switch SW4) and then turn it back off. The following table shows the correct outputs with the corresponding inputs from the user. As the inputs are applied, only the left and right signals should flash sequentially. The hazard signal, the left and right signal combined, should flash concurrently.

Page 17 of 22

Left Off Off Off On On On On Off

Input Right Off Off On On Off Off On On

Hazard Off On On On On Off Off Off

Output LD1, LD2, LD3, LD6, LD7, LD8 No output Hazard signals on Hazard signals on Hazard signals on Hazard signals on Left signal on Left signal on Right signal on

After it has been verified that the given inputs produce the proper output, the project is complete.

References
[1] Full Spartan-3E Documentation http://www.digilentinc.com/Products/Detail.cfm?Prod=S3EBOARD&Nav1=Prod ucts&Nav2=Programmable Spartan-3E Starter User Guide (Reference Manual) http://www.digilentinc.com/Data/Products/S3EBOARD/S3EStarter_ug230.pdf Spartan-3E Board (Schematic Diagram) http://www.digilentinc.com/Data/Products/S3EBOARD/S3E%20Starter_sch.pdf

[2] [3]

Page 18 of 22

Appendix A: VHDL code


The following appendix shows the VHDL code used for the tail_light project.
--file:top_level.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity top_level is port(l_r_haz :in std_logic_vector(2 downto 0); clk : in std_logic; rst : in std_logic; lights : out std_logic_vector(5 downto 0); clkdiv : out std_logic ); end top_level; architecture struct of top_level is component counter port (clk, rst : in std_logic; countOut : out std_logic ); end component; component tail_light port ( l_r_haz : in std_logic_vector(2 downto 0); clk : in std_logic; rst : in std_logic; lights : out std_logic_vector(5 downto 0) ); end component; --signal declaration signal countOut : std_logic; signal l_r_haz_in : std_logic_vector(2 downto 0); begin inst_counter: counter port map ( clk => clk, rst => rst, countOut => countOut ); inst_tail_light: tail_light port map ( l_r_haz => l_r_haz_in, rst => rst, clk => countOut, lights => lights ); l_r_haz_in <= l_r_haz; clkdiv <= countOut; end struct; --------------------------------------------------------------------------------file:counter.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity counter is port ( clk, rst : in std_logic; countOut : out std_logic ); end counter; architecture rtl of counter is begin process(rst, clk) variable count : unsigned(23 downto 0); begin if rst = '1' then count := (others =>'0');

Page 19 of 22
elsif (clk ='1' and clk'event) then count := count + 1; end if; countOut <= count(23); end process; end rtl; --------------------------------------------------------------------------------file: tail_light.vhd library ieee; use ieee.std_logic_1164.all; entity tail_light is port (l_r_haz : in std_logic_vector(2 downto 0); clk : in std_logic; rst : in std_logic; lights : out std_logic_vector(5 downto 0) ); end tail_light; architecture rtl of tail_light is type state_t is (idle, leftOne, leftTwo, leftThree, rightOne, rightTwo, rightThree, lr); signal state, next_state : state_t; signal next_all_lights : std_logic_vector(5 downto 0); signal all_lights : std_logic_vector(5 downto 0);--oneLeft, twoLeft, etc. begin comb_logic : process(l_r_haz, state) begin next_state <= idle; next_all_lights <= (others => '0'); case state is when idle => if (l_r_haz = "000") then next_state <= idle; next_all_lights <= (others => '0'); elsif (l_r_haz = "001") then next_state <= lr; next_all_lights <= "111111"; elsif (l_r_haz = "100") then next_state <= leftOne; next_all_lights <= "001000"; elsif (l_r_haz = "010") then next_state <= rightOne; next_all_lights <= "000100"; elsif (l_r_haz = "110") then next_state <= leftOne; next_all_lights <= "001000"; elsif (l_r_haz = "101") then next_state <= lr; next_all_lights <= "111111"; elsif (l_r_haz = "011") then next_state <= lr; next_all_lights <= "111111"; elsif (l_r_haz = "111") then next_state <= lr; next_all_lights <= "111111"; end if; when leftOne => if (l_r_haz = "100") then next_state <= leftTwo; next_all_lights <= "011000"; elsif (l_r_haz = "001") then next_state <= lr; next_all_lights <= "111111"; elsif (l_r_haz = "110") then next_state <= leftTwo;

Page 20 of 22
next_all_lights <= "011000"; end if; when leftTwo => if (l_r_haz = "100") then next_state <= leftThree; next_all_lights <= "111000"; elsif (l_r_haz = "001") then next_state <= lr; next_all_lights <= "111111"; elsif (l_r_haz = "110") then next_state <= leftThree; next_all_lights <= "111000"; end if; when leftThree => if (l_r_haz = "100") then next_state <= idle; next_all_lights <= "000000"; elsif (l_r_haz = "001") then next_state <= lr; next_all_lights <= "111111"; elsif (l_r_haz = "110") then next_state <= idle; next_all_lights <= "000000"; end if; when rightOne => if (l_r_haz = "010") then next_state <= rightTwo; next_all_lights <= "000110"; elsif (l_r_haz = "001") then next_state <= lr; next_all_lights <= "111111"; end if; when rightTwo => if (l_r_haz = "010") then next_state <= rightThree; next_all_lights <= "000111"; elsif (l_r_haz = "001") then next_state <= lr; next_all_lights <= "111111"; end if; when rightThree => if (l_r_haz = "010") then next_state <= idle; next_all_lights <= "000000"; elsif (l_r_haz = "001") then next_state <= lr; next_all_lights <= "111111"; end if; when lr => if (l_r_haz = "001") then next_state <= idle; next_all_lights <= "000000"; elsif (l_r_haz = "000") then next_state <= idle; next_all_lights <= "000000"; end if; when others => -- do nothing end case; end process comb_logic; the_reg: process (clk, rst) begin if (rst = '1') then state <= idle;

Page 21 of 22
all_lights <= "000000"; elsif (clk ='1' and clk'event) then state <= next_state; all_lights <= next_all_lights; end if; end process the_reg; lights <= all_lights; end rtl;

Page 22 of 22

Appendix B: UCF (user constraints file)


#PACE: Start of Constraints generated by PACE #PACE: Start of PACE I/O Pin Assignments NET "clk" LOC = "C9" ; NET "clkdiv" LOC = "F12" | IOSTANDARD = LVTTL ; NET "l_r_haz<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ; NET "l_r_haz<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ; NET "l_r_haz<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ; NET "lights<0>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "lights<1>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "lights<2>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "lights<3>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "lights<4>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "lights<5>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "rst" LOC = "N17" | PULLUP ; #PACE: Start of PACE Area Constraints #PACE: Start of PACE Prohibit Constraints #PACE: End of Constraints generated by PACE #Do not forget: #Start User Defined Timing Constraints #End User Defined Timing Constraints

S-ar putea să vă placă și