Search code examples
vhdlramxilinxlookup-tablesvivado

Instantiating a LUT and Initialising with a .coe for ModelSim/QuestaSim


The Background

This LUT needs a width of 32 and a depth of 256.

So I have a LUT which was created by an IP core. Now I want to instantiate it myself to get it working in the sim (this also helps me learn all of the parameters myself). I've done this many times for FIFOs but never created a LUT before so please check what I've done looks correct. I just want to create a LUT of values and to be able to read them back. I used a block of RAM for this.

I've tried on two different computers with:

QuestaSim-64 10.2c_5
ModelSim SE-64 10.1b

The Problem

So I can compile the code. When I try to open it:

vsim work.top

It opens the IDE and freezes on:

# Loading unisim.rb36_internal_vhdl(rb36_internal_vhdl_v)#1

If I remove:

INIT_FILE => "lut.coe",

Then it loads up fine. So I know that line crashes it.

The LUT:

So I have a LUT, does this look correct to you? Is there any other ways to instantiate a LUT with a .coe file?

lut : RAMB36E1 
generic map(
    INIT_FILE => "lut.coe",
    READ_WIDTH_A => 36
    )
port map
    (
    addrardaddr => addr_lut,
    addrbwraddr => X"0000",
    cascadeina => '0',
    cascadeinb => '0',
    clkardclk => clk_i,
    clkbwrclk => clk_i,
    diadi => X"00000000",
    dibdi => X"00000000",
    dipadip => X"0",
    dipbdip => X"0",
    doado => data_lut,
    enarden => '1',
    enbwren => '0',
    injectdbiterr => '0',
    injectsbiterr => '0' ,
    regceb => '0',
    regcearegce => '1',
    rstramarstram => rst_i,
    rstramb => rst_i,
    rstregarstreg => rst_i ,
    rstregb => rst_i,
    wea => X"0",
    webwe =>  X"00"   
    );

Tried swapping the above out for 18kb RAM, same error:

# Loading unisim.rb18_internal_vhdl(rb18_internal_vhdl_v)#2

LUT:

lut : RAMB18E1 -- Simple Duel Port mode, 512 deep
generic map(
    INIT_FILE => "lut.coe",
    RAM_MODE => "SDP"
    )
port map
    (
    addrardaddr => addr_lut,
    addrbwraddr => "00000000000000",
    clkardclk => clk_i,
    clkbwrclk => clk_i,
    diadi => X"0000",
    dibdi => X"0000",
    dipadip => "00",
    dipbdip => "00",
    doado => data_lut_b,
    dobdo => data_lut_a,
    enarden => '1',
    enbwren => '0',
    regceb => '0',
    regcearegce => '1',
    rstramarstram => rst_i,
    rstramb => rst_i,
    rstregarstreg => rst_i ,
    rstregb => rst_i,
    wea => "00",
    webwe =>  X"0"   
    );

Solution

  • Seriously. Throw away the IP core and the COE file. ((If that's the only place your data is, don't actually throw it away!)

    Subtype Data_Word is std_logic_vector(31 downto 0);
    Type Lut_Type is Array(0 to 255) of Data_Word;
    Constant Lut : Lut_Type := (
     0 => X"00000001",
     1 => X"00000002",
    ...
    17 => X"DEADBEEF",
    others => (others => 'X') );
    

    Substitute your own coefficient of course. For bonus points, use a script or even a C or VHDL program to read the COE file and write the above chunk of VHDL.

    Job done.

    It's synthesisable, simulatable, and portable to other FPGAs.

    (IMO the portability issue is the real reason for most vendors' IP cores. But I'll make an exception for complex cores like PCIe or DDR memory interfaces.)