如何在 Verilog 中推断块 RAM [英] How to infer block RAM in Verilog

查看:115
本文介绍了如何在 Verilog 中推断块 RAM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've got one very specific problem with a project that has been haunting me for days now. I have the following Verilog code for a RAM module:

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

它的行为完全符合预期,但是当我开始合成时,我得到以下信息:

It behaves exactly as expected, however when I go to synthesize I get the following:

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

32768 flip-flops! Why doesn't it just infer a block RAM? This RAM module is so huge (and I have two of them - one for instruction memory, one for data memory) that it consumes the entire available area of the FPGA... times 2.4

我一直在想方设法迫使它推断出一个块 RAM 而不是 33k 触发器,但除非我能尽快弄明白,否则我可能不得不大大减少我的内存大小以适应芯片.

I've been trying everything to force it to infer a block RAM instead of 33k flip flops, but unless I can get it figured out soon I may have to greatly reduce the size of my memory just to fit on a chip.

推荐答案

我只是删除了你的代码,结果如下:

I just remove something your code, the result like this:

 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  

初始化全零可能不需要代码,如果你想初始化,就去做:

Init all zeros may dont't need code, if you want to init, just do it:

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

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

Then the result that I got from 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,您必须强制它:Synthesis - XST -> Process Properties -> HDL option -> RAM style -> Change from auto to Block.结果将是这样的:

Update here!: Strong thanks to mcleod_ideafix Sorry about forgot your question: it's block RAM, not distributed. For block RAM, you must force it: Synthesis - XST -> Process Properties -> HDL option -> RAM style -> Change from auto to Block. The result will be this:

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).

更新结束

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

I recommend you read xst user guide for RAM sample code and the device data sheet. For example, in some FPGA LUT RAM: the reset signal is not valid. If you tried to reset it, the more logic module to reset must be integrate it. It leads to D-FF instead of RAM. The Reset signal will auto-assign to system reset.

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

In case of Block RAM (not LUT RAM), I prefer to specific depth/data-width or core generation or call it directly from library. More source code for general usage (ASIC/FPGA) can be found here: http://asic-world.com/examples/verilog/ram_dp_sr_sw.html

这篇关于如何在 Verilog 中推断块 RAM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆