Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

mapping a small table to a LUT instead of memory registers

I would like to map a table to a LUT simialr to the attached example in vhdl, but Quartus synthesis does not map the table in the attached verilog to a LUT, instead it uses memory registers.

Merely synthesizing the two equivalent modules in VHDL and verilog, shows the following synthesis reports.

Apparently, there is lack of initialization option in verilog compared to vhdl that is causing this mapping to registers in verilog compared to LUTs in VHDL.

What else can I do to map the table in verilog to LUT, other than the initial block, that is not working as desired.

Thanks in advance,

Fasahat

--------------------------------------- VHDL Synthesis -------------------------------

Analysis & Synthesis Status Successful - Fri May 14 15:46:56 2010

Quartus II Version 9.0 Build 235 06/17/2009 SP 2 SJ Full Version

Revision Name s_box

Top-level Entity Name sbox

Family Stratix II

logic utilization n/a

combinational aluts 40

dedicated logic registers 8

Total registers 8

Total pins 18

Total virtual pins 0

total block memory bits 0

DSP block 9-bit elements 0

Total PLLs 0

Total DLLs 0

------------------------------ VERILOG Synthesis --------------------------------------------------

Analysis & Synthesis Status Successful - Fri May 14 15:48:33 2010

Quartus II Version 9.0 Build 235 06/17/2009 SP 2 SJ Full Version

Revision Name s_box

Top-level Entity Name s_box_rom2

Family Stratix II

Logic utilization N/A

combinational aluts 0

dedicated logic registers 0

Total registers 0

Total pins 17

Total virtual pins 0

total block memory bits 2,048

DSP block 9-bit elements 0

Total PLLs 0

Total DLLs 0

10 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    i ran s_box_rom2.v in Quartus II 9.1sp2 targeting a CIII and the RAM was mapped to an M9K. the RAM inferring must have been improved.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    from the Quartus II Handbook, version 9.0 page 454:

    --- Quote Start ---

    Example 9–63. Verilog-1995 Code: Applying a syn_ramstyle Attribute to a Variable Declaration

    reg [0:7] my_ram[0:63] /* synthesis syn_ramstyle = "logic" */;

    Example 9–64. Verilog-2001 Code: Applying a romstyle Attribute to a Variable Declaration

    (* romstyle = "logic" *) reg [0:7] my_rom[0:63];

    Example 9–65. VHDL Code: Applying a ramstyle Attribute to a Signal Declaration

    type memory_t is array (0 to 63) of std_logic_vector (0 to 7);

    signal my_ram : memory_t;

    attribute ramstyle : string;

    attribute ramstyle of my_ram : signal is "logic";

    --- Quote End ---

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Also, from page 458 of 9.0 Quartus II Handbook :

    --- Quote Start ---

    In VHDL, you can also initialize the contents of an inferred memory by specifying a

    default value for the corresponding signal. In Verilog HDL, you can use an initial

    block to specify the memory contents. Quartus II integrated synthesis automatically

    converts the default value into a .mif file for the inferred RAM.

    --- Quote End ---

    Pretty sure both languages do the exact same thing, just for some reason it implemented them different. Most likely have the same function as well. If you want to make the vhdl implemented in memory you can make the ram_style attribute one of the following values, depending on device :

    "M512", "M4K", "M-RAM", "MLAB", "M9K", and "M144K"
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Dear fasahat,

    the Verilog and VHDL modules you provided are not identical.

    The VHDL module has an asynchronous 'rst' signal that causes it to output zero. This behaviour can't be implemented just with a M4K block, it would at the very least require aditional logic.

    The correct way to infer a synchronous ROM in VHDL would be

    process (clk)

    if clk'event and clk = '1' then

    byteout <= sbox_ram(conv_integer(bytein));

    end if;

    end process;

    Another important aspect is the table contents: at least in the VHDL case, the 2K bit table contents can be reduced to just 48 ALUTs (and 8 registers).

    So, what the way Quartus implemented that is problably the most efficient way to do it.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    rbugalho-

    You are correct, they are different. Somehow failed to notice that. However, all memory blocks (M512, M4K, and MRAM) of the stratix II support asynchronous clear of the output registers. That is actually the only thing they support async clear on. So, both the vhdl and verilog code can be implemented in either ram or logic elements, just a matter of how you want to do it.

    From the stratix II reference:

    --- Quote Start ---

    When applied to output registers, the asynchronous

    clear signal clears the output registers and the effects are seen

    immediately.

    --- Quote End ---

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You are right, I forgot to use reset in verilog.

    However, using a reset signal in verilog code and the recommended case statement (full case), does not map the memory to LUT as was the case with VHDL.

    Interestingly, if I remove the reset initialization of memory in VHDL code, as suggested by memory templates ( Chapter 6: Recommended HDL Coding Styles

    Inferring Memory Functions from HDL Code Example 6-23) , the synthesizer maps the table to dedicated registers and not to ALUT(s) anymore.

    What I am trying to get at is :

    If I have many small tables in adeisgn like the one in vhdl file, I see timing closure is much better (by about 30 MHz) compared to same implementation in verilog where the synthesizer infers M4K.

    I did not find anything in Chapter 6: Recommended HDL Coding Styles

    Inferring Memory Functions from HDL Code to infer a small memory in verilog to ALUT(s).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    You're trying both Verilog and VHDL and trying multiple coding styles. Please be carefull not to take away conclusions about Verilog vs VHDL when your code and coding style aren't actually equivalent.

    There are limitations to what cases can be mapped to dedicated logic blocks, such as M4K memory blocks.

    Some are fundamental limitations imposed by the dedicated logic, won't support some features.

    If you code a table whose content's can be reset, it won't ever be mapped to a M4K because M4K blocks don't support reseting it's contents.

    Some are just limitations of the design software.

    For example, IIRC, Quartus 9.0 is just "too dumb" to infer memory blocks from a "case based" coding style, either in Verilog or VHDL. You'll need 9.1 to do that.

    From my experience and from the examples, Quartus also won't infer memory blocks if you have a reset signal, like in the VHDL example you posted. Again, from what kbs972 wrote, this looks more like a software limitation than a hardware limitation.

    But if Quartus is able to infer RAM/ROM primitive from the HDL it will, in general, map it to a dedicated memory block, unless it's a very small RAM/ROM or your design is starved for resources.

    If you are not happy with what Quartus is doing, you can either fiddle with the synthesis settings or use attrbutes as kbs972 suggested.

    I find it a bit strange that you're getting better timming with ALUTs than with M4K blocks.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    ok, here is the stats

    w/reset and case statement

    verilog altera 9.0 sp2 M4k used 1

    vhdl altera 9.0 sp2 M4k used 0 alm used 40

    verilog altera 9.1 sp1 M4k used 1

    case statement (NO reset)

    verilog altera 9.0 sp2 M4k used 1

    vhdl altera 9.0 sp2 M4k used 0 alm used 40

    verilog altera 9.1 sp1 M4k used 1

    vhdl altera 9.1 sp1 M4k used 1 alm used 0

    So apparently, 9.1 is smarter in that vhdl is also mapped to M4K (w/reset or w/o reset)

    BUT there is a flag called

    AUTO ROM Replacement (default on)

    Allows the Compiler to find logic that can be replaced with the altsyncram or the lpm_rom megafunction. Turning on this option may change the power-up state of the design.

    Select OFF and it will map vhdl or verilog memory to to ALUT(s) instead.

    In 9.0, this flag is default on, so it mapped verilog to M4k as expected, but not the same for vhdl (now this is corrected in 9.1).

    Thanks for sharing,

    Fasahat
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Using the directive

    /* synthesis romstyle = "logic" */

    as in example below

    define MRESET

    module s_box_rom (

    input clk,

    `ifdef MRESET

    input rst,

    `endif

    input [7:0] address,

    output reg [7:0] data_out

    //);

    ) /* synthesis romstyle = "logic" */;

    `ifdef MRESET

    always @ (posedge clk or posedge rst)

    if (rst)

    data_out <= 0;

    else

    `else

    always @ (posedge clk)

    `endif

    begin

    case (address)

    // 8'b00000000: data_out2 <= 6'b101111;

    0 : data_out <= 8'h63;

    1 : data_out <= 8'h7C;

    2 : data_out <= 8'h77;

    ...

    ...

    244 : data_out <= 8'hBF;

    245 : data_out <= 8'hE6;

    246 : data_out <= 8'h42;

    247 : data_out <= 8'h68;

    248 : data_out <= 8'h41;

    249 : data_out <= 8'h99;

    250 : data_out <= 8'h2D;

    251 : data_out <= 8'h0F;

    252 : data_out <= 8'hB0;

    253 : data_out <= 8'h54;

    254 : data_out <= 8'hBB;

    255 : data_out <= 8'h16;

    endcase

    end

    endmodule

    maps it to ALUT(s) , doing away the need for global switch settings and more control per module.