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.
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
signalcounter:unsigned(32downto0):=x"14000000";
2
:
3
:
4
-- default count and saturate after 3 flash-cycles
5
ifcounter/=x"14000000"then
6
counter<=counter+1;
7
endif;
8
-- button freshly pressed? or one flash-cycle done and button pressed further on?
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
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entityflashledis
6
Port(clk50M:inSTD_LOGIC;-- lets assume this clock has 50MHz
7
led:outSTD_LOGIC);-- light when '1'
8
endflashled;
9
10
architectureBehavioralofflashledis
11
signalcounter:unsigned(31downto0):=x"00000000";
12
begin
13
counter<=counter+1whenrising_edge(clk);
14
LED<=counter(26);-- map one of the higher counter bits to the LED
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:
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...
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.. ;-)