如何在 Verilog 中推断 Block RAM

2024-04-11

我在一个项目中遇到了一个非常具体的问题,这个问题已经困扰我好几天了。我有以下 RAM 模块的 Verilog 代码:

module RAM_param(clk, addr, read_write, clear, data_in, data_out);
    parameter n = 4;
    parameter w = 8;

    input clk, read_write, clear;
    input [n-1:0] addr;
    input [w-1:0] data_in;
    output reg [w-1:0] data_out;

    reg [w-1:0] reg_array [2**n-1:0];

    integer i;
    initial begin
        for( i = 0; i < 2**n; i = i + 1 ) begin
            reg_array[i] <= 0;
        end
    end

    always @(negedge(clk)) begin
        if( read_write == 1 )
            reg_array[addr] <= data_in;
        if( clear == 1 ) begin
            for( i = 0; i < 2**n; i = i + 1 ) begin
                reg_array[i] <= 0;
            end
        end
        data_out = reg_array[addr];
    end
endmodule

它的行为完全符合预期,但是当我去合成时,我得到以下结果:

Synthesizing Unit <RAM_param_1>.
    Related source file is "C:\Users\stevendesu\---\RAM_param.v".
        n = 11
        w = 16
    Found 32768-bit register for signal <n2059[32767:0]>.
    Found 16-bit 2048-to-1 multiplexer for signal <data_out> created at line 19.
    Summary:
    inferred 32768 D-type flip-flop(s).
    inferred 2049 Multiplexer(s).
Unit <RAM_param_1> synthesized.

32768人字拖!为什么它不直接推断出块 RAM?这个 RAM 模块非常巨大(我有两个 - 一个用于指令存储器,一个用于数据存储器),以至于它消耗了 FPGA 的整个可用区域...乘以 2.4

我一直在尽一切努力迫使它推断出块 RAM 而不是 33k 触发器,但除非我能尽快弄清楚,否则我可能必须大大减少内存大小才能适应芯片。


我只是删除了你的代码,结果是这样的:

 module RAM_param(clk, addr, read_write, clear, data_in, data_out);
parameter n = 4;
parameter w = 8;

input clk, read_write, clear;
input [n-1:0] addr;
input [w-1:0] data_in;
output reg [w-1:0] data_out;

// Start module here!
reg [w-1:0] reg_array [2**n-1:0];

integer i;
initial begin
    for( i = 0; i < 2**n; i = i + 1 ) begin
        reg_array[i] <= 0;
    end
end

always @(negedge(clk)) begin
    if( read_write == 1 )
        reg_array[addr] <= data_in;
    //if( clear == 1 ) begin
        //for( i = 0; i < 2**n; i = i + 1 ) begin
            //reg_array[i] <= 0;
        //end
    //end
    data_out = reg_array[addr];
end
endmodule  

初始化全零可能不需要代码,如果你想初始化,只需这样做:

initial
begin
    $readmemb("data.dat", mem);
end

然后是我从 ISE 13.1 得到的结果

Synthesizing (advanced) Unit <RAM_param>.
INFO:Xst:3231 - The small RAM <Mram_reg_array> will be implemented on LUTs in order to maximize performance and save block RAM resources. If you want to force its implementation on block, use option/constraint ram_style.

    -----------------------------------------------------------------------
    | ram_type           | Distributed                         |          |
    -----------------------------------------------------------------------
    | Port A                                                              |
    |     aspect ratio   | 16-word x 8-bit                     |          |
    |     clkA           | connected to signal <clk>           | fall     |
    |     weA            | connected to signal <read_write>    | high     |
    |     addrA          | connected to signal <addr>          |          |
    |     diA            | connected to signal <data_in>       |          |
    |     doA            | connected to internal node          |         

此处更新!:强烈感谢 mcleod_ideafix抱歉忘记了你的问题:它是块 RAM,不是分布式的。对于块 RAM,您必须强制它:综合 - XST -> 进程属性 -> HDL 选项 -> RAM 样式 -> 从自动更改为块。结果将是这样的:

Synthesizing (advanced) Unit <RAM_param>.
INFO:Xst:3226 - The RAM <Mram_reg_array> will be implemented as a BLOCK RAM, absorbing the following register(s): <data_out>
    -----------------------------------------------------------------------
    | ram_type           | Block                               |          |
    -----------------------------------------------------------------------
    | Port A                                                              |
    |     aspect ratio   | 16-word x 8-bit                     |          |
    |     mode           | read-first                          |          |
    |     clkA           | connected to signal <clk>           | fall     |
    |     weA            | connected to signal <read_write>    | high     |
    |     addrA          | connected to signal <addr>          |          |
    |     diA            | connected to signal <data_in>       |          |
    |     doA            | connected to signal <data_out>      |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
Unit <RAM_param> synthesized (advanced).

更新结束

我建议您阅读 xst 用户指南以获取 RAM 示例代码和器件数据表。例如,在某些FPGA LUT RAM中:复位信号无效。如果您尝试重置它,则必须集成更多要重置的逻辑模块。它导致 D-FF 而不是 RAM。复位信号将自动分配给系统复位。

对于 Block RAM(不是 LUT RAM),我更喜欢特定的深度/数据宽度或核心生成或直接从库中调用它。 更多通用源代码(ASIC/FPGA)可以在这里找到:http://asic-world.com/examples/verilog/ram_dp_sr_sw.html http://asic-world.com/examples/verilog/ram_dp_sr_sw.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Verilog 中推断 Block RAM 的相关文章

  • 如何使用 Verilog 和 FPGA 计算一系列组合电路的传播延迟?

    我是 FPGA 和 HDL 的新手 但我正在尝试学习 但无法弄清楚这一点 如何通过多个级别的组合逻辑来计算或估计传播延迟 我可以仅凭经验确定这一点 还是可以在设计时弄清楚 在这种情况下 我使用 FPGA 来实现奇偶校验设置和检查电路 该电路
  • Verilog 中的“net”代表什么?

    我刚刚开始学习Verilog 据我了解 Verilog有net数据类型 什么是net代表 网络就是这样一种数据类型 您不使用它来存储值 它们代表物理连接 您可以将线路视为一种网络数据类型 你可以去网上看看更多here http www ee
  • 使用 lambda 表达式的嵌套集合创建对象图

    我对利用 lambda 表达式创建属性选择器树感兴趣 使用场景是 我们有一些代码对对象图进行一些递归反射 为了限制递归的范围 我们目前使用 Attributes 来标记应该遍历哪些属性 即获取对象的所有修饰属性 如果该属性是具有修饰属性的引
  • 使用接口和泛型约束进行类型推断

    我正在构建一个通用查询调度程序 想法如下 通用接口IQuery
  • 如何获取设备的总 RAM 大小?

    我想获得设备的完整 RAM 大小 memoryInfo getTotalPss 返回 0 中没有获取总 RAM 大小的函数ActivityManager MemoryInfo http developer android com refer
  • 向左旋转 verilog 大小写

    我的任务是用verilog编写一个16位ALU 当我做需要旋转操作数和进行2的补码加法和减法的部分时 我发现了困难 我知道如何用纸和铅笔解决这个问题 但我无法弄清楚如何在 Verilog 中做到这一点 例如 A表示为a15 a14 a13
  • 为什么对变量调用方法会阻止 Rust 推断变量的类型?

    此代码编译 derive Debug Default struct Example impl Example fn some method self fn reproduction gt Example let example Defaul
  • 通过 Emacs 启动时如何配置 SBCL 以使用更多 RAM?

    如何配置 SBCL 使其在使用 Emacs 中的 M x slime 启动时使用比默认值更多的内存 从我在网上看到的情况来看 答案似乎是调用 SBCL 传递参数 dynamic space size 由于我不直接调用 SBCL 因此我不知道
  • 如何获取 Java7 应用程序的 CPU、RAM 和网络使用情况

    我找到了这篇旧文章如何在 Java 中监控计算机的 cpu 内存和磁盘使用情况 https stackoverflow com questions 47177 how to monitor the computers cpu memory
  • ToString() 与字符串运算符的类型推断

    注 这个问题和我的有些关系前一个 https stackoverflow com questions 41347374 tostring throws nullreferenceexception for unit value 但实际上从不
  • 使用 C++0x decltype 返回值时返回局部变量或临时变量的地址

    Edit 这确实是编译器的一个bug 我开了一个defect https connect microsoft com VisualStudio feedback details 573330 bad code generated for f
  • 使用 php 获取服务器内存

    有没有办法用 php 知道服务器 linux 发行版 中的可用内存 不使用 linux 命令 编辑 抱歉 目标是了解特定服务器的服务器 虚拟机中可用的内存 即使该内存是共享的 如果你知道这段代码只能在Linux下运行 你可以使用特殊的 pr
  • C# 泛型类型推断与协方差 - bug 或限制

    当具有依赖参数的泛型方法推断类型时 它在某些情况下会给出意外的结果 如果我明确指定类型 则一切都可以正常工作 无需任何进一步的更改 IEnumerable
  • 将 IntelliJ IDEA 缓存/索引目录移动到 RAM

    我正在尝试移动caches and index从 IntelliJ IDEA 配置目录到 RAM 挂载点的目录 tmp使用符号链接 我已经添加 tmpfs tmp ramdisk tmpfs defaults size 1024M x gv
  • 为什么编译器无法推断对象数组类型?

    我想知道为什么这是有效的 object array bla bla bla 23 true 但这些不是 var array bla bla bla 23 true var array2 new bla bla bla 23 true 在第二
  • 使用正则表达式进行 Verilog 端口映射

    我有一个很长的端口映射 我想在其中替换一堆 SignalName i with SignalName SignalName i 我想我可以用正则表达式轻松地做到这一点 但我无法弄清楚如何做到这一点 有任何想法吗 假设 SignalData
  • 大师系统要求

    我们将使用 Virtuoso 来存储 RDF 三重计数一开始将为 1 亿 我需要知道典型的 RAM CPU 磁盘等应该是什么 查询将使用 SPARQL 并且查询会有点复杂 请提供您的意见 Virtuoso 版本 6 x 三元组 四元组 的平
  • Scala 类型参数推理因 Nothing 失败

    scala gt class A T defined class A scala gt class B T a A T defined class B scala gt val b new B new A Int b B Int B 1ff
  • 内存地址是否指向一个字节的信息?

    以下是 DTS 文件的摘录 linux arch powerpc boot dts 板名 dts memory device type memory reg lt 0x00000000 0x40000000 gt 1GB at 0 嵌入式设
  • 如何手动推断表达式的类型

    给定 Haskell 函数 head filter fst 现在的问题是如何手动 手动 找到类型 如果我让 Haskell 告诉我我得到的类型 head filter fst Bool b gt Bool b 但我想了解仅使用所用函数的签名

随机推荐