0

I recently almost finished my project(I need to create the frequency divider(50MHZ->1HZ(1s)) and to finish the 7 segment display decoder ) . My project consist in a timer(counts down to 00:00 triggering an alarm and counts up if the current state is 00:00) . The project runs good on Active HDL Simulator but I don't know if it works on FPGA . I written the code using behavioral method using 1 process . My question is : Does my code works on FPGA if I finish the frequency divider ? If not how can I modify the code to work ?

My code :

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
use IEEE.STD_LOGIC_arith.all;

entity Timer is
    port(start_stop,M,S : in std_logic; --Start/Stop , Minutes,Seconds
    clk : in std_logic; -- clock 1 MHz
    alarm : out std_logic; -- alarm/buzzer
    s1,s2,m1,m2 : inout std_logic_vector(6 downto 0)); --BCD to 7segment display representation for seconds and minutes
end Timer;
--}} End of automatically maintained section

architecture Timer of Timer is
signal sec1,sec2,min1,min2 : std_logic_vector(3 downto 0);
signal T : std_logic := '0';    
signal done : std_logic;  
signal cu : std_logic;
component seg7 is
    port(bcd : in std_logic_vector(3 downto 0);
    output : out std_logic_vector(6 downto 0)
    );
end component;

begin   
P0 : process(clk,start_stop,M,S)
variable temp1,temp2,temp3,temp4 : std_logic_vector(3 downto 0);
variable carry_s,carry_m : std_logic;   
variable alarm_counter : std_logic_vector(3 downto 0) := "1111"; -- buzzer/alarm counter
begin                             
    if(M = '1'and S = '1' and start_stop = '0') 
    then
    temp1 := "0000";
    temp2 := "0000";
    temp3 := "0000";
    temp4 := "0000";
    sec1 <= temp1;
    sec2 <= temp2;  
    min1 <= temp3;
    min2 <= temp4;
    alarm <= '0'; 
    done <= '0';
    T <= '0';--RESET when you press M and S 
    elsif(M = '0' and S = '1' and start_stop = '0')
        then 
        temp1 := temp1 + "0001";
        if(temp1 = "1010")
            then
            temp1 := "0000";
            carry_s := '1';
        else
            carry_s := '0';
        end if;
        if(carry_s = '1')
            then
            temp2 := temp2 + "0001";
            if(temp2 = "0110")
                then
                temp2 := "0000";
                carry_s := '0';
            end if;
        end if;
        sec1 <= temp1;
        sec2 <= temp2;-- Increment seconds when you press M 
    elsif(M = '1' and S = '0' and start_stop = '0')
        then 
        temp3 := temp3 + "0001";
        if(temp3 = "1010")
            then
            temp3 := "0000";
            carry_m := '1';
        else
            carry_m := '0';
        end if;
        if(carry_m = '1')
            then
            temp4 := temp4 + "0001";
            if(temp4 = "1010")
                then
                temp4 := "0000";
                carry_m := '0';
            end if;
        end if;
        min1 <= temp3;
        min2 <= temp4;-- Increment minutes when you press M  
    elsif(S = '0' and M = '0' and start_stop = '1')
        then
        alarm <= '0';
        T <= T xor '1';-- T Flip Flop behaviour 
        if(sec1 /= "0000" or sec2 /= "0000" or min1 /= "0000" or min2 /= "0000")
        then
        cu <= '0';
    else
        cu <= '1';
        end if; -- counting directions
    elsif(T = '1' and RISING_EDGE(clk))
        then  
        if(cu = '0')
            then
            done <= '0';
            temp1 := temp1 - "0001";
            if(temp1 = "1111")
                then
                temp2 := temp2 - "0001";
                temp1 := "1001";
            end if;
            if(temp2 = "1111")
                then
                temp2 := "0101";
                carry_s := '1';
            else
                carry_s := '0';
            end if;
            if(carry_s = '1')
                then
                temp3 := temp3 - "0001";
                if(temp3 = "1111")
                    then
                    temp4 := temp4 - "0001";
                    temp3 := "1001";
                end if;
            end if;
            if(temp1 = "0000" and temp2 = "0000" and temp3 = "0000" and temp4 = "0000")
                then
                done <= '1';
            end if;
            sec1 <= temp1;
            sec2 <= temp2;   
            min1 <= temp3;
            min2 <= temp4;-- counting down
        else
            temp1 := temp1 + "0001";
            if(temp1 = "1010")
                then
                temp1 := "0000";
                temp2 := temp2 + "0001";
            end if;
            if(temp2 = "0110")
                then
                temp2 := "0000";
                carry_s := '1';
            else
                carry_s := '0';
            end if;        
            if(carry_s = '1')
                then
                temp3 := temp3 + "0001";
                if(temp3 = "1010")
                    then
                    temp3 := "0000";
                    temp4 := temp4 + "0001";
                    if(temp4 = "1010")
                        then
                        temp4 := "0000";
                        T <= '0';
                        end if;
                    end if;
                end if;
            sec1 <= temp1;
            sec2 <= temp2;   
            min1 <= temp3;
            min2 <= temp4;-- counting up
        end if; 

     end if;

       if(done = '1')
            then  
            T <= '0'; 
            alarm_counter := alarm_counter - "0001";
            alarm <= '1'; 
            if(alarm_counter = "0000")
                then
                done <= '0';
                alarm <= '0';
                end if;
        else
            alarm_counter := "1111";
            alarm <= '0';
        end if;-- when the alarm starts 

end process P0;

C1 : seg7 port map (sec1,s1);
C2 : seg7 port map (sec2,s2);
C3 : seg7 port map (min1,m1);
C4 : seg7 port map (min2,m2);
-- seven segment display port mapping
end Timer;

EDIT : I fixed the code

Călin Calin
  • 155
  • 2
  • 10
  • Possible duplicate of [VHDL How to attach a frequency divider to a project?](http://stackoverflow.com/questions/37036019/vhdl-how-to-attach-a-frequency-divider-to-a-project) – PlayDough May 05 '16 at 15:09
  • 1
    @PlayDough: This question has nothing to do with port mapping which the other one asked about. Yes, they're by the same author and about the same code, but that doesn't make them duplicates. – Ben Voigt May 05 '16 at 15:18
  • @BenVoigt I disagree. The other one did mention port mapping, but ultimately the question had nothing to do with it because a) it never asked anything specific about the port mapping (only a vague "[h]ow to use port mapping") and b) it ended up with a question about whether it was functional and synthesizable. This question is essentially the same question. – PlayDough May 05 '16 at 15:26

1 Answers1

3

No, that design isn't synthesizable.

In particular, you have asynchronous feedback here:

if(M = '0' and S = '1')
    then 
    temp1 := temp1 + "0001";

All counting logic must be clocked. In the simulator, the sensitivity list on the process prevents this feedback from running away, but in real hardware asynchronous cycles will go nuts.

Try using this structure instead:

if (M = '1' and S = '1') then
    -- async reset
elsif RISING_EDGE(clk) then
    --all other logic for setting modes, counting, limits goes here
endif

The RISING_EDGE function is roughly the same as clk = '1' and clk'event except that it is much more meaningful to a human looking at the code, and has a few more advantages.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • If I fix this can be implemented on FPGA? – Călin Calin May 05 '16 at 14:34
  • 1
    It's completely feasible to build a alarm clock of this complexity in an FPGA, yes. – Ben Voigt May 05 '16 at 14:38
  • I wouldn't be happy with this: `if (M = '1' and S = '1') then`. From what I can understand by briefly reading the code, `M` and `S` are functional inputs ("minutes" and "seconds"). Functional logic should never control an asynchronous reset; the only signal that should drive an asynchronous reset is a dedicated reset signal that whose only function is to put the chip into a known state. Driving an asynchronous reset with any other signal is not _synchronous design_. – Matthew Taylor May 05 '16 at 15:04
  • If I press M and S simultaneously the timer will reset to 00:00 . Do I need a signal `reset` that when M = 1 and S = 1 then reset = '1' and will reset the timer ? – Călin Calin May 05 '16 at 15:14
  • @CălinCalin: The VHDL analyzer is smart enough to create an intermediate signal `areset = (M and S)`, you don't need to do that explicitly. – Ben Voigt May 05 '16 at 15:15
  • @MatthewTaylor: I believe those are inputs driven by user buttons. Yes, some debouncing might be appropriate (and perhaps immediately after reset, ignore both buttons completely until both have been released, rather than potentially moving through a 1/0 or 0/1 state on the way to 0/0) I don't call driving an asynchronous reset with another signal *synchronous design*, I call it *sometimes necessary*. – Ben Voigt May 05 '16 at 15:16
  • I would say it is better design style to reset the clock synchronously using `M` and `S` and asynchronously using (eg) some power on reset signal. When I teach this stuff I use this very similar example: Imagine a stop watch. The asynchronous reset is what should reset the stop watch to zero when you put a new battery in; the synchronous reset is what should reset the stop watch to zero when the timekeeper clicks the reset button, to get ready for the next race. – Matthew Taylor May 05 '16 at 15:34
  • @MatthewTaylor It's ok if I sync the `M` and `S` the default 50 Mhz FPGA clock and the counting with divided 1 HZ clock ? – Călin Calin May 05 '16 at 15:49
  • @CălinCalin The answer to that question is too long for a comment. I guess I must be careful not to make the best be the enemy of the good: I would say there are probably many issues in your code, but if you make the change that Ben Voigt recommended you might see something working, which will be (a) cool and (b) motivating. I would take a look at my answer [here](http://stackoverflow.com/questions/37039086/alternate-way-for-port-map-in-process) - the specifics are obviously not relevant, but the general advice (eg about templates) certainly is. – Matthew Taylor May 05 '16 at 16:03