Vhdl 为ModelSim/QuestaSim实例化LUT并使用.coe初始化 背景

Vhdl 为ModelSim/QuestaSim实例化LUT并使用.coe初始化 背景,vhdl,ram,xilinx,lookup-tables,vivado,Vhdl,Ram,Xilinx,Lookup Tables,Vivado,此LUT需要32的宽度和256的深度 所以我有一个由IP核心创建的LUT。现在我想自己实例化它,让它在sim卡中工作(这也帮助我自己学习所有参数)。我已经为FIFO做了很多次了,但以前从未创建过LUT,所以请检查我所做的看起来是否正确。我只想创建一个LUT的值,并能够读回它们。我用了一块RAM来做这个 我在两台不同的计算机上试用过: QuestaSim-64 10.2c_5 ModelSim SE-64 10.1b 问题 所以我可以编译代码。当我试图打开它时: vsim work.top 它

此LUT需要32的宽度和256的深度

所以我有一个由IP核心创建的LUT。现在我想自己实例化它,让它在sim卡中工作(这也帮助我自己学习所有参数)。我已经为FIFO做了很多次了,但以前从未创建过LUT,所以请检查我所做的看起来是否正确。我只想创建一个LUT的值,并能够读回它们。我用了一块RAM来做这个

我在两台不同的计算机上试用过:

QuestaSim-64 10.2c_5
ModelSim SE-64 10.1b
问题 所以我可以编译代码。当我试图打开它时:

vsim work.top
它打开IDE并冻结在以下位置:

# Loading unisim.rb36_internal_vhdl(rb36_internal_vhdl_v)#1
如果我删除:

INIT_FILE => "lut.coe",
然后就可以装了。所以我知道那条线会毁了它

LUT: 我有一个LUT,你觉得这对吗?是否有其他方法可以用.coe文件实例化LUT

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"   
    );
尝试将上述内容替换为18kb RAM,出现相同错误:

# Loading unisim.rb18_internal_vhdl(rb18_internal_vhdl_v)#2
LUT:


真的。扔掉IP核心和COE文件。((如果这是您的数据所在的唯一位置,请不要将其扔掉!)

当然,替换你自己的系数。为了获得额外的分数,可以使用脚本,甚至是C或VHDL程序来读取COE文件并编写上面的VHDL代码块

工作完成了

它是可合成、可模拟的,并且可移植到其他FPGA


(在我看来,可移植性问题是大多数供应商的IP核的真正原因。但我将对复杂的核心(如PCIe或DDR内存接口)例外。)

严肃地说。扔掉IP核和COE文件。((如果你的数据只放在那个地方,不要真的扔掉它!)

当然,替换你自己的系数。为了获得额外的分数,可以使用脚本,甚至是C或VHDL程序来读取COE文件并编写上面的VHDL代码块

工作完成了

它是可合成、可模拟的,并且可移植到其他FPGA


(在我看来,可移植性问题是大多数供应商IP核的真正原因。但我将为复杂的核心(如PCIe或DDR内存接口)提供一个例外。)

Xilinx工具有一种简单快捷的方法,可以直接在VHDL中读取*.mem或*.hex文件。文件内容可以在模拟和合成中用作块RAM初始化

Xilinx提供了第124页中的编码示例:

type RamType is array(0 to 7) of bit_vector(31 downto 0);

impure function InitRamFromFile (RamFileName : in string) return RamType is
  FILE RamFile : text is in RamFileName;
  variable RamFileLine : line;
  variable RAM : RamType;
begin
  for I in RamType'range loop
    readline (RamFile, RamFileLine);
    read (RamFileLine, RAM(I));
  end loop;
  return RAM;
end function;

signal RAM : RamType := InitRamFromFile("rams_20c.data");
该示例适用于RAM,但当您移除写入端口并用常量替换信号时,它可以很容易地转换为ROM(LUT)


例如,可以在中找到更高级的实现。此实现还可与Altera的sltsyncrams一起使用,后者可以读取*.mif文件。

Xilinx工具有一种简单快捷的方法,可以直接在VHDL中读取*.mem或*.hex文件。文件内容可以在模拟和合成中用作块RAM初始化

Xilinx提供了第124页中的编码示例:

type RamType is array(0 to 7) of bit_vector(31 downto 0);

impure function InitRamFromFile (RamFileName : in string) return RamType is
  FILE RamFile : text is in RamFileName;
  variable RamFileLine : line;
  variable RAM : RamType;
begin
  for I in RamType'range loop
    readline (RamFile, RamFileLine);
    read (RamFileLine, RAM(I));
  end loop;
  return RAM;
end function;

signal RAM : RamType := InitRamFromFile("rams_20c.data");
该示例适用于RAM,但当您移除写入端口并用常量替换信号时,它可以很容易地转换为ROM(LUT)



例如,可以在中找到一个更高级的实现。该实现还可以与Altera的sltsyncrams一起使用,csn读取*.mif文件。

这实际上是我扔掉了IP核,但我想我仍然可以回收.coe文件。谢谢,明天早上我的大脑不那么灵活的时候我会看看这个。我想我可以用上面的method-工具仍然会生成一个RAMB块,这是正常的。如果它出于某种原因拒绝,(a)检查您的管道-您需要在其地址或输出上注册一个寄存器(BRAM是同步的),并且(b)有一个属性(类似于Lut的
属性RAMSTYLE是“BRAM”;
)在文档中,这应该是强制的。我不记得该属性是必需的,但很高兴知道。这实际上是我扔掉了IP核心,但我认为我仍然可以回收.coe文件。谢谢,明天早上我的大脑不太灵活时,我会看一看这个。我猜使用上述方法-工具仍然会生成一个RAMB blockIt通常会这样做。如果它出于某种原因拒绝,(a)检查您的管道-您需要在其地址或输出上注册一个寄存器(BRAM是同步的),并且(b)有一个属性(类似于
属性,Lut的RAMSTYLE是“BRAM”;
)在文档中,这应该是强制的。我不记得该属性是必需的,但很高兴知道。设备特定原语的使用非常严格。如果可能,我建议使用通用描述。此解决方案也可以由模拟器使用,而无需供应商特定的原语支持。设备特定原语的使用imitives是非常严格的。如果可能的话,我建议使用通用描述。这个解决方案也可以由模拟器使用,而不需要特定于供应商的原语支持。谢谢,这是一个非常好的替代答案。虽然我写了一个简短的脚本,生成上面的LUT,我将首先试用。如果可行,我将稍后试用因为它看起来更通用一些=我忘了提到*.mem文件格式是什么样子的:n行代表n个内存字,因此每个内存字1行;每个内存字都用十六进制ASCII字符编码。使用这个答案的一个好方法是调整函数直接读取.coe文件,跳过不需要的行,然后提取coeffic来自有用行的IENT。@fiz可以随意扩展ocrom以读取新的文件格式:)干杯,因为.coe文件目前已修复,我只是从中提取了一些值,但如果我需要,我将尝试在未来的设计中使用它=)谢谢,这是一个非常好的替代答案。虽然我写了一个简短的脚本来生成上面的LUT,但我将首先尝试。如果可以的话,我稍后会尝试一下,因为它看起来更通用一些=我忘了提到*.mem文件格式的样子:n行代表n个内存字,因此每个内存字1行;每个内存字都用十六进制ASCII字符编码。使用此答案的一个好方法是调整函数以直接读取.coe文件
type RamType is array(0 to 7) of bit_vector(31 downto 0);

impure function InitRamFromFile (RamFileName : in string) return RamType is
  FILE RamFile : text is in RamFileName;
  variable RamFileLine : line;
  variable RAM : RamType;
begin
  for I in RamType'range loop
    readline (RamFile, RamFileLine);
    read (RamFileLine, RAM(I));
  end loop;
  return RAM;
end function;

signal RAM : RamType := InitRamFromFile("rams_20c.data");