VIVADO通过mmi文件更新bit文件

VIVADO通过mmi文件更新bit文件

背景:有一个MCU的工程,这个工程有很多HDL文件,由于某些原因需要联合使用synplify和vivado,即先通过synplify综合,之后将edf网表文件交给vivado进行p&r。

MCU的启动ROM的内容初始化是这样做的:

  1. 首先使用vivado的BRAM IP生成符合条件的IP
  2. 在HDL文件中添加生成的IP文件中的的stub文件以通过synplify综合
  3. vivado添加edf文件后会将这个ROM当作一个black box,添加第一步生成的IP后即可进行impl、p&r

最开始时使用的方法是通过COE文件初始化BRAM,由于工程很大,如果每次ROM的内容有变动的话都需要重新进行第一步、第三步,而第三步每次都需要重新p&r相当耗费时间。因此开始考虑能不能通过直接修改比特流来修改ROM的初始化内容,在参考了以下资料后发现是可以实现的:

干货:Vivado 直接修改RAM初始化文件,避免重新综合、实现的方法

Vivado中用HDL定义BRAM存储器并用updatemem合成bit文件

Vivado通过mmi文件更新bit文件

UpdateMEM User Guide (UG1580)

Vivado BRAM资源使用

差异之处

我使用的vivado版本为2019.1,与《Vivado中用HDL定义BRAM存储器并用updatemem合成bit文件》这篇文章的差异之处在于我在RAMB36的cell properties中看不到这块bram的对应的行列范围。通过阅读UG1580和《Vivado BRAM资源使用》我发现需要想办法不通过cell properties人工确定每块bram的对应的行列范围。

具体实例

生成BRAM

我的ROM IP如图所示,需要注意的是它虽然名字叫2kx64但是实际上是4kx64,由于位宽为64位,为了方便起见,在algorithm中原语选择为256x72,这样我的ROM是8个并联,不用串联凑位宽。

image-20221004175430386

image-20221004175650593

确定每个RAMB36的行列范围

经过我的测试,updatemem只能操作RAMB32(这个好像也就是不启用partial check的RAMB36),因此需要确保使用的BRAM资源全部均为36K BRAMs。

使用到的8个RAMB36如下图所示

image-20221004194809897

可以发现每个init行对应4个64位数据,右边的数据为放在ROM中的启动程序

image-20221004195107660

检查发现每个RAMB36单元通过下图方式输出64位,奇偶校验位不参与(奇偶校验位参与的情况能否使用updatemem未进行验证)

image-20221004195426366

同时需要记录每个RAMB36的坐标以编写mmi文件

编写mmi文件

参考UG1580,经过计算每个RAMB36包含4096个字节,每个AddressSpace只有一个BitLane,编写mmi文件如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?xml version="1.0" encoding="UTF-8"?>
<MemInfo Version="1" Minor="0">

<Processor Endianness="Little" InstPath="dummy">
<AddressSpace Name="axi_rom_0" Begin="0" End="4095">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X1Y19">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

<AddressSpace Name="axi_rom_1" Begin="4096" End="8191">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X1Y21">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

<AddressSpace Name="axi_rom_2" Begin="8192" End="12287">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X1Y22">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

<AddressSpace Name="axi_rom_3" Begin="12288" End="16383">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X1Y20">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

<AddressSpace Name="axi_rom_4" Begin="16384" End="20479">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X1Y23">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

<AddressSpace Name="axi_rom_5" Begin="20480" End="24575">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X2Y21">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

<AddressSpace Name="axi_rom_6" Begin="24576" End="28671">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X1Y24">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

<AddressSpace Name="axi_rom_7" Begin="28672" End="32767">
<BusBlock>
<BitLane MemType="RAMB32" Placement="X2Y22">
<DataWidth MSB="63" LSB="0"/>
<AddressRange Begin="0" End="511"/>
<Parity ON="false" NumBits="0"/>
</BitLane>
</BusBlock>
</AddressSpace>

</Processor>



<Config>
<Option Name="Part" Val="xc7vx485tffg1761-2"/>
</Config>

</MemInfo>

准备mem文件

接下来就是mem文件了,注意每个RAMB36的对应一个开始地址指示符号,例如下图第一个RAMB36开始地址为0x0,第二个RAMB36开始地址为0x1000(即4096)。另外还需要注意数据的大小端,这里需要转换一下大小端。

image-20221004195905607

updatemem

以上准备工作完成之后便可以通过updatemem -debug -meminfo xxx.mmi -data xxx.mem -bit xxx.bit -proc dummy -out new.bit -force来生成新的bit文件了。如无意外,-debug选项会显示每个被重新初始化的RAMB36的数据。

image-20221004201112604

最后将新生成的bit烧录,验证是否成功。

image-20221004201424658