EmbDev.net

Forum: FPGA, VHDL & Verilog Designated Number Counter and Cycle counter 2 Digit


Author: Jason W. (Company: n/a) (grauado)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Greetings.
Not long ago I've written this code shown down below for a BCD timer,
showing on 4 digit Seven Segment Display.
But now,I would like to change it to the design shown in the attachment 
file,
how can I do that?

In case there's any confusion in attached sketch,
My intention is to modify this code to a design
that has two counters,first counting designated number "870107",
second counter counts when first finished a "870107" cycle,
e.g. First counter : 8>7>0>1>0>7
    Second counter : 0>0>0>0>0>1
                     1>1>1>1>1>2
                     2>2>2>2>2>3
                     ...and so on...
and only using 2 of 4 seven segment display on the board.

and frequency divider divide my spartan 3E board's 50MHZ to 1HZ.
    decoder for scanning/refresh seven segment display
    Multiplexer to decide which Seven segment display to activate

Sincerely Appreciate to any assists.
 library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;


entity seven_segment_display is
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
        pause : in  STD_LOGIC;
           Anode_Activate : out  STD_LOGIC_VECTOR (3 downto 0);
           LED_out : out  STD_LOGIC_VECTOR (6 downto 0));
end seven_segment_display;

architecture Behavioral of seven_segment_display is
signal one_second_counter: STD_LOGIC_VECTOR (18 downto 0);
signal one_second_enable: std_logic;
signal displayed_number: STD_LOGIC_VECTOR (15 downto 0);
signal LED_BCD: STD_LOGIC_VECTOR (3 downto 0);
signal refresh_counter: STD_LOGIC_VECTOR (10 downto 0);
signal LED_activating_counter: std_logic_vector(1 downto 0);
begin
process(LED_BCD)
begin
    case LED_BCD is
    when "0000" => LED_out <= "0000001"; -- "0"     
    when "0001" => LED_out <= "1001111"; -- "1" 
    when "0010" => LED_out <= "0010010"; -- "2" 
    when "0011" => LED_out <= "0000110"; -- "3" 
    when "0100" => LED_out <= "1001100"; -- "4" 
    when "0101" => LED_out <= "0100100"; -- "5" 
    when "0110" => LED_out <= "0100000"; -- "6" 
    when "0111" => LED_out <= "0001111"; -- "7" 
    when "1000" => LED_out <= "0000000"; -- "8"     
    when "1001" => LED_out <= "0000100"; -- "9" 
    when "1010" => LED_out <= "0000010"; -- a
    when "1011" => LED_out <= "1100000"; -- b
    when "1100" => LED_out <= "0110001"; -- C
    when "1101" => LED_out <= "1000010"; -- d
    when "1110" => LED_out <= "0110000"; -- E
    when "1111" => LED_out <= "0111000"; -- F
    end case;
end process;
process(clk,reset)
begin 
    if(reset='1') then
        refresh_counter <= (others => '0');
    elsif(rising_edge(clk)) then
        refresh_counter <= refresh_counter + 1;
    end if;
end process;
 LED_activating_counter <= refresh_counter(9 downto 8);
process(LED_activating_counter)
begin
    case LED_activating_counter is
    when "00" =>
        Anode_Activate <= "0111"; 
        LED_BCD <= displayed_number(15 downto 12);
    when "01" =>
        Anode_Activate <= "1011"; 
        LED_BCD <= displayed_number(11 downto 8);
    when "10" =>
        Anode_Activate <= "1101"; 
        LED_BCD <= displayed_number(7 downto 4);
    when "11" =>
        Anode_Activate <= "1110"; 
        LED_BCD <= displayed_number(3 downto 0);
   when others => Anode_Activate <= "0111";
    end case;
end process;
process(clk, reset)
begin
        if(reset='1') then
            one_second_counter <= (others => '0');
        elsif(rising_edge(clk)) then
            if(one_second_counter>=x"7FFFF") then
                one_second_counter <= (others => '0');
            else
                one_second_counter <= one_second_counter + "0000001";
            end if;
        end if;
end process;
one_second_enable <= '1' when one_second_counter=x"7FFFF" else '0';
process(clk, reset)
begin
        if(reset='1') then
            displayed_number <= (others => '0');
          elsif (pause = '1') then
            displayed_number <= displayed_number;
            elsif(rising_edge(clk)) then
              if(one_second_enable='1') then
                displayed_number <= displayed_number + x"0001";
                end if;
        end if;
end process;

end Behavioral; 

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Jason W. wrote:
> use IEEE.std_logic_unsigned.all;
> use IEEE.NUMERIC_STD.ALL;
One hint in advance: NEVER EVER use both of the math libs. It will bring 
strange effects due to double type definitions now and then. Use the 
numeric_std solely. It has all you need!

Now this:
             if(one_second_counter>=x"7FFFF") then
                 one_second_counter <= (others => '0');
             else
                 one_second_counter <= one_second_counter + "0000001";
             end if;
Do you really have a oscillator with 1048576 Hz?
If not, then why not counting in a manner even humans are able to read?
signal one_second_counter: integer range 0 to 999999 := 0;
:
:
             if(one_second_counter=999999) then
                 one_second_counter <= 0;
             else
                 one_second_counter <= one_second_counter + 1;
             end if;

Jason W. wrote:
 e.g. First counter : 8>7>0>1>0>7
     Second counter : 0>0>0>0>0>1
                      1>1>1>1>1>2
                      2>2>2>2>2>3
So far I see those both together count like this:
08, 07, 00, 01, 00, 17, 18, 17, 10, 11, 10, 27, 28, 27, 20, 21, 20, 37, 
38 and so on. Ist this assumption correct?

Then first i would turn the sequence a little and start with the "second 
value":
low digit:  7 8 7 0 1 0
high digit: x 0 0 0 0 0
            1 1 1 1 1 1
            2 2 2 2 2 2
            3 3 3 3 3 3
Now the pattern looks more like a simple counter...

Having done that, you see that you can't count on the numbers directly, 
because some numbers appear two times and you can't step forward the 
counting FSM in 2 different ways. So simply do it with 2 counters: one 
counting from 0 to 5 for the 787010 sequence and the other for the 
straightforward high-digit of the counter.
And then select the low-digit value according to the counting index of 
the low counter.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
:
:
signal cntlo : integer range 0 to 5 := 1; -- start with display 80!
signal cnthi : integer range 0 to 9 := 0;
signal one_second_counter: integer range 0 to 999999 := 0;
:
:
process begin -- the prescaler and counter
   wait until rising_edge(clk);
   if one_second_counter<999999 then
      one_second_counter <= one_second_counter + 1;
   else
      one_second_counter <= 0;
      if cntlo<5 then
         cntlo <= cntlo+1;
      else
         cntlo <= 0;
         if cnthi<9 then
            cnthi <= cnthi+1;
         else
            cnthi <= 0;
            cntlo <= 0;
         end if;
      end if;
   end if;
end process;
:
:
displayed_number(15 downto 8) <= (others => '0');
displayed_number(7 downto 4) <= std_logic_vector(to_unsigned(cnthi, 4));
displayed_number(3 downto 0) <= x"7" when cntlo = 0 else
                                x"8" when cntlo = 1 else
                                x"7" when cntlo = 2 else
                                x"0" when cntlo = 3 else
                                x"1" when cntlo = 4 else
                                x"0" when cntlo = 5;
:
:
Got the trick?

: Edited by Moderator
Author: Jason W. (Company: n/a) (grauado)
Posted on:

Rate this post
0 useful
not useful
>Lothar M. wrote
library IEEE;
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.NUMERIC_STD.ALL;
 :
 :
 signal cntlo : integer range 0 to 5 := 1; -- start with display 80!
 signal cnthi : integer range 0 to 9 := 0;
 signal one_second_counter: integer range 0 to 999999 := 0;
 :
 :
 process begin -- the prescaler and counter
    wait until rising_edge(clk);
    if one_second_counter<999999 then
       one_second_counter <= one_second_counter + 1;
    else
       one_second_counter <= 0;
       if cntlo<5 then
          cntlo <= cntlo+1;
       else
          cntlo <= 0;
          if cnthi<9 then
             cnthi <= cnthi+1;
          else
             cnthi <= 0;
             cntlo <= 0;
          end if;
       end if;
    end if;
 end process;
 :
 :
 displayed_number(15 downto 8) <= (others => '0');
 displayed_number(7 downto 4) <= std_logic_vector(to_unsigned(cnthi, 4));
 displayed_number(3 downto 0) <= x"7" when cntlo = 0 else
                                 x"8" when cntlo = 1 else
                                 x"7" when cntlo = 2 else
                                 x"0" when cntlo = 3 else
                                 x"1" when cntlo = 4 else
                                 x"0" when cntlo = 5;
 :
 :

I'm not quite get it,If the code changed it into this,then where does my 
original code's MUX and Case statement fit in?Ditch the Case statements?
And how do I implement the actual LED_out(Seven Segment Display) output?
Your code is indeed human friendly,but it's quite too simple to me to 
understand.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Jason W. wrote:
> And how do I implement the actual LED_out(Seven Segment Display) output?
They do the same as now. I did not lay my hand on the display part. I 
only changed the counter part. the interface to your part of the design 
is the vector "displayed_number". Just think about it for some minutes 
or a few hours...

BTW: the sensitivity list in your
> process(LED_activating_counter)
is incomplete! The signal displayed_number is missing. Therfore the 
simulation will not match the reality. The synthesizer will report some 
kind of warning or info about that...

Author: Jason W. (Company: n/a) (grauado)
Posted on:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Jason W. wrote:
>> And how do I implement the actual LED_out(Seven Segment Display) output?
> They do the same as now. I did not lay my hand on the display part. I
> only changed the counter part. the interface to your part of the design
> is the vector "displayed_number". Just think about it for some minutes
> or a few hours...
>
> BTW: the sensitivity list in your
>> process(LED_activating_counter)
> is incomplete! The signal displayed_number is missing. Therfore the
> simulation will not match the reality. The synthesizer will report some
> kind of warning or info about that...

So after changed codes with your suggestion.I tried to implement them 
together and not sure where I've done wrong..
It's closed to the result but not quite...
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;


entity seven_segment_display is
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           Anode_Activate : out  STD_LOGIC_VECTOR (3 downto 0);
           LED_out : out  STD_LOGIC_VECTOR (6 downto 0));
end seven_segment_display;

architecture Behavioral of seven_segment_display is
signal displayed_number: STD_LOGIC_VECTOR (15 downto 0);
signal LED_BCD: STD_LOGIC_VECTOR (3 downto 0);
signal refresh_counter: STD_LOGIC_VECTOR (5 downto 0);
signal LED_activating_counter: std_logic_vector(1 downto 0);
signal cntlo : integer range 0 to 5 := 1; -- start with display 80!
signal cnthi : integer range 0 to 9 := 0;
signal one_second_counter: integer range 0 to 33554431 := 0;

begin
process(LED_BCD)
begin
    case LED_BCD is
    when "0000" => LED_out <= "0001111"; -- "7" 
    when "0001" => LED_out <= "0000000"; -- "8"
   when "0010" => LED_out <= "0001111"; -- "7"
   when "0011" => LED_out <= "0000001"; -- "0"  
   when "0100" => LED_out <= "1001111"; -- "1"
    when "0101" => LED_out <= "0000001"; -- "0"
   when others => LED_out <= "0001111";
    end case;
end process;
process(clk,reset)
begin 
    if(reset='1') then
        refresh_counter <= (others => '0');
    elsif(rising_edge(clk)) then
        refresh_counter <= refresh_counter + 1;
    end if;
end process;
 LED_activating_counter <= refresh_counter(5 downto 4);
process(LED_activating_counter)     -- MUX Not working , Warnings showed that :
                          --'One or more signals are missing in the process sensitivity list. 
                          --To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. 
                          --Please note that the result of the synthesis may differ from the initial design specification. The missing signals are: 'displayed_number'
begin
    case LED_activating_counter is      
    when "00" =>
        Anode_Activate <= "0101"; 
        LED_BCD <= displayed_number(7 downto 4);
    when "01" =>
        Anode_Activate <= "1010"; 
        LED_BCD <= displayed_number(3 downto 0);        
   when others => Anode_Activate <= "0101";
    end case;
end process;

process begin -- the prescaler and counter
   wait until rising_edge(clk);
   if one_second_counter < 33554431 then
      one_second_counter <= one_second_counter + 1;
   else
      one_second_counter <= 0;
      if cntlo<5 then
         cntlo <= cntlo+1;
      else
         cntlo <= 0;
         if cnthi<9 then
            cnthi <= cnthi+1;
         else
            cnthi <= 0;
            cntlo <= 0;
         end if;
      end if;
   end if;
end process;

displayed_number(15 downto 8) <= (others => '0');
displayed_number(7 downto 4) <= std_logic_vector(to_unsigned(cnthi, 4));
displayed_number(3 downto 0) <= x"7" when cntlo = 0 else
                                x"8" when cntlo = 1 else
                                x"7" when cntlo = 2 else
                                x"0" when cntlo = 3 else
                                x"1" when cntlo = 4 else
                                x"0" when cntlo = 5;
end Behavioral;
And a lot of Warnings Messages...
WARNING:Xst:646 - Signal <displayed_number<15:8>> is assigned but never 
used. This unconnected signal will be trimmed during the optimization 
process.
WARNING:Xst:737 - Found 4-bit latch for signal <LED_BCD>. Latches may be 
generated from incomplete case or if statements. We do not recommend the 
use of latches in FPGA/CPLD designs, as they may lead to timing 
problems.
WARNING:Xst:737 - Found 1-bit latch for signal <displayed_number_0>. 
Latches may be generated from incomplete case or if statements. We do 
not recommend the use of latches in FPGA/CPLD designs, as they may lead 
to timing problems.
WARNING:Xst:737 - Found 1-bit latch for signal <displayed_number_1>. 
Latches may be generated from incomplete case or if statements. We do 
not recommend the use of latches in FPGA/CPLD designs, as they may lead 
to timing problems.
WARNING:Xst:737 - Found 1-bit latch for signal <displayed_number_3>. 
Latches may be generated from incomplete case or if statements. We do 
not recommend the use of latches in FPGA/CPLD designs, as they may lead 
to timing problems.
WARNING:PhysDesignRules:372 - Gated clock. Clock net 
displayed_number_0_or0000
   is sourced by a combinatorial pin. This is not good design practice. 
Use the
   CE pin to control the loading of data into the flip-flop.
WARNING:Route:455 - CLK Net:displayed_number_0_or0000 may have excessive 
skew because
WARNING:Route:455 - CLK Net:refresh_counter<5> may have excessive skew 
because
WARNING:PhysDesignRules:372 - Gated clock. Clock net 
displayed_number_0_or0000
   is sourced by a combinatorial pin. This is not good design practice. 
Use the
   CE pin to control the loading of data into the flip-flop.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Jason W. wrote:
> I tried to implement them together and not sure where I've done wrong..
> And a lot of Warnings Messages...
Those messages may help you.

> The missing signals are: 'displayed_number'
As I already said. So add this signal.

> Signal <displayed_number<15:8>> is assigned but never used.
Thats correct. You do not use them, so they are hard wired to 0.

> if one_second_counter < 33554431 then
What the heck? What crystal do you use? Is it really a 33.554432 MHz 
oscillator? Or did you find that number by dicing?

> Found 4-bit latch for signal <LED_BCD>. Latches may be generated from
> incomplete case or if statements.
You wrote it in that way...

> We do not recommend the use of latches
> in FPGA/CPLD designs, as they may lead to timing problems.
"Do not recommend" is nice. You never ever MUST have latches unless you 
really need one and you know deeply what you are doing.

In your design all of those latches are serious design flaws due to

> use IEEE.std_logic_unsigned.all;
> use IEEE.NUMERIC_STD.ALL;
What did I say about this pair?

Jason W. wrote:
 begin
 process(LED_BCD)
 begin
     case LED_BCD is
    when "0000" => LED_out <= "0001111"; -- "7" 
    when "0001" => LED_out <= "0000000"; -- "8"
   when "0010" => LED_out <= "0001111"; -- "7"
   when "0011" => LED_out <= "0000001"; -- "0"  
   when "0100" => LED_out <= "1001111"; -- "1"
    when "0101" => LED_out <= "0000001"; -- "0"
   when others => LED_out <= "0001111";
Why did you do that? I said: do not change any more than that counter. 
With these modification you cannot display other number than 0,1,7 and 
8, you know?
I already did the mapping for the counter to the number in the last few 
lines of your code.
As I already said: THINK ABOUT THE POSTED CODE.
And when you understand it, then change it.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Ok, I did a litte finger twist in the lunch break. For me simulation 
looks fine, and there are no warnings during synthesizing...

Author: Jason W. (Company: n/a) (grauado)
Posted on:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Ok, I did a litte finger twist in the lunch break. For me simulation
> looks fine, and there are no warnings during synthesizing...
 signal refresh_counter: integer range 0 to 63 := 0; 
why 0 to 63? what's this controlling?
after your twists,can you tell me which part controls the displaying of 
Seven Segment Display,'cause I would like to add pause and reset bottom.

Author: Jason W. (Company: n/a) (grauado)
Posted on:

Rate this post
0 useful
not useful
Although the code's right,still doesn't display right at the 
board...ummm...thinking it.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Jason W. wrote:
> why 0 to 63? what's this controlling?
Just a random number. It's controlling the display MUX frequency. 
Almost similar to your even so random counting vector 5 downto 0 (which 
was 10 downto 0 in the first code).

A hint: analyze what's happening and adjust those counters top values to 
your specific FPGA clock and to your desired multiplex frequency.

> cause I would like to add pause and reset bottom.
Obviously a little work left over...

Jason W. wrote:
> still doesn't display right at the board...
What instead?

> ummm...thinking it.
Good idea đź’ˇ
A hint here: it may be decades too fast...

: Edited by Moderator
Author: Jason W. (Company: n/a) (grauado)
Posted on:

Rate this post
0 useful
not useful
Lothar M. wrote:
> What instead?
The codes seemed fine,but on the board the seven segment display is 
continuously light up whenever it counts,like it counts to 7 but still 
light up looks like 8 or only 0 lighting up,I've checked pins for seven 
segment,and they weren't wrong...

I can see a bit of result,but it's not quite what I described...

it's counting like 80>71>02>13>04>75>...etc.
but what I wanted is:
80>70>00>10>00>70>81>71>01>11>01>71>82>72>02>12>72>...etc

: Edited by User
Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Jason W. wrote:
> light up looks like 8 or only 0 lighting up
Your eye is much too slow to get up with the mux and counting speed. The 
counters run so fast, that you see all of the numbers at once.

> I've checked pins for seven segment,and they weren't wrong...
You're digging at the wrong part of the design! I said: check the 
counters top values and adapt it to YOUR specific needs. Is that sooooo 
difficult to understand?
You have a "one_second_counter" that counts up to 33554431 and then 
forwards the digit values. So lets assume you have a oscillator 
frequency and therfore a FPGA clock of somewhat in the 33MHz range.
In my design I only count to 999 to get a faster simulation. And now the 
question of questions: what is the difference between 1000 and 33554432?
You are rigt: the second is 33554 times greater than the first, and so 
my "one_second_counter" will advance 33554 times faster than yours. Got 
it?

Jason W. wrote:
> I can see a bit of result,but it's not quite what I described...
> it's counting like 80>71>02>13>04>75>...etc.
With what code?

> but what I wanted is:
> 80>70>00>10>00>70>81>71>01>11>01>71>82>72>02>12>72>...etc
Huh, then you have to twist those two digits. Because I assumed that the 
faster countig value is the rightmost digit.

: Edited by Moderator
Author: Jason W. (Company: n/a) (grauado)
Posted on:

Rate this post
0 useful
not useful
Lothar M. wrote:
>>Jason W. wrote
>> but what I wanted is:
>> 80>70>00>10>00>70>81>71>01>11>01>71>82>72>02>12>72>...etc
> Huh, then you have to twist those two digits. Because I assumed that the
> faster countig value is the rightmost digit.

So I'm guessing that what I need to twist is in this section?

signal cntlo : integer range 0 to 5 := 1; -- start with display 80!
signal cnthi : integer range 0 to 9 := 0;

process begin -- the prescaler and counter
   wait until rising_edge(clk);
   if one_second_counter < 9999998 then
      one_second_counter <= one_second_counter + 1;
   else
      one_second_counter <= 0;
      if cntlo<5 then
         cntlo <= cntlo+1;
      else
         cntlo <= 0;
         if cnthi<9 then
            cnthi <= cnthi+1;
         else
            cnthi <= 0;
            cntlo <= 0;
         end if;
      end if;
   end if;
end process;

displayed_number(15 downto 8) <= (others => '0');
displayed_number(7 downto 4) <= std_logic_vector(to_unsigned(cnthi, 4));
displayed_number(3 downto 0) <= x"7" when cntlo = 0 else
                                x"8" when cntlo = 1 else
                                x"7" when cntlo = 2 else
                                x"0" when cntlo = 3 else
                                x"1" when cntlo = 4 else
                                x"0";

how do I keep one digit at one seven seg's?
like "787010" use one seven seg's and other counter for one seven seg's?
something to do with here? e.g. [8,0] [7,0] [0,0] [1,0] [7,0]
process(LED_activating_counter, displayed_number)
begin
    case LED_activating_counter is
    when 0 =>
        Anode_Activate <= "1001"; 
        LED_BCD <= displayed_number(15 downto 12);
    when 1 =>
        Anode_Activate <= "1001"; 
        LED_BCD <= displayed_number(11 downto 8);
    when 2 =>
        Anode_Activate <= "1001"; 
        LED_BCD <= displayed_number(7 downto 4);
    when 3 =>
        Anode_Activate <= "1001"; 
        LED_BCD <= displayed_number(3 downto 0);
    end case;
end process;

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Jason W. wrote:
        Anode_Activate <= "1001"; 
        :
        Anode_Activate <= "1001"; 
        :
        Anode_Activate <= "1001"; 
        :
        Anode_Activate <= "1001"; 
Try to understand what "Anode_Activate" does. Then you will easily find 
out, why this is not working as you want to. At the moment it looks to 
me you are digging around in that design absolutely not knowing what and 
where, and so its a really laboriuos job to get you an the track...

> if one_second_counter < 9999998 then
This is almost fine for a 10MHz clock. But up to now its completely 
secret, what clock you really have, you know?

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig