Simple for you experienced folks

D

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
 
Hi,
it should be "exit when (widthcount == 0);".
Rgds,
Naren.
 
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
 
"==" 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 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.
 
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 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
 
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;)
 

Welcome to EDABoard.com

Sponsor

Back
Top