1

I'm trying to implement some logic that is either triggered on a rising or falling edge of the same clock, depending on a clock polarity signal. I tried the following but got an error message in Quartus 15.1 (error id: 10628): "Can't implement register for two clock edges combined with a binary operator".

process(clk)
begin
    if (rising_edge(clk) and pol='0') or (falling_edge(clk) and pol='1') then
        -- logic
    end if;
end process;

My current workaround is to just write the whole logic block twice, once with each condition separately. But since the logic block isn't that small and still under development this really isn't optimal. Does anyone have a better solution to this?

Edit: One easy way to achieve this would be a gated clock, but from what I understand, this is generally a bad idea, so I tried to do it without a mux or xor in the clock path.

  • 1
    Think about it: you will add logic in your clock line. This will add delay, affecting timing. Possibly causing sync issues. You don't want to do this with normal logic blocks. Use the DCM or PLL or what ever your fpga has. About the error: the synthesizer can only infer a register for a single clock edge. That's just the way it is. Use either a clock block or double logic. – JHBonarius Jan 18 '22 at 18:03
  • I don't know about those programs specifically, but the error message indicates a problem with the binary operator. This is probably a datatype issue. You set pol = '0' (a string) instead of pol = 0 (a true value). Now forgive me if this doesn't apply, but in other situations datatypes are usually the issue when it looks like it should work but doesn't. Can't compare a word to a number and all that. – easleyfixed Jan 18 '22 at 18:04
  • @JHBonarius Thanks for your answer. Why is this adding logic into the clock line and is it still doing that with my workaround? I also could not find any info on how to invert a clock with a PLL. FPGA is a Cyclone V. – tobiashellbusch Jan 18 '22 at 18:15
  • Nvm the PLL part, I can phase shift it 180 degrees. Although I'm not sure what to provide as reference frequency and output frequency, because the frequency is not known beforehand. Does it even matter or is the multiplier the only important part? – tobiashellbusch Jan 18 '22 at 18:26
  • @easleyfixed Thanks, but this really does not apply here at all. '0' is not a string but a ieee.std_logic_1164.std_logic. – tobiashellbusch Jan 18 '22 at 18:30
  • 1
    A register is a fixed block in the fpga. It has one clock input and can act on EITHER rising OR falling edge. There is no active logic to change that: it's fixed after synthesis. Changing the clock edge on the fly, requires you to modify the clock input to a register. I.e. put logic in the clock line. Logic adds delay, so the clock to those register will be out off sync with the other parts of the fpga. A double set of registers will not have logic in the clock line. One set will be rising edge and the second falling edge. – JHBonarius Jan 18 '22 at 19:00
  • Good to know, in some languages and DBs the difference between value = '0' and value = 0 are completely different, Godspeed on getting it going. – easleyfixed Jan 18 '22 at 20:12

1 Answers1

1

Edit: I misunderstood the question. The below only applies if pol is a constant:

Try the oldschool way of writing this, with separate event attribute and level:

if clk'event and clk = pol then
  -- logic
end if;

If pol is '1', this synthesises to the same thing as rising_edge(clk).

blueshift
  • 6,742
  • 2
  • 39
  • 63
  • Thanks, but I already tried this and it doesn't work. From what I understand, Quartus needs to be able to infer a rising or falling clock edge from a clock event, and throws an error if it can't. – tobiashellbusch Jan 21 '22 at 22:07
  • You are right. I was assuming `pol` was a constant, you said it is a signal. If it can vary at run-time, you will need to do something else. – blueshift Jan 24 '22 at 01:44
  • Sorry, I probably should have made that more clear. In that case your solution looks quite elegant, but it comes with the disadvantage of detecting transitions from undefined to 1 (or 0). – tobiashellbusch Jan 25 '22 at 09:12
  • I think you will find that it synthesises to exacly the same logic as e.g. `rising_edge()` would. – blueshift Jan 27 '22 at 03:34
  • For synthesis yes, but they behave slightly different when simulated. Either way, I solved my problem by instantiating the whole component twice, with a different clk_pol generic, and then using your approach within the component. On the top level I then use my actual clk_pol signal to mux the data ouputs of the two. – tobiashellbusch Jan 28 '22 at 08:39