3
\$\begingroup\$

I am storing a 16k constant sine table of 14 bit signed vectors in a package.

I use this package in my module to read out the array in a clocked process

But I get this warning during synthesis and my synthesis is taking a long time -

The RAM will be implemented on LUTs either because you have described an asynchronous read or because of currently unsupported block RAM features. If you have described an asynchronous read, making it synchronous would allow you to take advantage of available block RAM resources, for optimized device usage and improved timings. Please refer to your documentation for coding guidelines."

code in package -

TYPE signed_array IS ARRAY (integer RANGE <>) OF signed (DATAWIDTH-1 DOWNTO 0); 

CONSTANT SINE_TABLE_SIZE : integer := QUARTER_LENGTH+1; -- 16384+1
----sine pi/2 = 1 <=> "0111111....1" MSB is 0 because of the signed representation

CONSTANT SINE_TABLE : signed_array(0 TO SINE_TABLE_SIZE-1):= (
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.0), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*9.5873799096e-05), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000191747597311), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000287621393763), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000383495187571), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000479368977855), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000575242763732), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000671116544322), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000766990318743), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000862864086114), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.000958737845553), DATAWIDTH) ,
                    to_signed(integer((2.0**(DATAWIDTH-1)-1.0)*0.00105461159618), DATAWIDTH) ,


process(clk)
    if rising_edge(clk) then
        ctd <= ctr + 1;
    end if;
end process;

cos <= SINE_TABLE(to_integer(unsigned(ctr)));

Any suggestions on how to write a vhdl code in infer a block RAM instead of LUTs?

The SINE TABLE is in a package, and the process is in the main module

\$\endgroup\$
4
  • \$\begingroup\$ Can you present some code? You can set a RAM_STYLE attribute to force BlockRAM usage. I assume XST misses a read clock because BlockRAM does not support synchronous read. \$\endgroup\$
    – Paebbels
    Apr 29, 2015 at 7:24
  • \$\begingroup\$ I will modify the question to add code.. \$\endgroup\$
    – Sai Gautam
    Apr 29, 2015 at 7:46
  • \$\begingroup\$ What you have in here is giant combinatorial block you need to synchronize your access by putting the read operation in the clocked process. \$\endgroup\$
    – FarhadA
    Apr 30, 2015 at 6:36
  • \$\begingroup\$ @FarhadA yes...have done it \$\endgroup\$
    – Sai Gautam
    May 4, 2015 at 6:43

2 Answers 2

3
\$\begingroup\$

Move the take lookup right next to the increment so the output is registered.

That is a gigantic lookup table, though. You may want to consider using a compressed lookup table to save on the block RAM. The trade-off is you may need a couple of multipliers.

Here is an example of a pipelined, compressed sine lookup table: https://github.com/alexforencich/verilog-dsp/blob/master/rtl/sine_dds_lut.v . By default, this one has an 18 bit phase input (2^18 = 262k equivalent entries) with a 16 bit output width. It consumes 3 block RAMs (two are 512x16 and one is 256x8) and two DSP slices.

\$\endgroup\$
7
  • 1
    \$\begingroup\$ u mean i should register cos assignment as well? \$\endgroup\$
    – Sai Gautam
    Apr 29, 2015 at 8:04
  • 2
    \$\begingroup\$ Yeah. Xilinx block RAMs want a register on the output data. If you don't provide one, this is the error you get. Yes, I have made this mistake many times before. \$\endgroup\$ Apr 29, 2015 at 8:07
  • \$\begingroup\$ i registered the output. It still doesnt work. \$\endgroup\$
    – Sai Gautam
    Apr 29, 2015 at 8:49
  • \$\begingroup\$ i want the output to be registered based on the 2 MSBs of the counter. So I have a case statement inside the process where the output is being registered. this is a clocked process \$\endgroup\$
    – Sai Gautam
    Apr 29, 2015 at 8:50
  • \$\begingroup\$ i however saw that if i register the output inside a simple clocked process, the tool infers a block ram \$\endgroup\$
    – Sai Gautam
    Apr 29, 2015 at 8:51
2
\$\begingroup\$

The memory read needs to be registered to be recognised as a block RAM:

process(clk)
    if rising_edge(clk) then
        ctr <= ctr + 1;
        cos <= SINE_TABLE(to_integer(unsigned(ctr)));
    end if;
end process;

I would also make ctr of an integer type - then you don't need to faff around with the conversions.

\$\endgroup\$
4
  • \$\begingroup\$ this works...but what i actually want is not a direct assignment of "cos" but an assignment based on the 2 MSBs of the ctr to decide which quadrant of the sine signal is used. So I gave a case structure inside this clocked process, but this causes somehow the synthesis tool again not to infer the block ram \$\endgroup\$
    – Sai Gautam
    May 4, 2015 at 6:46
  • \$\begingroup\$ Are you trying to read both the sin and cos in the same clock cycle? If so you need to be careful to use a VHDL construct which the synthesis tool recognises as a dual-read BRAM. Also, keep the memory-reading logic separate from the address calculating logic (in separate processes) if you are using XST - it sometimes struggles to identify RAM constructs when things are mixed together in the same process. \$\endgroup\$ May 4, 2015 at 19:07
  • \$\begingroup\$ Thank you...that makes sense why the tool was not inferring the block RAM \$\endgroup\$
    – Sai Gautam
    May 6, 2015 at 7:01
  • \$\begingroup\$ I had mixed a mux inside the same clocked process as the output registration of the block RAM \$\endgroup\$
    – Sai Gautam
    May 7, 2015 at 7:48

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.