实例化 LUT 并使用 .coe 初始化 ModelSim/QuestaSim
Instantiating a LUT and Initialising with a .coe for ModelSim/QuestaSim
背景
这个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,这对你来说正确吗?还有其他方法可以使用 .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 : 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"
);
说真的。扔掉IP核和COE文件。 ((如果那是你的数据唯一的地方,不要真的把它扔掉!)
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') );
当然是代入你自己的系数。为了获得加分,请使用脚本甚至 C 或 VHDL 程序读取 COE 文件并编写上述 VHDL 块。
任务完成。
它是可综合的、可模拟的,并且可移植到其他 FPGA。
(IMO,可移植性问题是大多数供应商的 IP 内核的 真正 原因。但我会为 PCIe 或 DDR 内存接口等复杂内核做个例外。)
Xilinx 工具有一种简单快捷的方法可以直接在 VHDL 中读取 *.mem 或 *.hex 文件。文件内容可作为BlockRAM初始化用于仿真和综合。
Xilinx 在第 124 页的 UG901 中提供了一个编码示例:
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)。
例如可以在 PoC.mem.ocrom.sp 中找到更高级的实现。此实现也适用于 Altera 的 sltsyncrams,它 csn 读取 *.mif 文件。
背景
这个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,这对你来说正确吗?还有其他方法可以使用 .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 : 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"
);
说真的。扔掉IP核和COE文件。 ((如果那是你的数据唯一的地方,不要真的把它扔掉!)
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') );
当然是代入你自己的系数。为了获得加分,请使用脚本甚至 C 或 VHDL 程序读取 COE 文件并编写上述 VHDL 块。
任务完成。
它是可综合的、可模拟的,并且可移植到其他 FPGA。
(IMO,可移植性问题是大多数供应商的 IP 内核的 真正 原因。但我会为 PCIe 或 DDR 内存接口等复杂内核做个例外。)
Xilinx 工具有一种简单快捷的方法可以直接在 VHDL 中读取 *.mem 或 *.hex 文件。文件内容可作为BlockRAM初始化用于仿真和综合。
Xilinx 在第 124 页的 UG901 中提供了一个编码示例:
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)。
例如可以在 PoC.mem.ocrom.sp 中找到更高级的实现。此实现也适用于 Altera 的 sltsyncrams,它 csn 读取 *.mif 文件。