Forum Discussion
A very basic newbie question
Hi All
I have a very basic question. I've recently started learning about CPLD and VHDL. My VHDL code usually compiles and simulates fine, but when I put it in an actual CPLD it behaves really strange. I'm sure you have all been there. Could you please solve this mystery for me? Basically what I am doing is dividing the global clock by 500, and incerementing a counter to show the value on a seven segment. This is the very simple code, I am using MAX EPM7128SLC84-15:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
-- this is the entity
Entity V2 Is
Port (
GClk : In std_logic; --Global clock, pin 83
SS : Out std_logic_vector(6 Downto 0); -- Connected to the Seven Segement
);
End V2;
Architecture RTL of V2 is
Signal MyClk : std_logic; -- The divided clock
Signal SevSegVal : std_logic_vector(6 downto 0);
Begin
Process (GClk)
Variable Count : Integer Range 0 To 1023 := 0;
Begin
If (rising_edge(GClk)) Then
Count := Count + 1;
If (Count = 500) Then
Count := 0;
MyClk <= Not MyClk;
End If;
End IF;
End Process;
PROCESS (MyClk)
Variable Counter : Integer Range 0 To 9 := 0;
Type SSValues Is array(integer range 0 to 9) Of std_logic_vector(6 downto 0);
Variable Values : SSValues := (('1', '0', '0', '0', '0', '0', '0')
, ('1', '1', '1', '1', '0', '0', '1')
, ('0', '1', '0', '0', '1', '0', '0')
, ('0', '1', '1', '0', '0', '0', '0')
, ('0', '0', '1', '1', '0', '0', '1')
, ('0', '0', '1', '0', '0', '1', '0')
, ('0', '0', '0', '0', '0', '1', '0')
, ('1', '1', '1', '1', '0', '0', '0')
, ('0', '0', '0', '0', '0', '0', '0')
, ('0', '0', '1', '0', '0', '0', '0')); -- To hold the bit pattern for the seven segment numbers
Begin
If (rising_edge(MyClk)) Then
SevSegVal <= Values (Counter);
If (Counter = 9) Then
Counter := 0;
Else
Counter := Counter + 1;
End IF;
End If;
End Process;
SS <= SevSegVal;
End RTL;
This code simulates fine in Quartus II using a vector waveform file. But doesn't work properly when I upload it to my development board. The problem is the the seven segment flickers. I can see it count, but the lamps that are supposed to be off for each number flicker dimly. From what I can see, Quartus II (v 8.0) synthesizes this code to a latch which is clocked by MyClk, which goes to high impedance during the wait and causes the lines to float and flicker. Am I right? To me, it seems I am violating some 'well-known' rules for writing synthesizable code that actually works in real hardware. What am I doing wrong? What is the correct way of dividing a clock and incrementing a seven segment counter? I really really appreciate your help.13 Replies
- Altera_Forum
Honored Contributor
In theory setting the unused pins to output should have worked, but as batfink suggested, I think a few of the I/O pins that were connected to the microcontroller started misbehaving. A lesson learned.
This what you get with a poorly designed board and absolutely no documentation. Thanks guys for all your help! - Altera_Forum
Honored Contributor
Always follow the instructions in the .pin file regardless of the setting for unused pins.
You still need to follow the instructions in the .pin file with the unused pins set to "As input tri-stated". The .pin file probably tells you to ground unused pins. If they are left unconnected, the input buffers will float. That can cause oscillations on input buffers, which can result in a high I/O current, noise, and degraded reliability. For device families that have the option "As input tri-stated with bus-hold circuitry" for unused pins, I recommend that. For device families without that option, I recommend "As input tri-stated with weak pull-up resistor". With either of these settings, it is OK to leave unused pins unconnected and also OK to have them driven either high or low by something else on the board. - Altera_Forum
Honored Contributor
Good to hear you solved your problem Haplo.
Your chip obviously has more pins than you are actually using in your FPGA design. Previously the pins that you weren't using in the FPGA were driving low because of that setting. Either one of those pins is driving some output on some other chip or has a short to something nasty and causing weird behaviour. Personally I usually make sure that I set unused pins to tri-state. If you had a load of tracks that are connected to unused stuff which might cause signal integrity problems if left floating, then you could fix these to a safe level in your design. If all is working then you probably don't need to worry about this - leave unused pins as tri-state. Well done. Batfink - Altera_Forum
Honored Contributor
--- Quote Start --- Thanks for all your answers, very informative. I have improved my code a lot. All my problems went away (even using the original code) when I changed the policy for unused pins from "As output driving an unspecified signal" to "As input tri-stated ". Anyone knows why? --- Quote End --- The default setting of Quartus for unused pins ( Output driving ..) is dangerous in case of FPGA boards with external components. It is very likely that unused FPGA outputs will drive against ouputs of other components. - Altera_Forum
Honored Contributor
Thanks for all your answers, very informative. I have improved my code a lot.
All my problems went away (even using the original code) when I changed the policy for unused pins from "As output driving an unspecified signal" to "As input tri-stated ". Anyone knows why? - Altera_Forum
Honored Contributor
--- Quote Start --- The design uses a ripple clock, which would cause timing issues if the primary GCLK shall be used in connection with the derived MyClk. Cause both clock domains are strictly separated, it's O.K. --- Quote End --- --- Quote Start --- Although in principle there is nothing necessarily wrong with using two clocks as you have done, clocks/global signals are generally not in abundance in FPGAs/PLDs. Personally I would generate a clock enable pulse rather than another clock and then use a clock enabled register to drive the display. --- Quote End --- Even though it's apparently not critical for this design, in general you should follow batfink's advice. See http://www.alteraforum.com/forum/showthread.php?t=2388 for more information about driving clocks with registers or combinational logic versus using the preferred clock enable. - Altera_Forum
Honored Contributor
Try OrchestraDirector's idea of slowly toggling the LED pin; also try this (as well as tying it as you have done) without driving the 7 segment display. It would be interesting to see if it's a dynamic problem or just that the board is statically flaky.
How much current does the seven segment take? Is this within the device spec? Sounds like more of a board than a PLD problem. Good luck - Altera_Forum
Honored Contributor
Just a couple of clues for you.
1) when usinglow frequencies try to drive your led with the clock signal (pull it out from the CPLD) and see if it goes ON/OFF regularly, it is a very simple "oscilloscope". You may try to measure the DC voltage with a digital multimeter on both the divided clock (you should measure Vcc/2 with higher frequencies or discriminate the two logic levels with very low frequencies) and the original clock generated by the microcontroller. 2) use a 22ohm resistor in series with the clock input signal to the CPLD, it may reduce or cancel some unwanted signal bouncings. Without an oscilloscope is a bit hard, but you can do it! Good luck. - Altera_Forum
Honored Contributor
Thanks a lot for all your responses. As you predicted, changing variables to signals didn't make any differece, even the RTL netlist stayed exactly the same.
As for the frequency of the board, that is one problem, I am not exactly sure. I am using an obscure Chinese board called SY_03091 with virtually no documentation. The clock to the CPLD is created using a HT46R47 microcontroller and a 4MHz crystal. I do have the source code of the firmware, but it looks like it was written by a elementary school student. They used delay loops to create the clock pulses and the code is full of magic numbers. The fact that the value of a pot (through an A/D) changes the clock frequency (by changing the number of loop iterations!) doesn't help either. Unfortunately I don't have an oscilloscope to check measure the pulses. Dividing the clock by 500 made the numbers on the seven segments change every 700ms. So I don't think the speed is a problem. I changed it to 10000 and that resulted in 14 seconds between the increments. I'll try to explain how it looks like in those 14 seconds: Let's assume the seven segment is showing the number '1'. For a couple of seconds, '1' is shown nice and clean. Then for two seconds, the other lamps of the seven segment flicker dimly and then they go off again, only to flicker a few seconds later. This continues until the number changes to '2' and the same process all over again. I tried the clock enable method that was suggested and the end result was exactly the same. To test further, I also defined another std_logic output called LED connected to a LED on the board, and added the following line at the very end:
Looking at the RTL netlist, the LED pin is tied to VCC, but even the LED flickers! I really don't understand what is happening. If I comment out the "Counter := Counter + 1;" line, the seven sgement stays at a clean '0' with no flicker and the LED stays completely off too. Anybody has any idea what is happening? Thanks.SS <= SevSegVal; LED <= '1'; -- Keep the LED always off End RTL; - Altera_Forum
Honored Contributor
I agree with FvM and OrchestraDirector - using variables rather than signals should make no difference (check your roll-over though - I have a feeling that you may not actually display the digit 9).
What is your master clock speed? Try slowing that down. Although in principle there is nothing necessarily wrong with using two clocks as you have done, clocks/global signals are generally not in abundance in FPGAs/PLDs. Personally I would generate a clock enable pulse rather than another clock and then use a clock enabled register to drive the display. Have you set a clock frequnecy in Quartus? Are there any timing violaations? Have you tried a gate level simulation? I can't see any glaring errors in your code - it looks basically OK. Cheers batfink