0
votes

I'm developing control algorithms on FPGAs, but I can't claim to be experienced with VHDL. One functionality I needed is a sort of 'Trigger Upscaler', so I want to increase the trigger frequency instead of decreasing it.

Here's an explanation:

enter image description here I got a system clk of 50 MHz and got a trigger pulse for 1 clk cycle with 1 kHz frequency, thus one each ms. This trigger is the start for certain calculus which has to run faster than that. So I wonder if I can generate a new trigger with 10 kHz. Here's the essential code I have so far:

  calc_prescaler: process

 begin
  wait until rising_edge(clk);

  -- When a new trig appears, send 1 tick and reset counters
  if trig_in = '1' then
     cnt_clk    <= (others => '0');
     cnt_active <= '1';
     trig_out <= '1';
     trig_count <= (others => '0');
  else 
     trig_out <= '0';

     -- Safety feature: Do not send more ticks than estimated
     -- Useful in case trig_in freezes
     if trig_count > par_max - 1 then
        cnt_active <= '0';
        trig_count <= (others => '0');
     end if; 

     if cnt_active = '1' then
        cnt_clk <= cnt_clk + 1; 
     end if;

     -- If Counter reaches desired values, send 1 tick and increase tick counter
     if cnt_clk = par_fac - 1 then
        trig_count <= trig_count + 1;
        trig_out <= '1';
        cnt_clk <= (others => '0');
     end if; 
  end if; 


  -- Reset
  if res_n = '0' then   

    trig_out        <= '0';

    cnt_clk         <= (others => '0');
    trig_count      <= (others => '0');
    cnt_active      <= '0';                 

  end if;

There are two variable, par_fac with is the ratio between desired (higher) trigger frequency and system clk and par_max which is number of ticks on trig_out if there is no new trig_in.

Works for me so far, but the issue is that the two trigger are not in sync, there is a delay of 1 clk cycle.

Have you got any advice how to modify my approach? Any way to implement is welcome, the only requirements I have are: - no delay between trig_in and trig_out - no trig_out ticks if trig_in ticks stop

1

1 Answers

0
votes

In any sequential logic the output is always delayed by one clock cycle with respect to the input. This means that you cannot generate the very first tick for each trigger input inside the process.

if trig_in = '1' then
    cnt_clk    <= (others => '0');
    cnt_active <= '1';
    --trig_out <= '1'; don't do this
    trig_count <= (others => '0');

For the remaining ticks, just generate them one clock cycle earlier by using a lower counter value:

if cnt_clk = par_fac - 1 then
   trig_count <= trig_count + 1;
   --trig_out <= '1'; don't do this
   cnt_clk <= (others => '0');
end if;
-- instead:
if cnt_clk = par_fac - 2 then
    trig_out <= '1';
end if;

Then, outside the process, wherever you previously used trig_out you now use trig_in or trig_out.