no way to compare when less than two revisions
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | projekte:fpga_hello_world_on_novena [06.02.2015 03:03] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Hello World with FPGA on the Novena Board====== | ||
+ | ===== Introduction ===== | ||
+ | |||
+ | The FPGA is an interesting part of the Novena board but it needs some effort to get started. I just started development on the FPGA myself so I hope I still remember most of the pitfalls ;) | ||
+ | |||
+ | The FPGA can be seen as a lot of logic blocks (AND/ | ||
+ | |||
+ | For the Spartan6 FPGA on the Novena we will use the [[http:// | ||
+ | |||
+ | ===== Project Setup ===== | ||
+ | |||
+ | |||
+ | Now that you have installed and registered ISE (it will ask you to create a license file on first start) you can create a new Project. Select HDL as Top-level source type. | ||
+ | |||
+ | In the next Screen you have to define some FPGA-Settings: | ||
+ | |||
+ | * Family: Spartan6 | ||
+ | * Device: XC6SLX45 | ||
+ | * Package: CSG324 | ||
+ | * Speed: -3 | ||
+ | * Preferred Language: VHDL (you can select Verilog here if you are familiar with it but you will have to translate the VHDL code to Verilog) | ||
+ | |||
+ | {{:: | ||
+ | |||
+ | Confirm the next screen and you should get an empty Project Navigator window. | ||
+ | |||
+ | ===== VHDL-Code ===== | ||
+ | |||
+ | |||
+ | Right click on the xc6slx45-3csg324 folder and create a new file. Select "VHDL Module" | ||
+ | |||
+ | * clk_n: negative pair of the LVDS clock signal (will be explained later) | ||
+ | * clk_p: positive pair of the LVDS clock signal | ||
+ | * ledA: output to control led A on the GPBB | ||
+ | * ledB: output to control led B on the GPBB | ||
+ | * ledC: output to control led C on the GPBB | ||
+ | * ledD: output to control led D on the GPBB | ||
+ | |||
+ | Those signals are only one bit wide so we only need to set the direction and can ignore the MSB/LSB and Bus collumns. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Now ISE should have created an VHDL file for us with the following content: | ||
+ | |||
+ | <code vhdl> | ||
+ | -- Company: | ||
+ | -- Engineer: | ||
+ | -- | ||
+ | -- Create Date: 16:43:49 02/ | ||
+ | -- Design Name: | ||
+ | -- Module Name: blink - Behavioral | ||
+ | -- Project Name: | ||
+ | -- Target Devices: | ||
+ | -- Tool versions: | ||
+ | -- Description: | ||
+ | -- | ||
+ | -- Dependencies: | ||
+ | -- | ||
+ | -- Revision: | ||
+ | -- Revision 0.01 - File Created | ||
+ | -- Additional Comments: | ||
+ | -- | ||
+ | ---------------------------------------------------------------------------------- | ||
+ | library IEEE; | ||
+ | use IEEE.STD_LOGIC_1164.ALL; | ||
+ | |||
+ | -- Uncomment the following library declaration if using | ||
+ | -- arithmetic functions with Signed or Unsigned values | ||
+ | --use IEEE.NUMERIC_STD.ALL; | ||
+ | |||
+ | -- Uncomment the following library declaration if instantiating | ||
+ | -- any Xilinx primitives in this code. | ||
+ | --library UNISIM; | ||
+ | --use UNISIM.VComponents.all; | ||
+ | |||
+ | entity blink is | ||
+ | Port ( clk_n : in STD_LOGIC; | ||
+ | clk_p : in STD_LOGIC; | ||
+ | ledA : out STD_LOGIC; | ||
+ | ledB : out STD_LOGIC; | ||
+ | ledC : out STD_LOGIC; | ||
+ | ledD : out STD_LOGIC); | ||
+ | end blink; | ||
+ | |||
+ | architecture Behavioral of blink is | ||
+ | |||
+ | begin | ||
+ | |||
+ | |||
+ | end Behavioral; | ||
+ | </ | ||
+ | |||
+ | We will need the commented out library declarations so uncomment the '' | ||
+ | |||
+ | Right now the Code does not do much. To let it do something usefull we need a timesource and thankfully the Novena Board provides one for us but it is a differntial Signal so we need to intepret it and buffer it to be userd in our code to do so we define a signal that we will use as a clock source in the architecture block: | ||
+ | |||
+ | <code vhdl> | ||
+ | architecture Behavioral of blink is | ||
+ | signal clk: STD_LOGIC; | ||
+ | begin | ||
+ | </ | ||
+ | |||
+ | And feed the two differntial signals'' | ||
+ | |||
+ | <code vhdl> | ||
+ | begin | ||
+ | IBUFGDS_inst : IBUFGDS | ||
+ | | ||
+ | | ||
+ | | ||
+ | ) | ||
+ | |||
+ | port map ( | ||
+ | O => clk, -- clock buffer output | ||
+ | I => clk_p, | ||
+ | IB => clk_n -- diff_n clock buffer input | ||
+ | ); | ||
+ | |||
+ | end Behavioral; | ||
+ | </ | ||
+ | |||
+ | Now that we have a '' | ||
+ | |||
+ | This defines a 32 bit wide signal ('' | ||
+ | |||
+ | To increase the counter on each clock cycle we need to add a process in the architecture block that listens on the clk signal and changes the counter on each rising edge: | ||
+ | |||
+ | <code vhdl> | ||
+ | process(clk) | ||
+ | begin | ||
+ | if rising_edge(clk) then | ||
+ | if counter(31) = ' | ||
+ | counter <= (others => ' | ||
+ | else | ||
+ | counter <= std_logic_vector(unsigned(counter) + 1); -- increase counter if not | ||
+ | end if; | ||
+ | end if; | ||
+ | end process; | ||
+ | end Behavioral | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | Now we have a signal '' | ||
+ | |||
+ | So to have some leds blink just add an assigment to those leds at the end of the behaviour block (the '' | ||
+ | |||
+ | <code vhdl> | ||
+ | ledA <= counter(25); | ||
+ | ledB <= NOT counter(26); | ||
+ | ledC <= counter(27); | ||
+ | ledD <= NOT counter(28); | ||
+ | end Behavioral; | ||
+ | </ | ||
+ | |||
+ | The final code should look like this: | ||
+ | |||
+ | <code vhdl> | ||
+ | ---------------------------------------------------------------------------------- | ||
+ | -- Company: | ||
+ | -- Engineer: | ||
+ | -- | ||
+ | -- Create Date: 16:43:49 02/ | ||
+ | -- Design Name: | ||
+ | -- Module Name: blink - Behavioral | ||
+ | -- Project Name: | ||
+ | -- Target Devices: | ||
+ | -- Tool versions: | ||
+ | -- Description: | ||
+ | -- | ||
+ | -- Dependencies: | ||
+ | -- | ||
+ | -- Revision: | ||
+ | -- Revision 0.01 - File Created | ||
+ | -- Additional Comments: | ||
+ | -- | ||
+ | ---------------------------------------------------------------------------------- | ||
+ | library IEEE; | ||
+ | use IEEE.STD_LOGIC_1164.ALL; | ||
+ | |||
+ | -- Uncomment the following library declaration if using | ||
+ | -- arithmetic functions with Signed or Unsigned values | ||
+ | use IEEE.NUMERIC_STD.ALL; | ||
+ | |||
+ | -- Uncomment the following library declaration if instantiating | ||
+ | -- any Xilinx primitives in this code. | ||
+ | library UNISIM; | ||
+ | use UNISIM.VComponents.all; | ||
+ | |||
+ | entity blink is | ||
+ | Port ( clk_n : in STD_LOGIC; | ||
+ | clk_p : in STD_LOGIC; | ||
+ | ledA : out STD_LOGIC; | ||
+ | ledB : out STD_LOGIC; | ||
+ | ledC : out STD_LOGIC; | ||
+ | ledD : out STD_LOGIC); | ||
+ | end blink; | ||
+ | |||
+ | architecture Behavioral of blink is | ||
+ | signal clk: STD_LOGIC; | ||
+ | signal counter: STD_LOGIC_VECTOR(31 downto 0) :=(others => ' | ||
+ | begin | ||
+ | IBUFGDS_inst : IBUFGDS | ||
+ | generic map ( | ||
+ | IBUF_LOW_PWR => TRUE, | ||
+ | IOSTANDARD => " | ||
+ | ) | ||
+ | |||
+ | port map ( | ||
+ | O => clk, -- clock buffer output | ||
+ | I => clk_p, | ||
+ | IB => clk_n -- diff_n clock buffer input | ||
+ | ); | ||
+ | |||
+ | process(clk) | ||
+ | begin | ||
+ | if rising_edge(clk) then | ||
+ | if counter(31) = ' | ||
+ | counter <= (others => ' | ||
+ | else | ||
+ | counter <= std_logic_vector(unsigned(counter) + 1); -- increase counter if not | ||
+ | end if; | ||
+ | end if; | ||
+ | end process; | ||
+ | |||
+ | |||
+ | ledA <= counter(25); | ||
+ | ledB <= NOT counter(26); | ||
+ | ledC <= counter(27); | ||
+ | ledD <= NOT counter(28); | ||
+ | end Behavioral; | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Connecting the Code to the "real world" ===== | ||
+ | |||
+ | Now we have defined the logic for the FPGA and it would run happily on the FPGA but we still need to connect it to the outside world to see some effect. To do this we need to create a " | ||
+ | nstraints File" that describes the connection of the signals in the '' | ||
+ | |||
+ | So right click on your '' | ||
+ | |||
+ | {{: | ||
+ | |||
+ | You should receive an empty file where you define your networks: | ||
+ | |||
+ | <code ucf> | ||
+ | #the led pins | ||
+ | |||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | | ||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | | ||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | |||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | |||
+ | #the differential clock signal is provided at pin H1 and H2 | ||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | NET " | ||
+ | | ||
+ | NET " | ||
+ | | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | | ||
+ | If you want to use other pins have a look at [[ http:// | ||
+ | |||
+ | ===== Generate Programming File ===== | ||
+ | |||
+ | Now you are almost ready to generate the programming file but you have to change some configuration setting first right click on the " | ||
+ | |||
+ | {{: | ||
+ | |||
+ | The Novena does not seem to like it if all unused pins are pulled down and crashes if you don't change this setting. | ||
+ | |||
+ | Now you can right-click on the " | ||
+ | |||
+ | {{: | ||
+ | |||
+ | ===== Upload to FPGA ===== | ||
+ | |||
+ | To upload the '' | ||
+ | |||
+ | <code sh> | ||
+ | gcc devmem2.c -o devmem2 | ||
+ | </ | ||
+ | |||
+ | Then upload your bit file to the FPGA | ||
+ | |||
+ | <code sh> | ||
+ | sudo ./ | ||
+ | </ | ||
+ | |||
+ | After the upload is completed the LEDs should blink " |