(* ram_style=“ultra“ *)

        在Verilog/SystemVerilog中,(* ram_style = "ultra" *) 是一个Xilinx专用综合属性,用于指导Vivado工具将存储器推断为UltraScale+架构中的UltraRAM资源。

一、语法和作用

(* ram_style = "ultra" *) reg [width-1:0] memory [0:depth-1];

二、UltraRAM 特点

UltraRAM是Xilinx UltraScale+器件中的专用大容量RAM资源:

  • 超大容量:每个UltraRAM 4K x 72位(288Kb)

  • 专用资源:不占用块RAM或LUT资源

  • 特定结构:同步读写、简单双端口

  • 适用场景:超大容量存储应用

三、主要用途和示例

1. 基本UltraRAM实现

module ultra_ram_basic (
    input wire clk,
    input wire we,
    input wire [11:0] addr,     // 4K深度
    input wire [63:0] din,      // 64位宽度
    output reg [63:0] dout
);
    
    (* ram_style = "ultra" *) reg [63:0] ultra_ram [0:4095];
    
    always @(posedge clk) begin
        if (we)
            ultra_ram[addr] <= din;
        dout <= ultra_ram[addr];
    end
endmodule

2. UltraRAM vs 块RAM容量对比

module ram_capacity_comparison (
    input wire clk,
    input wire we,
    input wire [15:0] addr_block, addr_ultra,
    input wire [63:0] din,
    output reg [63:0] dout_block, dout_ultra
);
    
    // 块RAM - 最大深度受限于块RAM资源
    (* ram_style = "block" *) reg [63:0] block_ram [0:511];     // 512x64 = 32Kb
    
    // UltraRAM - 超大容量
    (* ram_style = "ultra" *) reg [63:0] ultra_ram [0:4095];    // 4Kx64 = 256Kb
    
    always @(posedge clk) begin
        if (we) begin
            block_ram[addr_block[8:0]] <= din;
            ultra_ram[addr_ultra] <= din;
        end
        dout_block <= block_ram[addr_block[8:0]];
        dout_ultra <= ultra_ram[addr_ultra];
    end
endmodule

3. 简单双端口UltraRAM

module simple_dual_port_ultra (
    input wire clk,
    input wire we,
    input wire [11:0] waddr, raddr,
    input wire [71:0] din,      // 72位宽度充分利用UltraRAM
    output reg [71:0] dout
);
    
    (* ram_style = "ultra" *) reg [71:0] ultra_ram [0:4095];
    
    always @(posedge clk) begin
        if (we)
            ultra_ram[waddr] <= din;
        dout <= ultra_ram[raddr];
    end
endmodule

四、实际应用场景

1. 大数据缓冲区

module large_data_buffer (
    input wire clk,
    input wire rst,
    input wire wr_en, rd_en,
    input wire [11:0] wr_addr, rd_addr,
    input wire [63:0] wr_data,
    output reg [63:0] rd_data,
    output reg full, empty
);
    
    parameter DEPTH = 4096;
    
    (* ram_style = "ultra" *) reg [63:0] data_buffer [0:DEPTH-1];
    reg [12:0] wr_ptr, rd_ptr;
    reg [13:0] data_count;
    
    assign full = (data_count == DEPTH);
    assign empty = (data_count == 0);
    
    always @(posedge clk) begin
        if (rst) begin
            wr_ptr <= 0;
            rd_ptr <= 0;
            data_count <= 0;
        end else begin
            // 写操作
            if (wr_en && !full) begin
                data_buffer[wr_ptr[11:0]] <= wr_data;
                wr_ptr <= wr_ptr + 1;
            end
            
            // 读操作
            if (rd_en && !empty) begin
                rd_data <= data_buffer[rd_ptr[11:0]];
                rd_ptr <= rd_ptr + 1;
            end
            
            // 更新计数器
            case ({wr_en && !full, rd_en && !empty})
                2'b10: data_count <= data_count + 1;
                2'b01: data_count <= data_count - 1;
                default: data_count <= data_count;
            endcase
        end
    end
endmodule

2. 帧缓冲区(Frame Buffer)

module frame_buffer_ultra (
    input wire clk,
    input wire we,
    input wire [11:0] pixel_x,    // 0-4095
    input wire [10:0] pixel_y,    // 0-2047  
    input wire [23:0] pixel_data, // RGB各8位
    output reg [23:0] pixel_out
);
    
    // 4096x2048 像素的帧缓冲区
    (* ram_style = "ultra" *) reg [23:0] frame_buffer [0:8191]; // 8K行,每行存储多个像素
    
    wire [12:0] line_addr = pixel_y[10:3];  // 每行存储8个像素
    wire [2:0]  pixel_offset = pixel_y[2:0];
    wire [15:0] combined_addr = {line_addr, pixel_offset, pixel_x[2:0]};
    
    always @(posedge clk) begin
        if (we)
            frame_buffer[combined_addr] <= pixel_data;
        pixel_out <= frame_buffer[combined_addr];
    end
endmodule

3. 神经网络权重存储

module neural_weights_ultra (
    input wire clk,
    input wire we,
    input wire [3:0] layer_sel,
    input wire [11:0] weight_addr,
    input wire [31:0] weight_data,
    output reg [31:0] weight_out
);
    
    // 存储多个神经网络的权重
    (* ram_style = "ultra" *) reg [31:0] weight_memory [0:16383]; // 16K权重
    
    wire [13:0] full_addr = {layer_sel, weight_addr};
    
    always @(posedge clk) begin
        if (we)
            weight_memory[full_addr] <= weight_data;
        weight_out <= weight_memory[full_addr];
    end
endmodule

五、工具支持和限制

1. UltraRAM配置选项

module ultra_ram_configurable (
    input wire clk,
    input wire we,
    input wire [1:0] config_mode,
    input wire [11:0] addr,
    input wire [71:0] din,
    output reg [71:0] dout
);
    
    (* ram_style = "ultra" *) reg [71:0] ultra_ram [0:4095];
    
    // 根据配置模式选择不同的操作
    always @(posedge clk) begin
        case (config_mode)
            2'b00: begin // 正常模式
                if (we) ultra_ram[addr] <= din;
                dout <= ultra_ram[addr];
            end
            2'b01: begin // 只读模式
                dout <= ultra_ram[addr];
            end
            2'b10: begin // 初始化模式
                if (we) ultra_ram[addr] <= 72'h0;
                dout <= ultra_ram[addr];
            end
            default: begin
                if (we) ultra_ram[addr] <= din;
                dout <= ultra_ram[addr];
            end
        endcase
    end
endmodule

六、使用建议和最佳实践

1. 容量规划示例

module memory_hierarchy_design (
    input wire clk,
    input wire we,
    input wire [19:0] addr,  // 1M地址空间
    input wire [31:0] din,
    output reg [31:0] dout
);
    
    // 根据地址范围选择不同的存储器类型
    wire [1:0] mem_region = addr[19:18];
    
    // 小容量:寄存器实现(最高性能)
    (* ram_style = "register" *) reg [31:0] fast_mem [0:255];      // 1K-256地址
    
    // 中容量:分布式RAM
    (* ram_style = "distributed" *) reg [31:0] medium_mem [0:1023]; // 1K-4K地址
    
    // 大容量:块RAM  
    (* ram_style = "block" *) reg [31:0] large_mem [0:16383];      // 16K-64K地址
    
    // 超大容量:UltraRAM
    (* ram_style = "ultra" *) reg [31:0] huge_mem [0:262143];      // 256K-1M地址
    
    always @(posedge clk) begin
        if (we) begin
            case (mem_region)
                2'b00: fast_mem[addr[7:0]] <= din;
                2'b01: medium_mem[addr[9:0]] <= din;
                2'b10: large_mem[addr[13:0]] <= din;
                2'b11: huge_mem[addr[17:0]] <= din;
            endcase
        end
        
        case (mem_region)
            2'b00: dout <= fast_mem[addr[7:0]];
            2'b01: dout <= medium_mem[addr[9:0]];
            2'b10: dout <= large_mem[addr[13:0]];
            2'b11: dout <= huge_mem[addr[17:0]];
        endcase
    end
endmodule

七、UltraRAM的特定约束

1. 字节使能实现

module ultra_ram_byte_enable (
    input wire clk,
    input wire we,
    input wire [7:0] byte_en,    // 字节使能(针对72位数据)
    input wire [11:0] addr,
    input wire [71:0] din,
    output reg [71:0] dout
);
    
    (* ram_style = "ultra" *) reg [71:0] ultra_ram [0:4095];
    reg [71:0] ram_read;
    
    always @(posedge clk) begin
        ram_read <= ultra_ram[addr];
        
        if (we) begin
            // 字节级写入
            for (int i = 0; i < 8; i = i + 1) begin
                if (byte_en[i])
                    ultra_ram[addr][i*9+:8] <= din[i*9+:8];
            end
            // 奇偶校验位处理(第9位)
            if (byte_en[8])
                ultra_ram[addr][71:64] <= din[71:64];
        end
        
        dout <= ram_read;
    end
endmodule

八、属性取值对比

(* ram_style = "ultra" *)        // UltraRAM(Xilinx UltraScale+超大容量)
(* ram_style = "block" *)        // 块RAM(通用大容量)
(* ram_style = "distributed" *)  // 分布式RAM(小容量,灵活)
(* ram_style = "register" *)     // 寄存器(极小容量,高性能)
(* ram_style = "auto" *)         // 工具自动选择

九、UltraRAM的特点总结

1. 优点

  • 超大容量(每个288Kb)

  • 专用硬件资源,不占用其他RAM

  • 适合大规模数据存储

  • 在UltraScale+器件中高效使用

2. 限制

  • Xilinx UltraScale+专用

  • 特定端口配置(主要是简单双端口)

  • 同步读写操作

  • 深度和宽度有特定限制(主要是4K x 72)

3. 适用场景

  • 大数据缓冲区

  • 帧缓冲区

  • 神经网络权重存储

  • 数据库缓存

  • 任何需要超大容量片上存储的应用

4. 注意事项

  1. 仅适用于Xilinx UltraScale+及以上架构

  2. 需要Vivado工具支持

  3. 检查器件是否包含UltraRAM资源

  4. 遵循UltraRAM的特定时序和配置要求

这个属性在需要超大容量片上存储的Xilinx UltraScale+设计中非常有用,可以充分利用器件的专用大容量RAM资源。

module distance_gate_processor ( input clk, // 250MHz时钟 input rst, // 复位信号(高有效) input data_valid, // 输入数据有效标志 input [15:0] data_in, // 输入数据 output reg [15:0] data_out [0:49], // 输出寄存器数组 output reg frame_done // 帧完成信号 ); // 参数定义 parameter NUM_GATES = 50; // 距离门数量 parameter REAL_POINTS = 500; // 真实数据点数 parameter ZERO_PAD = 12; // 补零点数 parameter TOTAL_POINTS = REAL_POINTS + ZERO_PAD; // 总点数/门 // 控制信号 reg [5:0] gate_index; // 距离门索引 (0-49) reg [8:0] point_index; // 点索引 (0-511) wire write_enable; // ==== BRAM自动级联实现 ==== (* cascade_height = 4, ram_style = "block" *) reg [15:0] ram [0:NUM_GATES*TOTAL_POINTS-1]; // 50×512深度×16宽度 // 输出控制信号 typedef enum {IDLE, OUTPUT} state_t; reg [5:0] out_gate; // 输出门索引 reg [8:0] out_point; // 输出点索引 state_t output_state; reg output_ready; // 输出数据有效标志 // 地址计算 wire [14:0] write_addr = gate_index * TOTAL_POINTS + point_index; wire [14:0] read_addr = out_gate * TOTAL_POINTS + out_point; // 写使能:仅在有效数据周期或补零周期使能 assign write_enable = data_valid || (point_index >= REAL_POINTS); // 初始化逻辑 initial begin for (int i = 0; i < NUM_GATES*TOTAL_POINTS; i++) begin ram[i] = 16'b0; end for (int g = 0; g < NUM_GATES; g++) begin data_out[g] = 16'b0; end end // ==== 写控制逻辑 ==== always @(posedge clk or posedge rst) begin if (rst) begin gate_index <= 0; point_index <= 0; frame_done <= 0; end else begin frame_done <= 0; if (write_enable) begin // 真实数据阶段 (0-499) if (point_index < REAL_POINTS) begin ram[write_addr] <= data_in; end // 自动触发补零 (500-511) else begin ram[write_addr] <= 16'b0; // 显式补零 end // 索引更新 if (point_index == TOTAL_POINTS-1) begin point_index <= 0; if (gate_index == NUM_GATES-1) begin gate_index <= 0; end else begin gate_index <= gate_index + 1; end end else begin point_index <= point_index + 1; end end end end // ==== 输出状态机逻辑 ==== always @(posedge clk or posedge rst) begin if (rst) begin output_state <= IDLE; out_gate <= 0; out_point <= 0; output_ready <= 0; frame_done <= 0; // 初始化输出数组 for (int g = 0; g < NUM_GATES; g++) data_out[g] <= 16'b0; end else begin output_ready <= 0; // 默认无效 case(output_state) IDLE: begin // 检测所有门数据收集完成 if (gate_index == NUM_GATES-1 && point_index == TOTAL_POINTS-1 && write_enable) begin output_state <= OUTPUT; out_gate <= 0; out_point <= 0; end end OUTPUT: begin // 更新当前门的数据 (自动级联读取) data_out[out_gate] <= ram[read_addr]; output_ready <= 1; // 索引更新 if (out_point == TOTAL_POINTS-1) begin out_point <= 0; if (out_gate == NUM_GATES-1) begin out_gate <= 0; output_state <= IDLE; frame_done <= 1; // 帧完成信号 end else begin out_gate <= out_gate + 1; end end else begin out_point <= out_point + 1; end end endcase end end // ==== 时序优化寄存器 ==== (* use_dsp48 = "no" *) (* dont_touch = "true" *) reg [5:0] gate_index_reg; reg [8:0] point_index_reg; always @(posedge clk) begin gate_index_reg <= gate_index; point_index_reg <= point_index; end endmodule你还有更好的办法吗?芯片是xc7z045ffg900。
09-20
module distance_gate_processor ( input clk, // 250MHz时钟 input rst, // 复位信号(高有效) input data_valid, // 输入数据有效标志 input [15:0] data_in, // 输入数据 output reg [15:0] data_out [0:49], // 输出寄存器数组 output reg frame_done // 帧完成信号 ); // 参数定义 parameter NUM_GATES = 50; // 距离门数量 parameter REAL_POINTS = 500; // 真实数据点数 parameter ZERO_PAD = 12; // 补零点数 parameter TOTAL_POINTS = REAL_POINTS + ZERO_PAD; // 总点数/门 // 控制信号 reg [5:0] gate_index; // 距离门索引 (0-49) reg [8:0] point_index; // 点索引 (0-511) wire write_enable; // 双端口RAM:50×512深度×16宽度 reg [15:0] ram [0:NUM_GATES*TOTAL_POINTS-1]; // 输出控制信号 typedef enum {IDLE, OUTPUT} state_t; reg [5:0] out_gate; // 输出门索引 reg [8:0] out_point; // 输出点索引 state_t output_state; reg output_ready; // 输出数据有效标志 // 地址计算 wire [14:0] write_addr = gate_index * TOTAL_POINTS + point_index; wire [14:0] read_addr = out_gate * TOTAL_POINTS + out_point; // 写使能:仅在有效数据周期或补零周期使能 assign write_enable = data_valid || (point_index >= REAL_POINTS); // 初始化逻辑 initial begin for (int i = 0; i < NUM_GATES*TOTAL_POINTS; i++) begin ram[i] = 16'b0; end for (int g = 0; g < NUM_GATES; g++) begin data_out[g] = 16'b0; end end // 写控制逻辑 always @(posedge clk or posedge rst) begin if (rst) begin gate_index <= 0; point_index <= 0; frame_done <= 0; end else begin frame_done <= 0; if (write_enable) begin // 真实数据阶段 (0-499) if (point_index < REAL_POINTS) begin ram[write_addr] <= data_in; end // 自动触发补零 (500-511) else begin ram[write_addr] <= 16'b0; // 显式补零 end // 索引更新 if (point_index == TOTAL_POINTS-1) begin point_index <= 0; if (gate_index == NUM_GATES-1) begin gate_index <= 0; end else begin gate_index <= gate_index + 1; end end else begin point_index <= point_index + 1; end end end end // 输出状态机逻辑 always @(posedge clk or posedge rst) begin if (rst) begin output_state <= IDLE; out_gate <= 0; out_point <= 0; output_ready <= 0; frame_done <= 0; // 初始化输出数组 for (int g = 0; g < NUM_GATES; g++) data_out[g] <= 16'b0; end else begin output_ready <= 0; // 默认无效 case(output_state) IDLE: begin // 检测所有门数据收集完成 if (gate_index == NUM_GATES-1 && point_index == TOTAL_POINTS-1 && write_enable) begin output_state <= OUTPUT; out_gate <= 0; out_point <= 0; end end OUTPUT: begin // 更新当前门的数据 data_out[out_gate] <= ram[read_addr]; output_ready <= 1; // 索引更新 if (out_point == TOTAL_POINTS-1) begin out_point <= 0; if (out_gate == NUM_GATES-1) begin out_gate <= 0; output_state <= IDLE; frame_done <= 1; // 帧完成信号 end else begin out_gate <= out_gate + 1; end end else begin out_point <= out_point + 1; end end endcase end end endmodule仿真正确,但是综合显示synth 8-3391。我的芯片是xc7z045ffg,应该是RAM超过单个BRAM资源,那么如何修改
09-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值