
声明本文仅供参考学习交流内容为网上整理获得禁止商用。特别感谢我的师兄朱博在Memory Compiler使用过程中给予的指导与帮助。1. 为什么需要Memory CompilerSRAM、ROM 等存储器是数字IC设计中重要的组成部分广泛应用于片上数据存储、缓存以及查找表等场景。本文将介绍如何使用Memory Compiler生成所需的存储器IP并结合RTL调用与VCS功能仿真完整展示从存储器生成到仿真验证的基本流程。在数字IC设计中经常需要存储大量的中间数据。如果存储规模很小我们可以直接使用寄存器实现但随着存储容量不断增加继续使用寄存器就会带来非常高的硬件开销。以最常见的SRAM为例一个经典的6T SRAM单元只需要6个MOS管即可存储1bit数据。而在标准单元设计中一个能够存储1 bit数据的D触发器通常需要20个甚至更多晶体管才能实现。虽然两者在功能和使用方式上并不完全等价但从存储密度的角度来看SRAM的优势十分明显。Memory Compiler是用于生成SRAM、ROM等存储器IP的工具。设计人员可以根据实际需求配置存储深度、数据位宽、端口类型等参数并生成对应的存储器宏单元及其仿真、综合、时序分析和后端实现所需的相关文件从而方便地将存储器集成到ASIC设计中。2. TSMC 28nm工艺库——Memory Compiler (MC2)介绍本文使用的Memory Compiler基于台积电28nm工艺平台配套的存储器编译环境完整的TSMC 28nm工艺库所包含的子目录如下工艺库可在网上获取。各个目录下文件功能描述如下EFUSE存放电熔丝存储器宏用于永久保存芯片配置、修复信息、校准值或密钥。General_AppNotes_PR_Constraint_File存放IO、ESD、eFuse及特殊版图设计的说明和约束文档。IO存放芯片输入输出、焊盘和ESD保护单元用于连接芯片内部电路与外部引脚。logic存放数字标准单元库用于逻辑综合、时序分析和布局布线。Memory存放SRAM、ROM、Register File等存储器的生成工具、配置文件和相关模型。PDK存放工艺器件、仿真模型及DRC、LVS、PEX规则是电路设计和版图验证的基础。TF存放不同金属层结构和EDA工具所需的技术文件用于布局布线、寄生参数提取和最终签核。其中Memory目录主要存放存储器IP的生成与集成资源包括Memory Compiler工具、SRAM、ROM和Register File等存储器的配置文件以及相关的时序、仿真和物理实现模型。对于存储器IP的生成而言Memory目录下的内容已经完全够用了具体内容如下。先看懂文件夹公共部分的命名规则tsnTSMC存储器IP的产品命名前缀。2828nm工艺。hpcpHigh Performance Compact Plus即N28HPC工艺。目录1下包含了三个子目录tsmc_n28hpcpmc_20120200_110aMemory Compiler公共执行环境其中mc2-eu是核心执行程序由各存储器的.pl脚本调用用于加载对应的.mco编译器对象并根据config.txt中的深度、位宽等参数生成指定规格的存储器IP。目录中还包含Linux等版本程序、安装脚本、许可证工具及使用文档。temn28hpcphssrammacros_170aN28HPC高速固定SRAM宏库。“固定”表示这些存储器规格已由厂商预先生成用户只能从现有宏中选择不能通过Memory Compiler自由配置容量和位宽。该目录包含Databook、9984个.ds数据表以及GDS、NLDM、LEF、SPICE、Verilog和MDT等设计视图。tsn28hpcpl2spsrammacros_180a面向L2 Cache的固定单端口SRAM宏库同样由厂商预先生成一组确定规格的存储器设计时可直接选用无需运行Memory Compiler。该目录包含256个.ds数据表及相应的物理、时序和仿真视图。其他目录分别存放不同类型存储器的MC2工具包用于配置并生成相应规格的Register File、SRAM或ROM存储器IP。内部主要包含了存储器的.pl脚本、.mco编译器对象、config.txt参数配置等文件。文件夹的命名含义如下tsn28hpcp1prf_20120200_130a1prf表示One-Port Register File即单端口寄存器文件编译器。tsn28hpcp2prf_20120200_130a2prf表示Two-Port Register File即双端口寄存器文件编译器。tsn28hpcpd127spsram_20120200_180ad127spsram表示D127系列Single-Port SRAM Compiler即单端口SRAM编译器。tsn28hpcpdpsram_20120200_130adpsram表示Dual-Port SRAM Compiler即双端口SRAM编译器。tsn28hpcprom_20120200_130arom表示ROM Compiler即ROM编译器。tsn28hpcpuhddpsram_20120200_170auhd表示Ultra High Densitydpsram表示Dual-Port SRAM因此这是超高密度双端口SRAM Compiler。tsn28hpcpuhdspsram_20120200_170auhd表示Ultra High Densityspsram表示Single-Port SRAM因此这是超高密度单端口SRAM Compiler。整个存储IP的生成流程可以概括为先选对应的MC2工具包并在config.txt中填写存储器的深度、位宽等功能选项随后运行对应的.pl脚本该脚本会读取并检查配置参数加载该存储器类型对应的.mco编译器对象然后调用1/tsmc_n28hpcpmc_20120200_110a/.../MC2_2012.02.00.d/bin/Linux-64/mc2-eu核心程序完成编译。最终MC2会生成指定规格的存储器IP并输出用于芯片设计的Databook、GDS、LEF、SPICE、NLDM和Verilog等文件。注意执行mc2-eu来生成存储器IP需要许可证文件license.dat。解决方法₥㏄ 2012 02 00 d - EDA资源使用讨论 - EETOP 创芯网论坛 (原名电子顶级开发网) - Powered by Discuz! 替换/bin/Linux-64/mc2-eu和/aux/flexlm/amd64_re3/interrad两个文件并添加可执行权限。经过本人测试该方法有效。3. 存储IP生成及功能仿真规范化工程目录让整个工程的结构更加清晰。在目录mem下来生成所需的存储单元假设项目中需要一个双口RAM和一个ROM所以在mem下再创建两个目录dpsram512_16bit和rom512_8bit。3.1 DPSRAM案例3.1.1 SRAM IP的生成先确定存储器类型为双口SRAM可以选择目录tsn28hpcpdpsram_20120200_130a下的工具包。将目录tsn28hpcpdpsram_20120200_130a/AN61001_20180125/TSMCHOME/sram/Compiler/tsn28hpcpdpsram_20120200_130a/下的4个文件复制到目录/mem/dpsram512_16bit/下。在目录/mem/dpsram512_16bit/下给一些文件添加权限方便后续操作。chmodw config.txtchmodx tsn28hpcpdpsram_130a.pl先看一下原始的config.txt文件中的内容为4096x36m8m 4096 x 36 m 8 m │ │ │ │ │ └── 分段模式Medium │ │ │ │ └───── MUX数值8 │ │ │ └──────── MUX字段的标识符 │ │ └─────────── 数据位宽36 bit │ └─────────────── 深度与位宽的分隔符 └──────────────────── 存储深度4096个地址表示生成一个深度为4096、位宽为36bit、采用MUX 8和Medium分段模式的双端口SRAM。但是这些配置信息并不能随意填写而是要遵照对应工具包的Databook中的要求。Databook的目录为tsn28hpcpdpsram_20120200_130a/AN61001_20180125/TSMCHOME/sram/Documentation/documents/tsn28hpcpdpsram_20120200_130a/DB_TSN28HPCPDPSRAM_20120200_130A.pdf。下表为Databook中规定的双口SRAM配置相关的约束条件。分段模式只能选择F或M其中F偏向速度M更侧重面积与容量。MUX只能选择4、8或16它决定阵列的列复用方式和长宽比例。Word Depth不能在范围内随意填写。MUX为4、8、16时深度必须分别从32、64、128开始并按照16、32、64的步长递增最大深度还会随分段模式变化。Word Width则必须为整数。MUX为4、8、16时分别支持472、436和418bit。计算WL WordDepth / MUX避免取到Databook注明的特殊禁用值。对于F分段WL不能为68132和196而对于M分段WL则不能为132260和388。如果所需存储空间超过单个存储器IP的容量则可使用多个合法规格的存储器IP进行扩展组合并行连接扩展位宽分Bank扩展深度。这里我们需要生成512x16bit的双口SRAM可在config.txt文件中写入如下内容512x16m4f在目录/mem/dpsram512_16bit/下打开终端命令行输入如下指令exportPATH/data/SunYuhao_TSMC28/TSMC28/Memory/1/tsmc_n28hpcpmc_20120200_110a/AN61001_20180125/TSMCHOME/sram/Compiler/tsmc_n28hpcpmc_20120200_110a/MC2_2012.02.00.d/bin/Linux-64:$PATHwhichmc2-eu该命令将MC2的bin目录加入当前Shell的命令搜索路径使用户可以直接执行mc2-eu末尾的$PATH用于保留系统原有的命令搜索路径。其中export不仅完成PATH变量的设置还会将更新后的路径传递给当前Shell启动的.pl脚本及其他子进程保证它们也能找到MC2程序。值得注意的是该设置只在当前终端会话中有效关闭终端后会失效失效后需要重新设置。命令which mc2-eu用来检测上一条指令是否配置成功配置成功后会显示mc2-eu的绝对路径。输入如下指令运行tsn28hpcpdpsram_130a.pl脚本生成双口SRAM IP相关的文件./tsn28hpcpdpsram_130a.pl运行.pl脚本后首先会生成tsdn28hpcpa512x16m4fwbaso.cfg其中记录SRAM的深度、位宽、MUX、分段模式及BIST等功能选项随后MC2根据该文件生成lastrun.cfg补充实际输出路径和各PVT条件是本次编译的最终配置记录。tsdn28hpcpa512x16m4fwbaso_130a目录中是生成的双口SRAM IP的相关文件。DATASHEET包含16种PVT条件下的数据表用于查看SRAM的面积、时序、功耗及工作条件。DFT包含ATPG和MBIST相关测试模型用于生成测试向量和集成存储器自测试功能。GDSII包含SRAM完整的物理版图数据用于DRC、LVS等物理验证以及最终流片。LEF包含SRAM的尺寸、引脚位置和布线阻挡信息供布局布线工具进行宏单元集成。LOG记录MC2的配置参数、文件生成过程以及错误和警告信息可用于检查运行结果。NLDM包含16种PVT条件下的.lib时序模型用于逻辑综合、静态时序分析和功耗评估。SPICE包含SRAM的晶体管级网表和层次信息用于电路仿真以及版图与原理图一致性验证。VERILOG包含普通行为模型和电源相关模型用于SRAM的功能仿真、时序检查及低功耗验证。其中VERILOG目录下的文件可以用来进行功能仿真一共包含两类模型每类又按照不同的PVT工艺角划分普通Verilog模型文件名以.v结尾接口中不包含VDD和VSS电源引脚适合常规RTL功能仿真和时序仿真。带电源引脚的Verilog模型文件名以_pwr.v结尾功能与普通模型基本一致但增加了VDD和VSS端口主要用于电源感知或低功耗仿真。每类模型均提供16种PVT条件其中ffg、tt和ssg分别表示快、典型和慢工艺角文件名中的0p9v等字段表示工作电压25c等字段表示温度。不同文件描述的是同一个SRAM只是延迟参数对应的工作条件不同因此一次仿真只需选择一个模型即可。对于一般的功能验证选择典型工艺、0.9V、25℃对应的普通模型来仿真接口文件名如下tsdn28hpcpa512x16m4fwbaso_130a_tt0p9v25c.v3.1.2 SRAM IP的功能仿真文件tsdn28hpcpa512x16m4fwbaso_130a_tt0p9v25c.v内部包含了两个模块TSDN28HPCPA512X16M4FWBASOSRAM的顶层仿真模块定义外部接口并模拟读写控制、BIST、休眠、关断、端口冲突以及时序检查等行为。TSDN28HPCPA512X16M4FWBASO_Int_Array内部存储阵列模块使用Verilog数组保存数据实现双端口读写、按位写入以及存储内容初始化等基本功能。其中顶层仿真模块会例化内部存储阵列模块因此只需要关注顶层仿真模块即可。为了便于在设计中使用通常会在该模型外部增加一层封装将复杂的原厂接口整理为常用的时钟、地址、写使能、写数据和读数据接口并将BIST、休眠、关断等暂不使用的控制信号设置为固定值。后续设计和Testbench只需连接封装模块无需直接处理SRAM原始接口。下面进入到功能仿真阶段大家可以参考我之前的博客《Synopsys 功能仿真入门Makefile、VCS 与 Verdi 协同使用及 IP 核调用》有比较详细的解释和步骤。下面的仿真流程就进行简化。切换到rtl目录将文件tsdn28hpcpa512x16m4fwbaso_130a_tt0p9v25c.v复制到rtl中并创建封装模块dpsram512_16bit内容如下timescale 1ns/1ps module dpsram512_16bit ( input wire clka, input wire ena, input wire wea, input wire [8:0] addra, input wire [15:0] dina, output wire [15:0] douta, input wire clkb, input wire enb, input wire web, input wire [8:0] addrb, input wire [15:0] dinb, output wire [15:0] doutb ); localparam real INPUT_DELAY 0.1;// Simulation-only input delay: 0.1 ns wire ena_d; wire wea_d; wire [8:0] addra_d; wire [15:0] dina_d; wire enb_d; wire web_d; wire [8:0] addrb_d; wire [15:0] dinb_d; assign #(INPUT_DELAY) ena_d ena; assign #(INPUT_DELAY) wea_d wea; assign #(INPUT_DELAY) addra_d addra; assign #(INPUT_DELAY) dina_d dina; assign #(INPUT_DELAY) enb_d enb; assign #(INPUT_DELAY) web_d web; assign #(INPUT_DELAY) addrb_d addrb; assign #(INPUT_DELAY) dinb_d dinb; TSDN28HPCPA512X16M4FWBASO u_sram ( // Low-power and test-option pins: normal operating mode. .SLP (1b0), .SD (1b0), .WTSEL (2b01), .RTSEL (2b01), .VG (1b1), .VS (1b1), // Port A. The original macro control signals are active low. .AA (addra_d), .DA (dina_d), .BWEBA ({16{~wea_d}}), .WEBA (~wea_d), .CEBA (~ena_d), .CLKA (clka), // Port B. The original macro control signals are active low. .AB (addrb_d), .DB (dinb_d), .BWEBB ({16{~web_d}}), .WEBB (~web_d), .CEBB (~enb_d), .CLKB (clkb), // BIST interface is disabled in normal operation. .AWT (1b0), .AMA (9b0), .DMA (16b0), .BWEBMA (16hffff), .WEBMA (1b1), .CEBMA (1b1), .AMB (9b0), .DMB (16b0), .BWEBMB (16hffff), .WEBMB (1b1), .CEBMB (1b1), .BIST (1b0), .CLKM (1b0), .QA (douta), .QB (doutb) ); endmodule在功能仿真中不关注低功耗和调节信号和BIST测试接口故这里将这些信号固定为常数值。对这些信号感兴趣的朋友可以直接去问问AI。下面稍微介绍一下要使用的读写端口信号位宽方向作用CLKA、CLKB1输入A、B端口的独立时钟读写操作在对应时钟的上升沿执行。CEBA、CEBB1输入端口使能低有效为0时允许端口工作为1时关闭对应端口并保持输出。WEBA、WEBB1输入写使能低有效端口使能时为0执行写操作为1执行读操作。AA、AB9输入A、B端口的访问地址可选择0511共512个存储位置。DA、DB16输入A、B端口的写入数据在写周期的时钟上升沿写入指定地址。QA、QB16输出A、B端口的读取数据读周期中地址在时钟上升沿被采样随后经过SRAM的时钟到输出延迟更新。端口未使能时通常保持上一次读取结果发生同址读写冲突时可能输出未知值X。BWEBA、BWEBB16输入按位写使能低有效每一位分别控制对应的数据位为0时允许写入为1时保持该位原有数据。信号BWEBA和BWEBB用于分别控制写入数据DA和DB中各数据位的写入权限。为了简化封装将其所有位统一连接至写使能逻辑因此每次写操作都会完整写入16位数据不支持按位写入或部分更新。另外端口使能和写使能信号都修改成高电平有效。将除时钟外的信号延迟0.1ns后再送入TSDN28HPCPA512X16M4FWBASO模块。原因是该仿真模型不支持控制、地址或数据信号与时钟上升沿在同一时刻发生变化否则可能产生竞争、时序告警或未知值X导致仿真无法正常进行。加入少量延迟可以错开输入变化与时钟采样时刻保证模型正确识别读写操作。该延迟仅用于功能仿真综合时通常会被忽略。注意所有的Memory Compiler生成的存储IP都有这个特点一定要加上延迟才能仿真正确。切换到tb文件夹创建仿真文件dpsram512_16bit_tb.v内容如下timescale 1ns/1ps module dpsram512_16bit_tb; parameter clk_period 10; reg clk; reg ena; reg wea; reg [8:0]addra; reg [15:0]dina; wire [15:0]douta; reg enb; reg web; reg [8:0]addrb; reg [15:0]dinb; wire [15:0]doutb; dpsram512_16bit dpsram512_16bit_inst0( .clka(clk), .ena(ena), .wea(wea), .addra(addra), .dina(dina), .douta(douta), .clkb(clk), .enb(enb), .web(web), .addrb(addrb), .dinb(dinb), .doutb(doutb) ); ifdef DUMP_FSDB initial begin $fsdbDumpfile(dpsram512_16bit.fsdb); $fsdbDumpvars(0,dpsram512_16bit_tb); end endif initial clk 1b1; always #(clk_period/2) clk ~clk; task reset_port_a; ena 1b0;wea 1b0;addra 8d0;dina 16d0;#10; endtask task reset_port_b; enb 1b0;web 1b0;addrb 8d0;dinb 16d0;#10; endtask initial begin reset_port_a; //write addr 1 data 1 ena 1b1;wea 1b1;addra 8d1;dina 16d1;#10; reset_port_a; //read addr 1 ena 1b1;wea 1b0;addra 8d1;dina 16d0;#10; reset_port_a; //write addr 3 data 3 ena 1b1;wea 1b1;addra 8d3;dina 16d3;#10; reset_port_a; //read addr 3 ena 1b1;wea 1b0;addra 8d3;dina 16d0;#10; reset_port_a; //read addr 1 ena 1b1;wea 1b0;addra 8d1;dina 16d0;#10; reset_port_a; //read addr 1 ena 1b1;wea 1b0;addra 8d1;dina 16d0;#10; reset_port_a; //read addr 1 ena 1b1;wea 1b0;addra 8d1;dina 16d0;#10; reset_port_a; #200; $finish; end initial begin reset_port_b; //write addr 2 data 2 enb 1b1;web 1b1;addrb 8d2;dinb 16d2;#10; reset_port_b; //read addr 2 enb 1b1;web 1b0;addrb 8d2;dinb 16d0;#10; reset_port_b; //write addr 3 data 33 enb 1b1;web 1b1;addrb 8d3;dinb 16d33;#10; reset_port_b; //read addr 3 enb 1b1;web 1b0;addrb 8d3;dinb 16d0;#10; reset_port_b; //read addr 1 enb 1b1;web 1b0;addrb 8d1;dinb 16d0;#10; reset_port_b; //write addr 1 11 enb 1b1;web 1b1;addrb 8d1;dinb 16d11;#10; reset_port_b; //read addr 1 enb 1b1;web 1b0;addrb 8d1;dinb 16d0;#10; reset_port_b; end endmodule在dpsram512_16bit_tb.v文件中除了验证A、B端口各自的基本读写功能外还考虑了双端口同时访问存储器的多种特殊情况包括两个端口同时读写不同地址、同时读取同一地址、同时向同一地址写入不同数据以及一个端口读取而另一个端口同时写入同一地址。通过这些场景可以验证双端口SRAM在正常并行访问和端口冲突情况下的仿真行为。切换到sim目录下创建文件filelist.f和Makefile内容如下所示。filelist.f文件内容../tb/dpsram512_16bit_tb.v ../rtl/dpsram512_16bit.v ../rtl/tsdn28hpcpa512x16m4fwbaso_130a_tt0p9v25c.vMakefile文件内容# 基本变量MODULEdpsram512_16bit TB_TOP$(MODULE)_tb WAVE_NAME$(MODULE).fsdb FILELISTfilelist.f SIMVsimv#伪目标.PHONY: all com sim verdi clean all:com sim verdi# 编译com: vcs-full64\-sverilog\v2k\-timescale1ns/1ps\-debug_accessall\-f$(FILELIST)\defineDUMP_FSDB\-fsdb\-o$(SIMV)\-lcompile.log# 仿真sim: ./$(SIMV)-lsim.log# 调试verdi: verdi-sverilog\-f$(FILELIST)\-top$(TB_TOP)\-ssf$(WAVE_NAME)\-nologo# 清理clean:rm-rfcsrc DVEfiles *.daidir *.log simv* *.key *.vpd *.fsdb verdiLog *.conf novas* ucli.key在sim目录下打开终端命令行输入make运行功能仿真自动跳出Verdi界面并查看仿真波形。仿真波形表明A、B端口分别向地址1和地址2写入数据后均能正确读出对应数据当两个端口同时向地址3写入不同数据时发生写写冲突输出变为未知值X。随后两个端口同时读取地址1时均得到数据1当A端口读取地址1、B端口同时向该地址写入数据0xB时发生读写冲突A端口输出X下一周期重新读取后得到更新数据0xB。波形结果符合双端口SRAM的预期行为。总结来说两个端口不能同时向同一地址写入数据两者数据都无法写入两个端口不能同时对一个地址分别进行写和读虽然写可以成功写入但是读出的值为X。3.2 ROM案例3.2.1 ROM IP的生成将目录tsn28hpcprom_20120200_130a/AN61001_20180125/TSMCHOME/sram/Compiler/tsn28hpcprom_20120200_130a/下的文件复制到目录/mem/rom512_8bit/下。向.pl文件添加可执行权限向config.txt添加可写权限。ROM Compiler目录中包含多个Perl脚本用于ROM生成和数据处理。ROM的数据需要固化到芯片版图中因此除了生成脚本外还需要数据格式转换和内容校验脚本。tsn28hpcprom_130a.pl主生成脚本读取config.txt并调用mc2-eu生成ROM IP。bin2hex.pl将二进制ROM数据转换为十六进制格式。hex2intel.pl将普通十六进制数据转换为ROM Compiler使用的Intel HEX格式。chk_rom_code_n28.pl检查生成的网表或Verilog模型中的ROM内容是否与原始数据一致。创建ROM数据文件rom512_8bit.hex采用十六进制格式存放数据。文件共包含512行每行对应一个ROM地址。这里采用了一个完整周期的正弦波数据部分内容如下所示。80 81 83 ... 7C 7E将HEX格式转换为ROM Compiler使用的Intel HEX格式运行下方指令perl hex2intel.pl rom512_8bit.hex rom512_8bit.intelhex指令生成了文件rom512_8bit.intelhex部分内容如下所示:01000000807F :01000100817D :01000200837A ... :0101FE007C84 :0101FF007E81 :00000001FF打开config.txt文件自行查看Databook要求输入下方内容512x8m8m rom512_8bit.intelhex配置MC2环境并生成ROM IP核指令和生成内容如下所示exportPATH/data/SunYuhao_TSMC28/TSMC28/Memory/1/tsmc_n28hpcpmc_20120200_110a/AN61001_20180125/TSMCHOME/sram/Compiler/tsmc_n28hpcpmc_20120200_110a/MC2_2012.02.00.d/bin/Linux-64:$PATHperl tsn28hpcprom_130a.pl如上图所示生成了ROM IP核在各个IC设计阶段需要的文件其中文件TS3N28HPCPA512X8M8MBS.rom.v在后续的功能仿真中会被使用到。下一步检查ROM数据是否正确固化运行校验脚本将输入的Intel HEX数据与生成的SPICE网表中实际固化的ROM内容进行逐地址比较确认512个地址中的8 bit数据完全一致。指令如下所示perl chk_rom_code_n28.pl ts3n28hpcpa512x8m8mbs_130a/SPICE/ts3n28hpcpa512x8m8mbs_130a.spi rom512_8bit.intelhex终端命令行显示结果Result : All Pass3.2.2 ROM IP的功能仿真将目录mem/rom512_8bit/ts3n28hpcpa512x8m8mbs_130a/VERILOG/下的文件ts3n28hpcpa512x8m8mbs_130a_tt0p9v25c.v复制到rtl目录下并切换到rtl目录下。ts3n28hpcpa512x8m8mbs_130a_tt0p9v25c.v文件中同样包含两个模块一个是顶层仿真模块一个是内部存储阵列模块其中顶层仿真模块例化了内部存储阵列模块。下面创建封装模块rom512_8bit.v内容如下所示timescale 1ns/1ps module rom512_8bit ( input wire clk, input wire en, input wire [8:0] addr, output wire [7:0] dout ); // Keep the clock undelayed and delay only the external non-clock inputs. wire en_d; wire [8:0] addr_d; assign #0.1 en_d en; assign #0.1 addr_d addr; TS3N28HPCPA512X8M8MBS u_rom ( // Normal read interface. CEB is active low in the original macro. .A (addr_d), .CEB (~en_d), .CLK (clk), .Q (dout), // BIST interface is disabled during normal operation. .AM (9b0), .CEBM (1b1), .BIST (1b0), // Normal-power and recommended process/test settings. .SLP (1b0), .RTSEL (2b01), .PTSEL (2b01), .TRB (2b01) ); endmodule切换到tb目录下创建仿真文件rom512_8bit_tb.v内容如下timescale 1ns/1ps module rom512_8bit_tb; parameter clk_period 10; reg clk; reg en; reg [8:0]addr; wire [7:0]dout; rom512_8bit rom512_8bit_inst( .clk(clk), .en(en), .addr(addr), .dout(dout) ); ifdef DUMP_FSDB initial begin $fsdbDumpfile(rom512_8bit.fsdb); $fsdbDumpvars(0,rom512_8bit_tb); end endif initial clk 1b1; always #(clk_period/2) clk ~clk; integer i; initial begin en 1b0; addr 9d0; #100; for(i0;i512;ii1)begin en 1b1; addr i; #10; end en 1b0; #100; $finish; end endmodule切换到sim目录下修改Makefile文件中变量MODULE rom512_8bit即可。同时编辑filelist.f文件内容为../tb/rom512_8bit_tb.v ../rtl/rom512_8bit.v ../rtl/ts3n28hpcpa512x8m8mbs_130a_tt0p9v25c.v注意想要完成功能仿真需要将文件TS3N28HPCPA512X8M8MBS.rom.v也复制到sim目录下。该文件在运行tsn28hpcprom_130a.pl脚本时被生成出来目录为mem/rom512_8bit/ts3n28hpcpa512x8m8mbs_130a。在sim目录下打开终端命令行输入命令make完成ROM的功能仿真Verdi界面自动出现。修改信号显示为Analog Waveform波形如下所示。4. 总结本文对SRAM和ROM两种IP的生成流程进行了简单介绍和演示剩余的Memory Compiler内容需要大家自己去探索。有任何问题欢迎大家在评论区进行讨论