You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SystemVerilog BRAM映射失败求助:写入计数器值无法综合

Yosys综合Tang Nano 4K RAM时写入计数器值失败的问题

在使用Yosys为Tang Nano 4K综合SystemVerilog存储器时,遇到如下问题:仅当向RAM写入固定值时可正常完成综合,若写入计数器值则综合失败。

可正常工作的代码

module top (
        input logic clk_i,
        output logic data_o
    );

    reg [31:0] counter  = '0;

    (* ram_style="block" *)
    reg [31:0] video_ram_array [0:(2**15)-1];

    always_ff @(posedge clk_i) begin
        counter <= counter + 1;
        // video_ram_array[counter] <= counter;
        video_ram_array[counter] <= 32'h1234;
    end


    always_comb begin
        data_o = video_ram_array[counter][0];
    end

endmodule

无法工作的代码

module top (
        input logic clk_i,
        output logic data_o
    );

    reg [31:0] counter  = '0;

    (* ram_style="block" *)
    reg [31:0] video_ram_array [0:(2**15)-1];

    always_ff @(posedge clk_i) begin
        counter <= counter + 1;
        video_ram_array[counter] <= counter;
        // video_ram_array[counter] <= 32'h1234;
    end


    always_comb begin
        data_o = video_ram_array[counter][0];
    end

endmodule

综合错误信息

2.8. Executing MEMORY_LIBMAP pass (mapping memories to cells).
<suppressed ~2 debug messages>
ERROR: no valid mapping found for memory top.video_ram_array
make: *** [run] Error 1

补充信息

即使将RAM规模缩小至[0:2],问题仍存在。怀疑首次成功是因为综合器优化了BRAM,但netlistsvg显示结构符合预期,不确定是否实际有效。


问题原因与解决方法

原因分析

核心问题在于:

  1. 时序与端口约束不匹配:Tang Nano 4K搭载的Gowin BRAM原语对同步读写的时序、端口信号复用有严格要求。你的代码中,counter同时作为写地址、写数据和读地址,且读写地址在同一时钟沿使用同一信号值,这种组合无法匹配BRAM原语的端口逻辑,导致Yosys的MEMORY_LIBMAP pass找不到有效映射。
  2. 固定值写入的特殊优化:写入固定值时,Yosys会自动将RAM优化为只读存储器(ROM),绕过了BRAM的写端口约束,因此能正常综合,但这并非实际的可写BRAM实现。

解决步骤

  1. 拆分读写地址,消除时序冲突
    将读地址延迟一个时钟周期,避免读写操作在同一周期复用同一地址信号,匹配BRAM的同步端口时序要求:

    module top (
            input logic clk_i,
            output logic data_o
        );
    
        reg [31:0] counter  = '0;
        reg [31:0] read_addr = '0;
    
        (* ram_style="block" *)
        reg [31:0] video_ram_array [0:(2**15)-1];
    
        always_ff @(posedge clk_i) begin
            counter <= counter + 1;
            read_addr <= counter; // 读地址延迟一个周期,规避读写时序冲突
            video_ram_array[counter] <= counter;
        end
    
        always_comb begin
            data_o = video_ram_array[read_addr][0];
        end
    
    endmodule
    
  2. 调整综合约束或直接例化BRAM原语

    • 若拆分地址后仍有问题,可先移除(* ram_style="block" *)约束,让Yosys自动选择存储器类型(分布式RAM可绕过部分BRAM端口限制,但若需BRAM则不推荐)。
    • 直接例化Gowin官方提供的BRAM原语,完全控制端口连接,确保符合器件的物理特性。
  3. 检查综合脚本的库配置
    确保Yosys综合脚本正确加载了Gowin的器件库,示例脚本片段:

    read_verilog top.sv
    synth_gowin -family GW1NR -device GW1NR-LV9QN88PC6/I5
    write_verilog -attr2comment top_synth.v
    

验证说明

首次写固定值时的“成功”是Yosys将RAM优化为ROM的结果,并非实际的可写BRAM。可通过查看综合后的网表文件(top_synth.v)确认是否真的映射到了BRAM原语。

内容的提问来源于stack exchange,提问作者Filip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 03:12:22