I'm a VHDL newbie and I'm struggling with the following idea. I think I still misunderstand the idea of counters and timers in VHDL. I will explain it with a simple blinking LED diode. (BTW I'm learning on Spartan-3E FPGA kit.)
So here is my code (I'm not using reset yet)
entity top_level is
Port( clk : in STD_LOGIC;
led1 : out STD_LOGIC);
end top_level;
architecture Behavioral of top_level is
signal timer : STD_LOGIC_VECTOR(25 downto 0) := "00000000000000000000000000";
signal reset: boolean:= false;
begin
process (clk)
begin
led1 <= '1';
if clk='1' and clk'event then
if reset <= true then
timer <= (others => '0');
end if;
timer <= timer + 1;
end if;
if timer <= "11100100111000011100000000" then
led1 <= '0';
end if;
end process;
end Behavioral;
The oscillator frequency is 50 MHz so one period is 20 ns. If I want to blink with a LED for 1.2 second (which makes 60 000 000 cycles) I need to create a 26 bit vector. So I created a process which is triggered by clk change.
WHAT I THINK IT SHOULD DO:
the first line of code is a logic 1 assignment to led1. So the led1 should light until the counter won't count 60 000 000 cycles. When counter counts 60 000 000 cycles, the led logic state should switch to 0 which means no light. As the maximum value of 26 bit number is 67 108 863, the LED should light for 60 000 000 cycles and be turned off for the remaining 7 108 863 cycles. Isn't that right ?
WHAT IT DOES:My impression is, that it's kinda reversed. The LED is off for the most of the time (67 108 063 cycles) and lights for 7 108 863 cycles. Why is this happening ? I don't really get it.
Additional question: How can I achieve to run this process only once/twice/...? E.g. I want to blink with my LED 3 times and then turn it off. Because as far as I know after reaching maximum 26 bit number, the time vector will start counting from the beginning (from 0). And so on, endlessly.
First of all, you should divide your design in several parts, which can be entities or several processes. I'll use processes or some one-liner. You can also extract the presented functions into a separate package.
Part 1
I would suggest to use the type UNSIGNED for a counter, so the '+' operator is defined for this type. I named it
timer_us
so it's easy to see that this signal is an unsigned. Additionally, you can use(others => '0')
in declarations, too.The last line describes a ternary operator (like
z = a ? x : y
in C). So the tick signal is '1' if the timer reaches 60,000,000. But there is a fault: Your counter starts at 0 so 60,000,000 cycles are already reached atmax - 1
.Some improvements for a more generic counter template:
timer_rst
TIMER_MAX
log2ceil
to_sl
Here the extended counter code:
If you have fun in coding function, you can also invent a function which converts a time (the period for the 0.833 Hz signal) into a cycle count at a given frequency of 50 MHz ;)
Part 2
A blinking LED is a simple T-FF:
Or as an one-liner (no need for a process block):
Part 3
So now you have all the tools to build counters. You can implement a second counter to count from 0 to 2. if 2 is reached you can set a control signal
counter2_ctrl
which is then feed back to the blink process to stop this process from toggling.Here the extended one-liner:
To your question
The inverse LED output can be caused by low-active circuits on your test board.