I'm new to VHDL and FPGAs but need to learn how to program with it for my graduate studies. I decided to try out the tutorials and labs on Altera's web site to get a start and have managed to work my way up to this lab. (Btw, if anyone has any other tutorials, books you'd recommend to a beginner, I'd love to hear about them).Anyway, I got up to Lab 4, Part 4. In order to get it to work I've used a 26-bit counter from the megafunctions library. 50 000 000 clock cycles (10111110101111000010000000 in binary) from the CLOCK_50 MHz signal corresponds to 1 sec of course. After the counter reaches this point through value Count, I increment the Num signal and assert the Clear signal in the counter, otherwise the Clear signal remains off. I also have an if statement to keep the Num within 0-9 on the 7-segment display. My logic can be seen in the top level code below.
LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; ENTITY part4 IS PORT ( HEX0 : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); CLOCK_50 : IN STD_LOGIC); END part4; ARCHITECTURE Behavior OF part4 IS COMPONENT num_7seg PORT ( M : IN STD_LOGIC_VECTOR(3 DOWNTO 0); Display : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)); END COMPONENT; COMPONENT megacounter PORT (aclr : IN STD_LOGIC ; clock : IN STD_LOGIC ; cnt_en : IN STD_LOGIC ; q : OUT STD_LOGIC_VECTOR (25 DOWNTO 0)); END COMPONENT; SIGNAL Count : STD_LOGIC_VECTOR(25 DOWNTO 0); SIGNAL Num : STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL Clear : STD_LOGIC; BEGIN A0: megacounter PORT MAP (Clear, CLOCK_50, '1', Count); PROCESS (Count) BEGIN IF (Count = "10111110101111000010000000") THEN Num <= Num + '1'; Clear <= '1'; IF (Num > "1001") THEN Num <= "0000"; END IF; ELSE Clear <= '0'; END IF; END PROCESS; D0: num_7seg PORT MAP (Num,HEX0); END Behavior;Everything compiles fine but for whatever reason, the 7-segment display remains stuck at zero. Nothing is wrong with my num_7seg function, as I have tested it in the previous lab sections and I have imported the correct assignments in. Any help would be appreciated. Thanks.
I'm not sure how this would synthesize, but you should make your process clocked instead of depending on the counter. What you are describing here is to keep on increasing num as long as the count vector is at that value, not just increase it once when you reach the value. This code will probably generate a combinatorial loop that will give unpredictable results.So the first rule is to make your process dependent on the clock only:
PROCESS (CLOCK_50)And then in the process, only accomplish what you want on the rising edge of the clock
BEGIN IF rising_edge(CLOCK_50) THEN IF (Count = "10111110101111000010000000") THEN Num <= Num + '1'; Clear <= '1'; IF (Num > "1001") THEN Num <= "0000"; END IF; ELSE Clear <= '0'; END IF; END IF; END PROCESS;Please note that doing it that way will add one cycle latency between the counter and your process. The value you will see in the 'Count' variable will be the counter output from the previous clock cycle. You may need to subtract one to your maximum counter value to have the exact number of cycles. I would also recommend to forget about ieee.std_logic_unsigned.all and use ieee.numeric_std and the unsigned/signed types instead.
There will be a problem having your process sensitive to count rather than making it synchronous. With your asynchronous design, what you're asking it to do is create a transparent latch that latches the value of num when the count is equal to that silly long binary number. My solutions:1. make the proces synchronous to clk, not count, and follow the standard synchronous process template:
process(clk) begin if rising_edge(clk) then --do some logic end if; end process;2. As you're a beginner, please stop using std_logic_unsigned/signed/arith now. They are not standard packages. They were written origionally by synopsys to make some things easier. Since then (in 1993!) the IEEE standardised the numeric_std package. It meant that this package was standard rather than having different versions created by different vendors, plus you can do signed/unsigned arithmatic in the same file (not possible with std_logic_vectors) and you can do division. 3. VHDL is strongly typed. It is much better to use appropriate types. a std_logic_vector is NOT a number, it is a collection of bits. Use integer/natural/positive if you actually mean integer, and unsigned/signed types (from the numeric_std package) if you want a binary version of numbers. so instead of if count = "110101001001001010" then... you can write instead: if count = 150000 then or if you prefer hex literals: if count = 16#AAAA# then .. This also carries for port maps. It is an old thing that old synthesisors insisted that ports had to be std_logic/std_logic_vector. Since then synthesisors support many many many different types - so you can quite happily use integer, boolen, signed/unsigned as ports on entities. So, learn now that you can make your code more readable, with the compiler doing all the work. Good habits learned now are better than bad habits unlearned later.
--- Quote Start --- I'm not sure how this would synthesize, but you should make your process clocked instead of depending on the counter. What you are describing here is to keep on increasing num as long as the count vector is at that value, not just increase it once when you reach the value. This code will probably generate a combinatorial loop that will give unpredictable results. --- Quote End --- Oh yeah, I forgot compiler ignores sensitivity. This highlights another issue - simulation/synthesis mismatch. The code that was origionally written would probably synthesise to the infinite counter Daixiwen mentioned, but in simulation it would look like a transparent latch.
Oh yes now that I read again what I wrote, I realise I wasn't entirely clear in my explanation. ;)In pure theory (and in simulation) the original code should work because the process is supposed to be only triggered when 'count' changes, and it will do a latch. In practise though, the synthesizer ignores the process sensitivity list and that's why we'll have the infinite loop.
Thanks for the advice guys. It helped steer me in the right direction.I got rid of the megafunction counter and created my own. I also got rid of the clear signal and just decided to reset the counter manually. This ended up working:
PROCESS (CLOCK_50) BEGIN IF rising_edge(CLOCK_50) THEN Count <= Count + '1'; IF (Count = "10111110101111000010000000") THEN Num <= Num + '1'; Count <= "00000000000000000000000000"; IF (Num = "1001") THEN Num <= "0000"; END IF; END IF; END IF; END PROCESS; D0: num_7seg PORT MAP (Num,HEX0);In regards to the packages and types that I use, those are the ones they discuss and use in the tutorial/lab exercises on the Altera webiste as well as the digital logic textbook by Brown & Vranesic that Altera recommends. I'll take your advice however. Thanks again.
It is unfortunate that tutorials and books on the web still refer to those non standard and confusing libraries... But as Tricky said, it's better to try and get the good habits as soon as possible ;)Just a remark on your code. As you may have noticed, the signals aren't updated immediately in a process. This is because of the hardware that is generated. Every statement inside the clocked part of the process read the value of the signal at the clock rising edge and assignments give the value that they must take after that. So in those lines:
Count <= Count + '1'; IF (Count = "10111110101111000010000000") THENinside the if, the value that you see for 'Count' is still the old value, not the one added by 1. Therefore I think that you are counting one value too far. Don't think it is very noticeable, but as an exercise, it's better to have it right ;)
--- Quote Start --- In regards to the packages and types that I use, those are the ones they discuss and use in the tutorial/lab exercises on the Altera webiste as well as the digital logic textbook by Brown & Vranesic that Altera recommends. I'll take your advice however. Thanks again. --- Quote End --- This is the problem. So many people learn from exercises like this that were written some time ago that havent been updated. Then it becomes a vicious circle of people learning the old ways as they then teach/post on forums for others.