如何在 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 的相关文章

  • 如何获取 RAM 大小、引导加载程序

    我想问如何在引导加载程序中获取总 RAM 大小和可用 RAM 大小 截至目前 我知道如何获得较低的内存 但由于某种原因我无法将其打印到屏幕上 因为它保存在斧头寄存器中 这是我到目前为止所拥有的 BITS 16 BootLoader alwa
  • 标识符必须用端口模式声明:busy。 (Verilog)

    我有如下所示的 Verilog 代码 当我编译它时 我收到以下错误消息 并且代码的第一行突出显示 Error 标识符必须用端口模式声明 busy Code module main clk rst start busy ready cnt s
  • 这个 Haskell 函数的类型签名是什么?

    我写了一个函数来检查一个数字是否是质数 prime n prime n 2 floor sqrt n where prime n c u n mod c 0 False c gt u True otherwise prime n c 1 u
  • 函数类型可以通过推理来定义吗?

    Scala 类型推断非常好 而且很容易习惯 不必写两次 当你不得不这么做的时候 你会更痛苦 函数类型就是这样的一个例子 有时我想为某些函数签名创建命名类型 有可能吗 有什么方法可以获取函数的编译时类型 这样我在定义时就不必再次输入它FTyp
  • 评估 C/C++ 内存泄漏时的虚拟内存与物理内存

    我有一个 C 应用程序 我试图解决内存泄漏问题 但我意识到我并不完全理解虚拟内存和物理内存之间的区别 由于 导致的结果top 所以 16 8g 虚拟 111m 物理 4406 um 20 0 16 8g 111m 4928 S 64 7 2
  • 如何从 Spartan 6 写入 Nexys 3 FPGA 板上的 Micron 外部蜂窝 RAM?

    我到处都查过了 数据表 Xilinx 网站 digilent 等等 但什么也没找到 我能够使用 Adept 工具来验证我的蜂窝 RAM 是否正常运行 但我找不到任何库存 VHDL 代码作为控制器来写入数据和从中读取数据 帮助 找到了此链接
  • ToString() 与字符串运算符的类型推断

    注 这个问题和我的有些关系前一个 https stackoverflow com questions 41347374 tostring throws nullreferenceexception for unit value 但实际上从不
  • Verilog 中的大括号是什么意思?

    我很难理解 Verilog 中的以下语法 input 15 0 a 16 bit input output 31 0 result 32 bit output assign result 16 a 15 a 15 0 我知道assign语句
  • 在 Windows 上使用 PHP 获取总可用系统内存

    使用 PHP 我想获取系统可用的总内存 而不仅仅是空闲或已用内存 在 Linux 上 这非常简单 你可以做 memory fopen proc meminfo 然后解析该文件 有人知道 Windows 的等效方法吗 我愿意接受任何建议 编辑
  • 使用推断的 (?) 类型克隆 std::iter::Map

    我在以紧凑的方式克隆地图时遇到问题 extern crate itertools num use itertools num linspace fn main 440Hz as wave frequency middle A let fre
  • 使用正则表达式进行 Verilog 端口映射

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

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

    以下代码无法编译 trait A F def find x Int F def fill f F Unit object TestA def test T lt A F forSome type F t T t fill t find 0
  • 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
  • Verilog 双向握手示例

    我正在完成一个项目 要求是处理器内部功能单元之间的双向握手 我知道它是什么 但是有没有任何 标准 或一个简单的例子 我唯一能想到的就是两个单元之间 当它们之间有一条数据线并且当 X 发送到 Y 时 会给出一个单独的 发送 信号 当 Y 接收
  • 学习 Verilog 的资源 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我是 Verilog 新手 有人可以推荐学习资源 书籍 视频 博客或任何他们有良好个人经验并帮助他们更
  • \add_34/U1_1_6 的 Verilog 命名约定

    有人可以解释一下这个命名约定在下面的 Verilog 行中意味着什么吗 我不知道这是什么 add 34 部分的意思是 ADDHXL add 34 U1 1 6 A n1022 B add 34 carry 6 CO add 34 carry
  • 为什么 GHC 在这里推断出单态类型,即使禁用了单态限制?

    这是由解析 f f pure 的类型 https stackoverflow com questions 55388119 resolving the type of f f pure 55388309 noredirect 1 comme
  • 从测试台访问子模块中的输入和输出

    我的被 测设备 DUT 有许多子模块 我想测试其中的一些 我的测试夹具将是我的项目的顶层 比 DUT 高一级 并且由于我似乎只能访问下一层模块的输入和输出 所以我只能访问顶层的输入和输出被测设备 我希望能够从测试夹具下方的两层或多层模块访问
  • Java 8 中异常类型推断的一个独特功能

    在为该网站上的另一个答案编写代码时 我遇到了这个特性 static void testSneaky final Exception e new Exception sneakyThrow e no problems here nonSnea

随机推荐