Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

12 Hour Clock using VHDL

Status
Not open for further replies.

triplel06

Newbie level 3
Newbie level 3
Joined
Apr 3, 2018
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
41
Hello all,

I'm trying to use VHDL so create a 12 hour clock. I have to break up each part into blocks and them use a top level to combine them all. I have the TickGenerator which moves the 50MHz clock down to a 1Hz clock. Next is the second generator block which I have below but keep getting errors.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity SecondGenerator is
port(
tick_in: in std_logic;
minute_out: out std_logic
second : out std_logic_vector (5 downto 0);
);
end entity;
 
architecture behave of SecondGenerator is
 
signal tick_in1 : std_logic :='1';
signal sec: integer range 0 to 59;
 
begin
 
process(tick_in)
begin
 
if(rising_edge(tick_in))then
if(sec = 59) then
sec <= sec+1;
else
sec <= 0;
end if;
end if;
end process;
end behave;



Screen Shot 2018-04-02 at 2.07.56 PM.jpg
 

This is a problem:
Code:
if(sec = 59) then
sec <= sec+1;
else
sec <= 0;

You are incrementing only if sec is exactly 59, which it won't be (especially from simulation start as sec will be X).
You should be doing something like this:

Code:
if (reset = '1') then
  sec <= 0;
elsif (sec < 59) then
  sec <= sec + 1;
else
  sec <= 0;
end if;

Of course this is disregarding the bad practice of generating clocks internally from flip-flops like you are doing to get your 1Hz tick_in signal. The synchronous way to do this is to generate a one_sec_enable signal that is high for only one 50 MHz clock cycle and use that in an enabled process instead.
 
I think tick_in should be included in the code.
Code:
process(tick_in,reset,sec)
begin
 if(reset = '1') then
  sec <= '0';
 elsif(rising_edge(tick_in))then
  if(sec = 59) then
   sec <= 0;
  else
   sec <= sec + 1;
  end if;
 end if;
end process;

And even you can define sec as unsigned(5 downto 0) instead of integer as integer will synthesize 32 bit register.

In addition to this you have to use
Code:
second <= std_logic_vector(to_unsigned(sec,6)); -- if you are still using integer
 
First error

second : out std_logic_vector (5 downto 0);
);

You need to remove the ";"

Second error

Your logic is wrong, you want to count when less than x. As #2 points out.

Third Error

The use of a flip flop (d) as a clock can lead to problems (race conditions/timings etc), fpgas are designed for specific paths for clock tree compared to the data tree. What #2 is emphasising is the use of the clock tree - i.e. 50MHz with an enable strobe to activate the behaviour you want.
This has a two fold result - 1. It makes your design synchronous. 2. It could reduce your multiple blocks to a single block which is instantiated with a with different generic limit & enable signal.
 
Thank yall for all the help!
Yes Ive read that the way Im doing my 1Hz is mostly wrong, but it was the only way my labs have shown to do it in the past. My knowledge of VHDL is somewhat limited.
Below is the posted code that came back without any errors.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
 
entity SecondGenerator is
port(
tick_in: in std_logic;
minute_out: out std_logic;
second : out std_logic_vector (5 downto 0)
);
end entity;
 
architecture behave of SecondGenerator is
 
signal tick_in1 : std_logic :='1';
signal sec: integer range 0 to 60 := 0;
signal reset: std_logic :='0';
 
begin
 
second<= conv_std_logic_vector(sec,6);
 
process(tick_in,reset)
begin
if(rising_edge(tick_in))then
if(reset = '1') then
sec<= 0;
elsif (sec < 59) then
sec <= sec + 1;
else
sec <= 0;
end if;
end if;
end process;
end behave;

 
Last edited by a moderator:

another quick question. when I test the code it comes back with zero errors which is awesome but when I assign the minute_out to a led pin it doesnt blink every minute why is that?
 

I can't see any reference of "minute_out" in your code, please share the relevant section of code.
 

Hi,

I wonder why you used "minute_out".
Why don't you go step by step from 50MHz to hours. (First check if the seconds run correctly)

If you expect to do some other VHDL projects in the future:
I strongly recommend to write code the "correct way": Running all FF from the same clock with individual "enable" signals.
Don't learn the wrong way.
There are more than enough threads, documents, tutorials, even video tutorials around.

Klaus
 

I was provided a block diagram and told to make a 12 hour clock. (the diagram is on the OP) Seconds seem to work fine and I can get an led to blink every second. I used minute_out first off because that was how it was labeled on the block diagram and second I figured if I assigned an led to the output (minute_out) it would work.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top