I am trying to get a simple blinking LED program working on my FPGA and I am having problems. Instead of blinking the LED stays on the entire time. I tried writing my on but then I just copied an example program so I'm sure the program is fine.
Thi sis the board I am using: http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,836&Prod=ATLYS From what I've read you are supposed to use DCMs for all clock needs but in my example I have just attached my clock to the global clock which is supposed to be 100MHz.
Any help for my poor noobie self would be appreciated! Below is my code and my ucf which can be verified with the ucf listed at the above link.
By the way, do any of you know offhand how to import a DCM in ISE? I can figure out how to use it I just can't find an import reference.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity counter is
port( clk: in std_logic;
rst: in std_logic;
led: out std_logic;
led2: out std_logic;
sw0: in std_logic);
end counter;
architecture Behavioral of counter is
constant CLK_FREQ : integer := 1000000;
constant BLINK_FREQ : integer := 1;
constant CNT_MAX : integer := CLK_FREQ/BLINK_FREQ/2 - 1;
signal cnt : unsigned(24 downto 0);
signal blink : std_logic := '1';
begin
process(clk)
begin
if (clk='1' and clk'event) then
if cnt = CNT_MAX then
cnt <= (others => '0');
blink <= not blink;
else
cnt <= cnt + 1;
end if;
end if;
end process;
process(sw0)
begin
if sw0 = '1' then
led2 <= '1';
else led2 <= '0';
end if;
end process;
led <= blink;
end Behavioral;
ucf file
# Bank = 1, Pin name = IO_L42P_GCLK7_M1UDM, Type = GCLK, Sch name = GCLK
NET "clk" LOC = L15;
# Bank = 1, Pin name = IO_L52N_M1DQ15, Sch name = LD0
NET "led" LOC = U18;
# PlanAhead Generated physical constraints
NET "led2" LOC = M14;
NET "rst" LOC = F5;
NET "sw0" LOC = A10;
-
1\$\begingroup\$ Not gonna put this in an answer but you really should implement a proper reset in the clocked process that initializes the count to zero and sets the LED state. giving a signal a default works great in simulation, but it's not acceptable for hardware. Besides, you don't initialize your counter, even if defaults were acceptable. :-) \$\endgroup\$akohlsmith– akohlsmith2012年03月13日 03:25:17 +00:00Commented Mar 13, 2012 at 3:25
2 Answers 2
Have you simulated the code to make sure it does behave OK in the ideal world?
Also, 100MHz is quite a fast clock and unless you tell the tools that's how fast you want to go, you might find it doesn't work. The logfiles should report what the final timing numbers are. You don't need to use a DCM, but if you want to, in the libraries guide there is a sample VHDL instantiation template, or you can use CoreGen.
As others have said, it's conventional to use the rst
signal to reset your design, especially your counter. With FPGAs you can get them to startup in a known state. but it's often easier (especially to get it to match with simulation) to have an explicit reset. When you do this, check the polarity of the reset signal - sometimes they are active-high and sometimes active-low.
If you are using XST for synthesis, it should work fine with initial values. And even if it doesn't, the blink
inversion will work, it'll just start from '0' not '1'. And the counter will start from all-zeros.
So:
- Simulate the design, make sure it toggles in simulation first.
- Add a PERIOD constraint to the UCF file to put a 10ns constraint on the clk signal.
- Also, check the
.pad
file to see that the things you think you have constrained to the pins actually have gone on the right pins.
Yeah as Andrew mentioned in the comment, when you write the line
signal blink : std_logic := '1';
that is tying the signal blink to a logic high value. If you want to say that it starts as a '1' then use a reset signal clause:
if(reset = '1') then
--initial conditions
blink <= '1';
elsif (clk='1' and clk'event) then
if cnt = CNT_MAX then
cnt <= (others => '0');
blink <= not blink;
else
cnt <= cnt + 1;
end if;
end if;
as I believe most fpga boards pulse the reset signal when they go through a power cycle. Or at least the Spartan-3/4 demo boards that I've used do.
But expanding on why the default value doesn't make sense: If something is tied to a logic high value, it doesn't matter what else you drive it with, it is always going to be a pulled high signal.
Edit: So the two demo boards that I've used for the Spartan-3 and Spartan-4 have a push button labelled reset. It is a normally off button that has a pull-up resistor attached to the pin. So when the reset button is pushed it bring the reset signal to ground. That means reset is an active low signal. However, for readability in my code, I generally try to make signals active high. So my ucf file will have the following net statement:
net swrst loc=D15; # xst-3 RESET pushbutton
and then in my top level entity I will create a global reset signal:
signal reset : std_logic;
...
...
...
reset <= not swrst;
All the reset signals for any components I use can now be driven by my active high global reset signal.
-
\$\begingroup\$ "Most fpga boards pulse the reset signal..." — Can you give me some more information about it, please? How can I use this feature in my code? Let's say I have several blocks and all of them has async. reset. So sould I tied up all resets and define this line in UCF? \$\endgroup\$vasco– vasco2012年03月13日 09:26:38 +00:00Commented Mar 13, 2012 at 9:26
-
\$\begingroup\$ Sure, see my edit. \$\endgroup\$NickHalden– NickHalden2012年03月13日 19:17:33 +00:00Commented Mar 13, 2012 at 19:17
-
\$\begingroup\$ No, that doesn't drive the signal high. It just sets the power-up value (if the signal happens to end up in a flip-flop, otherwise it will be ignored). \$\endgroup\$Ben Voigt– Ben Voigt2012年03月13日 23:09:19 +00:00Commented Mar 13, 2012 at 23:09
-
\$\begingroup\$ @BenVoigt which part is that in reference to? \$\endgroup\$NickHalden– NickHalden2012年03月14日 12:58:00 +00:00Commented Mar 14, 2012 at 12:58
-
\$\begingroup\$ @JGord: Your first paragraph. \$\endgroup\$Ben Voigt– Ben Voigt2012年03月14日 13:51:55 +00:00Commented Mar 14, 2012 at 13:51