Hi I am new to VHDL and FPGA but I am trying to learn to have some fun. I got myself a brand new nexys 4 DDR as a present so now I have to do some projects. I know that perhaps for someone this project will be a joke but as I said earlier I am a complete beginner. My idea is: I want to short-click a button and have some led on the board blink a couple of times lets say 3 times, at the same time when the button is pressed without letting it go I want it to blink continuously until the button is released. How can I start? I know I need a clock (clk) as an input to handle the blinking also a button (btn_1) as an input and an led (led_1) as an output all declared in std_logic. Can someone help me?
Sania P. wrote: > How can I start? Start with the simple flashing LED. With this you will learn 1. how to use the toolchain, 2. how to assign pins to ports to signals and 3. how to implement a simple counter. Having done the flashing LED you can read in the button and implement synchronizer to the systems clock, additionally a debouncer and an edge detection. There the simple task is to implement a LED toggle with each button press. Sania P. wrote: > My idea is: I want to short-click a button and have some led on the > board blink a couple of times lets say 3 times Ok, thats easy then: having done the LED flasher and the button input stage you can implement something that waits for on a button press, then resets a counter thats counts up to a saturating value and lets flash the LED with one of the higher bits. > at the same time when the button is pressed without letting it go > I want it to blink continuously until the button is released. What should happen when the button is pressed "fairly long", but lets say only until the second LED flash? Or may it flash additionally 2-3 times after releasing the button? If the second, then the task ist solved almost as easy as the simple 3-times-flsher: implement a saturating couter as shown and reset with a falling edge on the button signal as shown, but additonally reset the counter after pone cycle when the button is pressed at that very moment. Check the attached code and the testbench to get an idea how it may be solved. I had to make it blink fairly fast to reduce simulation time. For real life you should add some bits to the counter... ;-) And do not present this code to your teacher. She/He will recognize immediately that this code is not yours.
:
Edited by Moderator
Thanks for the answer, I learnt how to map an led to a button, also how to make it blink. And how to make it blink while the button is pressed. Now I am trying to make the button blink only 3 times after a short press. I am reading a lot of blogs/tutorials online and many people call it double counter, correct me if I am wrong. So one counter is counting the clock and the other counter is counting the cycles of the first one. But I still cannot understand the vhdl implementation of this theory completely. I saw in your code you implement this technique so in desperation I just took your code and copy-pasted it in vivado (I am using 2018.3 version). I mapped the button to the led and generated bitstream and programmed the board. It didnt work completely (led was on only by pressing and holding the button) so I thought maybe it is because it is too fast and I cannot see the blinking altogether so I increased a lil bit the count vector because my original clock is 100MHz, but it still seemed not to work correctly. The only thing which does work is the led lights on when the button is continously pressed, it is always on without blinking and after releasing the button led turns off. Nevertheless all I need now is to learn how to make it blink only 3 times, I hoped I could crack it simply by studying your code but I am again hopeless. Could you help me please with an advice?
Sania P. wrote: > so I thought maybe it is because it is too fast Take a scope and measure at the LED pin. With this tool you can easily see wheter there is something going on or not... > so I increased a lil bit the count vector In my waveform I use a 20 Bit vector and get times in the ms range. you want something in the second range, therefore you will need somewhat around 9 bits more. So simply try that:
1 | signal counter : unsigned (32 downto 0) := x"14000000"; |
2 | :
|
3 | :
|
4 | -- default count and saturate after 3 flash-cycles
|
5 | if counter/=x"14000000" then |
6 | counter <= counter+1; |
7 | end if; |
8 | -- button freshly pressed? or one flash-cycle done and button pressed further on?
|
9 | if btnsr(2 downto 1)="01" or (counter=x"08000000" and btnsr(2)='1') then |
10 | counter <= (others=>'0'); -- then reset the counter |
11 | end if; |
12 | end process; |
13 | |
14 | LED <= not counter(26); -- map the relevant bit of the counter to the LED |
:
Edited by Moderator
I have also found and read your previous answers on this forum, in this topic: Beitrag "Xilinx VHDL Blinker-Programm Problem" it is somewhat relevant to my problem, so I tried this time the code you gave the other guy for the answer (I attached your code so that you know what I am talking about). As before the board is programmed well without interruptions, but on the board the same thing happens, I press the button the led turns on (without blinking), i let it go the led turns off (without any 3 blinks) I am using vivado 2018.3 and the board is nexys4 ddr (clock=100MHz). My OS is win10pro. I still cannot figure out why your codes don't work. Unfortunately I have no scope, I tried to record leds on iPhone's slow mo camera to see the lights but the light on led is steady without any blinking. Do you have any idea why this can happen? I also have another board MIMAS V.2 but it is not supported in vivado 2018.3 so I think if I won't find a workaround, I will try the code in ISE with MIMAS V.2 (XC6SLX9).
Sania P. wrote: > Do you have any idea why this can happen? No. My usual way is to write the code, simulate it and debug it in the simulator. Then I synthesize it and it runs as expected... ;-) Did you get the simple straightforward flashing LED to work? Its a simple unsigned counter with 32 bits and one of the higher counter bits assigned to the LED.
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity flashled is |
6 | Port ( clk50M : in STD_LOGIC; -- lets assume this clock has 50MHz |
7 | led : out STD_LOGIC); -- light when '1' |
8 | end flashled; |
9 | |
10 | architecture Behavioral of flashled is |
11 | signal counter : unsigned (31 downto 0) := x"00000000"; |
12 | begin
|
13 | counter <= counter+1 when rising_edge(clk); |
14 | LED <= counter(26); -- map one of the higher counter bits to the LED |
15 | end Behavioral; |
I have attached the file this is how far I got so far. This code is working fine on the board. I press the button and the led blinks with a period around a second, I release it and it turns off.
Sania P. wrote: > the led blinks with a period around a second So you know what bit to take (and my guess was not too bad ;-) From there it is fairly easy. For 3 times flashing the calculation is done this way:
1 | counter |
2 | bit |
3 | 28 0 0 0 0 1 1 |
4 | 27 0 0 1 1 0 0 |
5 | 26 0 1 0 1 0 1 |
6 | |
7 | LED 1 0 1 0 1 0 = bit 26 inverted |
With a rising edge at the button input the counter must be reset, so that all bits an espacially bits 26..28 are "000". Then the counter counts up till bits 28 downto 26 are "101". Reaching that value the LED is off and it has flashed up 3 times. First job "short press": done! When the counter bits 28 downto 26 reach "010" you must check whether the button is pressed further on (long press). If so, then the counter mus be reset to the start value "000". Second job "long press": done! So finally this should work:
1 | ----------------------------------------------------------------------------------
|
2 | library IEEE; |
3 | use IEEE.STD_LOGIC_1164.ALL; |
4 | use IEEE.NUMERIC_STD.ALL; |
5 | |
6 | |
7 | entity flashled is |
8 | Port ( clk50M : in STD_LOGIC; -- lets assume this clock has 50MHz |
9 | button : in STD_LOGIC; -- pressed = '1' |
10 | led : out STD_LOGIC); -- light when '1' |
11 | end flashled; |
12 | |
13 | architecture Behavioral of flashled is |
14 | signal counter : unsigned (28 downto 0) := (others=>'0'); |
15 | signal btnsr : std_logic_vector (2 downto 0) := "000"; |
16 | |
17 | begin
|
18 | -- sync the button to the 50MHz system clock
|
19 | btnsr <= btnsr(1 downto 0) & button when rising_edge(clk50M); |
20 | |
21 | process begin |
22 | wait until rising_edge(clk50M); |
23 | -- default count and saturate after 3 flashing cycles
|
24 | if counter(28 downto 26)/=x"101" then |
25 | counter <= counter+1; |
26 | end if; |
27 | -- button freshly pressed? or one flash cycle done and button pressed further on?
|
28 | if btnsr(2 downto 1)="01" or (counter(28 downto 26)="010" and btnsr(2)='1') then |
29 | counter <= (others=>'0'); -- then reset the counter |
30 | end if; |
31 | end process; |
32 | |
33 | LED <= not counter(26); -- map the relevant bit of the counter to the LED |
34 | |
35 | end Behavioral; |
Unfortunately it does not work either. But at least it blinks now straight from the beginning, when I press the button the light stays just a tiny bit longer on and then continues blinking, the same thing happens when I release it, the led stays on a tiny moment longer. It is like if by pressing the button I interrupt the blinking and shift it a tiny little bit forward and then the blinking interval continues normally like before. I am hopeless, I have posted the same question on xilinx forum but no one really gave me something valuable yet. One guy suggested debouncing the button, but I still don't see any relationship to the 3 times blink while pressing the button with debouncing it, correct me if I am wrong. I would love to have a working code in front of me to be able to study it and understand how it actually works. Perhaps it is not the right way to learn but this is how I do it and it works for me. I understand that I have to create two signals, the first one will count the clock and increment it in a loop of desired bits (in my case 26 downto 0). The second signal starts counting the first one once I press the button and counts minimum till 3, if the button is released before the 3 count-cycle is over. If the button is still pressed I need to make sure that the second signal keeps counting. And finally I need to pin my signal to led (this is not a problem anymore, I know how to do it already)
Sania P. wrote: > One guy suggested debouncing the button Having a second thougt he will recognize: thats not neccessary here. Even a bouncing button will work with my code above. > Unfortunately it does not work either. Did you simulate your design? What does your simulation look like? Is it ok? No, it is not. And the problem is the remaining erronous 'x' here: if counter(28 downto 26)/=x"101" then Wipe it out and it runs as expected: if counter(28 downto 26)/="101" then Because with that 'x' the compare value is a hex number and it does not match the desired stop value. But I'm asking myself: why the heck didn't the simulator throw an error due to mismatching vector lengths.. > I am hopeless Look for a scope or a logic analyzer (a cheap one will do the job) to see a little bit more of the reality...
:
Edited by Moderator
Now everything is working perfectly!!!! I dont understand only one line: btnsr <= btnsr(1 downto 0) & button when rising_edge(clk); you commented over it that this is to synchronise the button to the clock frequency, I understand what this means but I do not understand how it works. My guess is everytime I press the button the action will wait till the rising edge of the clock and then begin together synchronised am I right? One more thing why did you assign 2 dimensional vector (1 downto 0) of btnsr to the original 3 dimensional vector (2 downto 0) of btnsr?
Sania P. wrote: > My guess ...is fundametally wrong ;-) In a FPGA nothing "waits" for the rising/falling edge of the clock. Instead the clock is connected to flipflops. And due to is a rising/falling edge, then the flipflop transfers the level at it input to its output and stores it there. > One more thing why did you assign 2 dimensional vector (1 downto 0) of > btnsr to the original 3 dimensional vector (2 downto 0) of btnsr? Read about the '&' operator in VHDL. It is obviously that you don't know it close enough. It has nothing to do with any kind of AND function like the ampersand '&' and '&&' operator in C (*). Instead it is the "glue" that concatenates signals and/or vectors to a new and "longer" vector. > btnsr <= btnsr(1 downto 0) & button when rising_edge(clk); btnsr is a 3 bit shift register (it comes from BuTtoN Shift Register). So it is 3 flipflops one behind the ohter. Each one is clocked with the systems clock. The last two flipflops are used to detect the edge ot the button signal. Have a look at the simulation how it works. And have a look in the RTL schematics how it is realized... This here is some background to it: http://www.lothar-miller.de/s9y/archives/52-Kompakte-Flankenerkennung.html (Google translator may help, its German) (*) read out this sentence loud and clear, listen to it and you will find a smile on your face.. ;-)
:
Edited by Moderator
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.