Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
17 years ago

Timing Problem(Clock Edge)

Dear all,

I'm new to VHDL and need all u guys out there,

I'm currently designning a VHDL code for traffic light (two processes) coding style and i bump to this error regarding clock timing:

Error (10818): Can't infer register for "state.s0" at traffic.vhd(44) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "state.s1" at traffic.vhd(44) because it does not hold its value outside the clock edge

and so on......

All ur help will be deeply appreciate by me.. enlight me... thx

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    here is de code:

    library IEEE;

    use IEEE.std_logic_1164.all;

    use IEEE.std_logic_arith.all;

    use IEEE.std_logic_unsigned.all;

    entity traffic is

    port (

    CLK : in std_logic;

    RST : in std_logic;

    car : in std_logic;

    pedestrian : in std_logic;

    Digit1_o : out unsigned (3 downto 0);

    Digit10_o : out unsigned (3 downto 0);

    lights : out std_logic_vector (6 downto 0)

    );

    end traffic;

    architecture traffic_arch of traffic is

    type state_type is (s0,s1,s2,s3,s4,s5,s6,s7);

    signal state : state_type;

    signal Digit1 : unsigned (3 downto 0);

    signal Digit10 : unsigned (3 downto 0);

    begin

    main:process(CLK,RST,car,pedestrian)

    begin

    if pedestrian = '1' then

    state <= s4;

    if RST = '1' then

    state <= s0;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    if CLK'event and CLK = '1' then

    case state is

    when s0 =>

    if Digit1 < 9 then

    state <= s0;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 5 then

    state <= s0;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s1;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    end if;

    end if;

    when s1 =>

    if (car = '1') then

    state <= s2;

    else

    if Digit1 < 9 then

    state <= s1;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 2 then

    state <= s1;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s2;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    end if;

    end if;

    end if;

    when s2 =>

    if Digit1 < 9 then

    state <= s2;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 0 then

    state <= s2;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s3;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    end if;

    end if;

    when s3 =>

    if Digit1 < 2 then

    state <= s3;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 0 then

    state <= s3;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s4;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    end if;

    end if;

    when s4 =>

    if Digit1 < 9 then

    state <= s4;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 2 then

    state <= s4;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s5;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    end if;

    end if;

    when s5 =>

    if (car = '1') then

    if Digit1 < 9 then

    state <= s5;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 2 then

    state <= s5;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s6;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    if (car = '0') then

    state <= s6;

    end if;

    end if;

    end if;

    end if;

    when s6 =>

    if Digit1 < 9 then

    state <= s6;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 0 then

    state <= s6;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s7;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    end if;

    end if;

    when s7 =>

    if Digit1 < 2 then

    state <= s7;

    Digit1 <= Digit1 + 1;

    if

    Digit10 < 0 then

    state <= s7;

    Digit1 <= (others=>'0');

    Digit10 <= Digit10 + 1;

    else

    state <= s0;

    Digit1 <= (others=>'0');

    Digit10 <= (others=>'0');

    end if;

    end if;

    when others =>

    state <= s0;

    end case;

    end if;

    end if;

    end if;

    end process main;

    Digit1_o <= Digit1;

    Digit10_o <= Digit10;

    sub:process(state)

    begin

    case state is

    when s0 =>

    lights <= "1011011";

    when s1 =>

    lights <= "1011011";

    when s2 =>

    lights <= "1010111";

    when s3 =>

    lights <= "1001111";

    when s4 =>

    lights <= "1101101";

    when s5 =>

    lights <= "1101101";

    when s6 =>

    lights <= "1101110";

    when s7 =>

    lights <= "1001111";

    when others =>

    lights <= "1011011";

    end case;

    end process sub;

    end traffic_arch;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You are missing some elses in the main process... You should start with replacing the two ifs (on RST and CLK'event) with elsifs and see what happens

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks for ur comment.. i will try it out.. and certainly.. appreciate de help from u guys..

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Also I would look at the structure of your process. You have to be very strict with your coding style for synthesis:

    
    process (clk, reset_n, async_load)
    begin
    if reset_n = '0' then
        -- ansynchonous clear assignments
    elsif async_load = '1' then
        -- asynchronous load assignments
    elsif rising_edge(clk) then
        -- put your register assignments (i.e. your state machine) in here
    end if;
    end process

    Of course you don't have to have the asynchronous reset or load in there:

    
    process (clk)
    begin
    if rising_edge(clk) then
        -- put your register assignments (i.e. your state machine) in here
    end if;
    end process

    Don't be tempted to add anything else into the rising_edge(clk) line as this will give you a gated clock.

    Altera have some guidelines on coding for synthesis (which are pretty much the same as other FPGA manufacturers):

    http://www.altera.com/literature/hb/...din g%20style (http://www.altera.com/literature/hb/qts/qts_qii51007.pdf?gsa_pos=1&wt.oss_r=1&wt.oss=coding%20style)

    By the way the "clk'event and clk = '1'" notation that you've used is fine and basically the same as "rising_edge(clk)" - the only real difference is that the latter works with transitions like 'L' to 'H' in simulation - for synthesis it won't make a difference.

    I would start by tweaking your code to comply with this sort of standard and I'm sure you will get rid of the errors, a whole load more warnings that you haven't noticed yet and a whole load of nasties still waiting in the wings.

    Probably something like this:

    
    process (CLK,RST)
    begin
    if RST = '1' then
        state <= s0;
        Digit1 <= (others=>'0');
        Digit10 <= (others=>'0');
    elsif CLK'event and CLK = '1' then
        if pedestrian = '1' then
            state <= s4;
        else
            case state is
                    when s0 =>
                 -- etc etc
        end if;
    end if;
    end process

    Your pedestrian signal is now effectively a synchronous reset but note that the reset and clk conditions are as above.

    Hope this helps - the coding style document is really worth a read.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks for all ur comments. i hav finished modifying de traffic code and now it is really works.. sorry if i bother u all too much..

    another question.. de prob that i facing now is that i want to generated a 1 Hz clock using clock divider method from the original crystal frequency of 33.333 MHz.. The FPGA board that I'm using is Apex20k EFC200-484 from Altera

    de code is as below :

    begin

    cloc:process(clk)

    variable cnt : integer range 0 to 16500000;

    begin

    if(clk'event and clk='1') then

    if(cnt=16500000)then

    cnt:=0;

    clkout<='1';

    else

    cnt := cnt+1;

    clkout<='0';

    end if;

    end if;

    end process cloc;

    I had compiled the code above.. and when i simulate for 2 seconds .. it took me overnite to finish .. anyone hav better idea than this method? thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    sorry if i bother u all too much..

    --- Quote End ---

    No worries - the forum exists for us all to help each other.

    As for your clock divider - the code looks fine - the real question is the headache of the simulation job. I'm sure that you'll get a few different bits of advice on this. Personally I would break down the task into a few different objectives.

    You've done your big simulation to show that your clock divider works with the correct frequencies - i.e. for a 33 MHz clock and a division of 16500000 you get a 1 Hz output.

    Now you want to check that this interacts with everything else in the design which will be the case regardless of the frequencies involved, so change your division to something much quicker - everything based on the 1Hz clock will obviously happen much faster than in real life but you know that when you change your divider constant for synthesis, you will get the right result.

    What I sometimes do is use the "--translate synthesis_off" and "--translate synthesis_on" comments to mask off bits from synthesis so that no code changes are required between simulation and synthesis.

    constant division : integer := 16500000;
    constant division_sim : integer := 165;
    phttp://www.alteraforum.com/images/smilies/tongue.gifrocess(clk)
    variable cnt : integer range 0 to 16500000;
    begin
    if(clk'event and clk='1') then
    if(cnt=0)then
        cnt:=division;
        -- translate synthesis_off
        cnt := division_sim;
        -- translate synthesis_on
        clkout<='1';
    else
        cnt := cnt-1;
        clkout<='0';
    end if;
    end if;
    end process cloc;

    Basically what happens here is your counter gets loaded with the large value and then decrements to zero. At zero, your output goes high and the counter is reloaded. Now for simulation, you load cnt with division (16500000), then straight way before this value has any effect, you load cnt again but with division_sim (165). For synthesis, the translate pragmas mask off the second assignment and so cnt only gets loaded with division.

    This way you can use the same code for (speeded up) simulation and (real time) synthesis.

    Hope you find this useful.