Simple for you experienced folks

Discussion in 'VHDL' started by Dave Smith, Nov 24, 2005.

  1. Dave Smith

    Dave Smith Guest

    Greetings all -

    I am currently writing a simple module that reads a value from a lookup
    table based on two inputs, and then uses that value as a loop counter
    for the suqsequent instructions. The code I have looks like the
    following:

    --InjTable is declared as an 8x8 table of integers
    --enginespeed and engineload are input variables

    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    use ieee.std_logic_arith.all;

    widthcount := InjTable(enginespeed)(engineload);

    PulseWidth:loop
    InjPulse <= '1';
    widthcount := widthcount -1;
    exit when (widthcount = 0);
    end loop PulseWidth;


    I have also tried setting this up as a while loop and for loop, and
    everytime I get the same compile error that "loop must terminate at or
    before 10000 iterations". The largest table value is 64 so how can the
    compiler deduce this? Is there something wrong with the logic I've
    used to exit the loop??

    Thanks in advance
    Dave Smith, Nov 24, 2005
    #1
    1. Advertising

  2. Dave Smith

    Naren Guest

    Hi,
    it should be "exit when (widthcount == 0);".
    Rgds,
    Naren.
    Naren, Nov 24, 2005
    #2
    1. Advertising

  3. Dave Smith

    Dave Pollum Guest

    Naren wrote:
    > Hi,
    > it should be "exit when (widthcount == 0);".
    > Rgds,
    > Naren.


    Naren:
    "==" looks like "C". I just checked the book "HDL Chip Design" and as
    I suspected, it's valid for Verilog, but not for VHDL.

    Dave Smith:
    I wonder what type "widthcount" is. If it's an interger, I think "=0"
    should get you out of the loop. I haven't used loops yet in VHDL, so
    I'm not sure if your loop would get translated (synthesized) into
    actual logic. Perhaps this would work if it was part of a testbench?

    -Dave Pollum
    Dave Pollum, Nov 24, 2005
    #3
  4. Dave Smith

    Dave Smith Guest

    "==" does not work and it not proper for VHDL.

    Dave:

    Yes, widthcount is an integer, and the final code does need to be
    synthesizable because this is going into hardware.
    Dave Smith, Nov 24, 2005
    #4
  5. Dave Smith

    Duane Clark Guest

    Dave Smith wrote:
    > Greetings all -
    >
    > I am currently writing a simple module that reads a value from a lookup
    > table based on two inputs, and then uses that value as a loop counter
    > for the suqsequent instructions. The code I have looks like the
    > following:
    >
    > --InjTable is declared as an 8x8 table of integers
    > --enginespeed and engineload are input variables
    >
    > use ieee.std_logic_1164.all;
    > use ieee.std_logic_unsigned.all;
    > use ieee.std_logic_arith.all;
    >
    > widthcount := InjTable(enginespeed)(engineload);
    >
    > PulseWidth:loop
    > InjPulse <= '1';
    > widthcount := widthcount -1;
    > exit when (widthcount = 0);
    > end loop PulseWidth;
    >


    What is it you are trying to do? It appears you are trying to create a
    counter. But there is no clock, and there is no signal saying when to
    start the count. I would guess this is a homework problem? In general,
    do not use loops for counters. Assuming you are a student, the rest is
    left as an exercise.
    Duane Clark, Nov 24, 2005
    #5
  6. Dave Smith

    Dave Smith Guest

    You are correct, I am a student. However, this project has nothing to
    do with schoolwork. I am working on synthesizing a fuel injection
    controller using an FPGA. The loop occurs twice, and is supposed to
    act as a delay mechanism once a pulse is received by the camshaft
    position sensor.

    After receiving the pulse, a signal is set high while the loop is
    supposed to count down for the determined length (widthcount). This
    creates a variable width pulse for the injector. There is then a
    second loop afterwards that does the same thing, but the output signal
    is held low until the loop counts down (advancedelay). This output is
    the delayed spark plug fire pulse. Here is the code in its entirety:

    library ieee;

    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    use ieee.std_logic_arith.all;

    entity ECM is
    port(
    Starter,Kill : in std_logic;
    CamPos : in std_logic; -- Cam position sensor
    Knock : in std_logic; -- Knock sensor
    Tach,Load : in std_logic_vector(7 downto 0); -- Injector pulse
    sensors
    Temp : in std_logic_vector(7 downto 0); -- Spark advance sensors
    InjPulse,SpkPulse : out std_logic;
    clk : in std_logic);
    end ECM;

    Architecture behavior of ECM is
    Type state_type is
    (idle,InjSample,PulseCalc,SpkSample,AdvanceCalc,Send);
    Signal state,next_state : state_type;

    Signal enginespeed : integer;
    Signal engineload : integer;
    Signal cooltemp : std_logic_vector(7 downto 0);
    Signal templookup : integer;
    Shared Variable advancedelay : integer;
    Shared Variable widthcount : integer;


    --Definition of Injector Pulse Width Lookup Table
    type Row is array (0 to 7) of integer;
    type Table is array (7 downto 0) of Row;
    signal PRow0 : Row := (1,2,3,4,5,6,7,8);
    signal PRow1 : Row := (2,4,6,8,10,12,14,16);
    signal PRow2 : Row := (3,6,9,12,15,18,21,24);
    signal PRow3 : Row := (4,8,12,16,20,24,28,32);
    signal PRow4 : Row := (5,10,15,20,25,30,35,40);
    signal PRow5 : Row := (6,12,18,24,30,36,42,48);
    signal PRow6 : Row := (7,14,21,28,35,42,49,56);
    signal PRow7 : Row := (8,16,24,32,40,48,56,64);

    signal InjTable : Table :=
    (PRow7,PRow6,PRow5,PRow4,PRow3,PRow2,PRow1,PRow0);

    --Definition of Spark Advance Timing Lookup Table
    signal DelayTable : Row := (0,1,2,3,4,5,6,7);
    begin

    state_reg:process (clk,Starter,Kill)
    begin
    if (Starter = '1') then
    state <= InjSample;
    elsif (Kill = '1') then
    state <= idle;
    elsif (clk'event AND clk = '1') then
    state <= next_state;
    end if;
    end process;

    state_transition:process (state)

    begin
    case state is
    -- State while engine is not running
    when idle =>
    InjPulse <= '0';
    SpkPulse <= '0';
    -- Initial state once start triggers
    -- samples sensors needed for pulse width calculation
    when InjSample =>
    enginespeed <= Conv_Integer(Tach);
    engineload <= Conv_integer(Load);
    next_state <= PulseCalc;
    -- Calculates width of injector pulse from lookup table
    when PulseCalc =>
    widthcount := InjTable(enginespeed)(engineload);
    next_state <= SpkSample;
    -- Samples temperature value for spark delay calculation
    when SpkSample =>
    cooltemp <= Temp;
    next_state <= AdvanceCalc;
    -- Calculates spark delay time from lookup table
    when AdvanceCalc =>
    if (Knock = '1') then
    -- If knock is detected, divide the temperature advance value
    cooltemp <= '0' & cooltemp(7 downto 1);
    end if;
    templookup <= Conv_Integer(cooltemp);
    advancedelay := DelayTable(templookup);
    next_state <= Send;
    -- Outputs injector and spark pulse at proper timing.
    when Send =>
    if (CamPos = '1') then
    -- Trigger injector pulse for determined length
    PulseWidth:loop
    InjPulse <= '1';
    widthcount := widthcount
    -1;
    exit when (widthcount =
    0);
    end loop PulseWidth;
    InjPulse <= '0';
    -- Wait for determined time to start spark
    SparkDelay:loop
    SpkPulse <= '0';
    advancedelay := advancedelay
    -1;
    exit when (advancedelay = 0);
    end loop SparkDelay;
    SpkPulse <= '1';
    next_state <= InjSample;
    end if;
    end case;
    end process;
    End behavior;

    Again, this code is not finalized and I'm aware there are other flaws.
    I'm just after why I can't seem to get this to compile. BTW, I'm using
    Altera Quartus II if that has any effect.
    Dave Smith, Nov 26, 2005
    #6
  7. Dave Smith wrote:

    > Signal enginespeed : integer;
    > Signal engineload : integer;


    this is a 32 bit signed value. maybe
    subtype measure_t is natural range 0 to 511;
    is more reasonable

    > Shared Variable advancedelay : integer;
    > Shared Variable widthcount : integer;


    only signals or process variables for synthesis.

    > type Row is array (0 to 7) of integer;
    > type Table is array (7 downto 0) of Row;
    > signal PRow0 : Row := (1,2,3,4,5,6,7,8);

    ^^^^^^
    constant

    > Again, this code is not finalized and I'm aware there are other flaws.


    Consider vhdl simulation to find and remove the flaws
    and to tune up the design.

    > I'm just after why I can't seem to get this to compile. BTW, I'm using
    > Altera Quartus II if that has any effect.


    I compile for synthesis only after I
    have simulation waveforms that look ok.
    Synthesis by trial and error is very tedious.

    -- Mike Treseler
    Mike Treseler, Nov 26, 2005
    #7
  8. Dave Smith

    Duane Clark Guest

    Dave Smith wrote:
    > You are correct, I am a student. However, this project has nothing to
    > do with schoolwork. I am working on synthesizing a fuel injection
    > controller using an FPGA.


    Okay, my apologies. Actually, it sounds like it might have the makings
    of a good homework problem.

    > The loop occurs twice, and is supposed to
    > act as a delay mechanism once a pulse is received by the camshaft
    > position sensor.


    Then what you want is a counter (or shift register), clocked by the
    clock you already have. Your state machine should output signals to
    control it. You will find it virtually impossible to make a "delay" work
    in an FPGA. While it is not completely impossible, don't bother trying;)
    Duane Clark, Nov 27, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page