3
\$\begingroup\$

Look at this piece of code (flip image on X)

PROCESS(iCLK) 
BEGIN
  IF (rising_edge(iCLK)) THEN 
    -- Mise en mémoire du pixel
    ram(640*IdxC + PixX) <=  PIXIN; 
    -- Choix traitement
    IF (SWITCH='1') THEN
      PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
    ELSE
      PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
    END IF; 
  END IF;   
END PROCESS;

When I compile it, the overall project takes about 15% of the logic elements and 13% of total memory bits (QuartusII on cyclone III). If I change the code to

PROCESS (iCLK)
BEGIN
  IF(rising_edge(iCLK)) THEN 
    -- Mise en mémoire du pixel
    ram(640*IdxC + PixX) <=  PIXIN; 
    -- Choix traitement
    IF (SWITCH='1') THEN
      PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
    ELSE
      IF (PixX > 1 AND PixX < 640) THEN
        PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
      ELSE
        PIXOUT <= x"111";
      END IF;
    END IF; 
  END IF;   
END PROCESS;

I get

Error (276003): Cannot convert all sets of registers into RAM megafunctions when creating nodes. The resulting number of registers remaining in design exceeds the number of registers in the device or the number specified by the assignment max_number_of_registers_from_uninferred_rams. This can cause longer compilation time or result in insufficient memory to complete Analysis and Synthesis

That seems that I cannot fit anymore the design. I don't believe this. Is there a bug on the compiler or I'm doing something wrong?

I have the Quartus II web edition

Just putting some -- comments on the lines like this and it compiles again:

PROCESS (iCLK)
BEGIN
  IF (rising_edge(iCLK)) THEN
    -- Mise en mémoire du pixel
    ram(640*IdxC + PixX) <= PIXIN;
    -- Choix traitement
    IF (SWITCH='1') THEN
      PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
    ELSE
   -- IF (PixX > 1 AND PixX < 640) THEN
        PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
   -- ELSE
   --   PIXOUT <= x"111";
   -- END IF;
    END IF;
  END IF;
END PROCESS;

This code works with megafunction RAM 2 port:

PROCESS (iCLK)
BEGIN
  IF rising_edge(iCLK) THEN     
    -- Ecrire linéairement dans la RAM le pixel de la cam
    RAMWRITE <= TO_UNSIGNED(640*IdxC + PixX - 1, 11);
    -- Choix traitement
    IF (SWITCH='1') THEN
      RAMREAD <= TO_UNSIGNED(640*((IdxC + 1) mod 2) + PixX - 1, 11);
      PIXOUT <= PIXMEM;
    ELSE
      RAMREAD <= TO_UNSIGNED(640*(2-IdxC) - PixX, 11);
      IF (PixX > 1 AND PixX < 640) THEN
        PIXOUT <= PIXMEM;
      ELSE
        PIXOUT <= x"FFF";
      END IF;
    END IF;     
  END IF;                       
END PROCESS;
\$\endgroup\$
6
  • \$\begingroup\$ Are you absolutely sure that that's the only thing that changed in the whole design? \$\endgroup\$
    – Dave Tweed
    Jan 12, 2013 at 14:44
  • \$\begingroup\$ Absolutely, just putting some -- comment on the lines like this and it compiles again: PROCESS(iCLK) BEGIN IF(rising_edge(iCLK)) THEN -- Mise en mémoire du pixel ram(640*IdxC + PixX) <= PIXIN; -- Choix traitement IF (SWITCH='1') THEN PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX); ELSE -- IF (PixX > 1 AND PixX < 640) THEN PIXOUT <= ram(640*(2-IdxC) - PixX + 1); -- ELSE -- PIXOUT <= x"111"; -- END IF; END IF; END IF; END PROCESS; \$\endgroup\$ Jan 12, 2013 at 15:56
  • 1
    \$\begingroup\$ Does look as if you have hit some limitation on the synthesis tool rather than faulty VHDL code. It's decided it can't recognise the RAM and infer a RAM block because of the extra clause. To work around it, try creating a variable (or signal) that is purely RAM output (not necessarily valid), and separate logic to blank it when desired, rather than doing both tasks in one nested "IF" statement. Should work in a single process though. \$\endgroup\$
    – user16324
    Jan 12, 2013 at 16:07
  • \$\begingroup\$ I edited your comment back into the question so that it is readable. But I'm baffled as to why this simple change should cause the design to "blow up". Perhaps you should show us the rest of the module in which this appears. \$\endgroup\$
    – Dave Tweed
    Jan 12, 2013 at 16:08
  • \$\begingroup\$ You may find even else PIXOUT <= ram(some addr) or x"111"; will do... \$\endgroup\$
    – user16324
    Jan 12, 2013 at 16:15

1 Answer 1

5
\$\begingroup\$

I wouldn't say it is a bug, it is more of a limitation, and in a way it makes total sense. You want it to infer a dual port ram, the compiler wants to infer a dual port ram, however the process in the problem snippet does not properly describe the address input of the read port of the ram, because not all paths are covered, so it would have to infer a latch, while what you really want is a don't care. So you are basically making it hard for the compiler.

Realize that to infer the ram, it must also infer a few signals and their values, one of which is the address input. In the synchronous process, the value for this inferred signal is not defined for the case that ends up in PIXOUT <= x"111". So it would have to infer a latch and the warning would be an awkward "inferring latch on inferred address signal of inferred ram". It ends up being a bit too much, so it probably gives up, but then alternative solution does not fit the device. I'm not saying that this is the exact reason why it is giving up, but it should be clear that the compiler would have difficulties filling in the blanks for the inferred ram, given the way this process was coded.

All the solutions that work cover all the cases for the address signal, inferred or not. You could test declaring the signal and then coding it the same way so that it has to infer a latch, and it may even compile because now at least would have an explicitly declared signal it can refer to.

The coding styles for inferring ram blocks for Altera can be found in http://www.altera.com/literature/hb/qts/qts_qii51007.pdf#page13

This is one of the reasons why it is strongly suggested that if you wish to use existing hardware blocks, either instantiate them as such to avoid ambiguities, or follow the appropriate coding styles so that it can be easily and adequately inferred.

Also note that a simulator would not have to deal with this, because it would not have to infer a ram block per se and deal with the ambiguous don't care vs latch of this phantom signal, because in simulation it does not exist.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.