Electronics > FPGA

timed state machines VHDL

(1/8) > >>

sahko123:
I'm struggling to get timed state machines working in reality, simulations seem to be ok though.

The basic premise is that there is a list of cases for a state variable and the conditions are checked after a few clock cycles decided by a separate timer/counter which is reset when the next state is triggered when simulating it everything works flawlessly but in fabric (on a max V dev kit) the logic falls apart and doesnt continue through all the states the way it should. sometimes it goes back a state where it shouldnt be possible to.

I believe this is something timing related so could anyone suggest a better way of going about doing this? For context this is for a multislope ADC.

ejeffrey:
Is your synthesis tool giving you any warnings about clocks or timing?  Any inferred latches? Are you using wildcard sensitivity lists on all of your combinatoric logic?  Are you doing comparison against X values?  Are your external inputs stable?

If you follow the rules you shouldn't get simulation synthesis mismatch and the tools should generally warm you about problematic usage but unfortunately vendor IPs have so many meaningless warnings that it can be hard to notice ones that matter.

SiliconWizard:
Maybe post your code?

sahko123:
Here is a good chunk of the code excluding most declarations.



architecture behavioral of converter is


signal RP_COUNT:signed(23 downto 0):=(others=>'0');--runup counter
signal count_stage12:unsigned(7 downto 0):=(others=>'0');--10k rundown
signal count_stage34:unsigned(7 downto 0):=(others=>'0');--80k pos(4MSB) 640k neg(4LSB)
signal count_stage5:unsigned(7 downto 0):=(others=>'0');--5.12M pos
signal state:std_logic_vector(3 downto 0):=(others=>'0');
signal timer:std_logic_vector(3 downto 0):=(others=>'0');
signal timer_reset:std_logic:='0';
signal comp_hold:std_logic:='0';--flag for comparator input


component counter is
port(
count_out:out std_logic_vector(3 downto 0);
RST,CLK:in std_logic:='0'
);
end component;
begin

state_output_0<=not state(0);
state_output_1<=not state(1);
CLK_pass<=CLK;
time_counter:counter port map(count_out=>timer,CLK=>CLK,RST=>timer_reset);

--control registers
process(address,CLK) begin
   --if rising_edge(clk) then
   case address is
      when "0000" => data<=std_logic_vector(count_stage12);
      when "0001" => data<=std_logic_vector(count_stage34);
      when "0010" => data<=std_logic_vector(count_stage5);
      when "0011" => data<=std_logic_vector(RP_COUNT(7 downto 0));
      when "0100" => data<=std_logic_vector(RP_COUNT(15 downto 8));
      when "0101" => data<=std_logic_vector(RP_COUNT(23 downto 16));
      when "0110" => data<="01010101";
      when "0111" => data(3 downto 0)<=timer;data(7 downto 4)<=(others=>'0');
      when "1000" => data(3 downto 0)<=state;data(7 downto 4)<=(others=>'0');
      --when others => data<=(others=>'Z');
      when others => data<="01010101";
      
   end case;
   --end if;
end process;

--conversion process



process(CLK) begin

case state is

-----------------------------------------------initial state
when "0000" =>
SW_sample<='0';
SW10K1<='0';
SW10K2<='0';
SW80K3<='0';
SW640K4<='0';
SW5120K5<='0';
timer_reset<='0';
if CONV='1' then --if conversion triggered
state<="0001";
timer_reset<='1';
end if;
-----------------------------------------------pause before conversion
when "0001"=>
timer_reset<='0';
RP_COUNT<=(others=>'0');
count_stage12<=(others=>'0');
count_stage34<=(others=>'0');
count_stage5<=(others=>'0');
SW_short<='1';
if timer="0101" then
state<="0010";
timer_reset<='1';
end if;
-----------------------------------------------t1 sample
when "0010"=>
SW_short<='0';
timer_reset<='0';
SW_sample<='1';
comp_hold<=comp;
if timer="0111" then
timer_reset<='1';
state<="0011";
end if;
-----------------------------------------------runup
when "0011"=>
timer_reset<='0';

if comp_hold='0' then
SW10K1<='1';--positive ramp
SW10K2<='0';
else
SW10K1<='0';--negative ramp
SW10K2<='1';
end if;

if timer="1010" then --if timer=10
if comp_hold='1' then
RP_COUNT<=RP_COUNT+1;
comp_hold<=comp;
else
RP_COUNT<=RP_COUNT-1;
comp_hold<=comp;
end if;
timer_reset<='1';
state<="0100";
end if;
-----------------------------------------------recharge
when "0100"=> --recharge
timer_reset<='0';
SW10K1<='0';
SW10K2<='0';
if timer="0011" then
timer_reset<='1';
if CONV='1' then
state<="0011";
else
state<="0101";
end if;
end if;
-----------------------------------------------rundown 10k pos
when "0101"=>
SW10K2<='0';
if CLK<='1' then
comp_hold<=comp;
end if;

if comp_hold=not comp then
SW10K1<='1';--positive ramp
count_stage12<=count_stage12+1;
else
state<="0110";
end if;

nctnico:
You need to make your logic synchronous. Asynchronous logic doesn't work very well (usually not at all) in an FPGA.

Undo this comment:
--if rising_edge(clk) then

 and make all your other logic synchronous as well if there is an 'if then' clause

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod