libero Simulate - ModelSim ME (三) 实战测试 双端口 RAM 读写

 

libero Simulate - ModelSim ME (一) 新建工程 - 所长 - 博客园

libero Simulate - ModelSim ME (二) 语法分析 - 所长 - 博客园

libero Simulate - ModelSim ME (三) 实战测试 双端口 RAM 读写

 

RAM 测试 和 之前的工程有区别的地方,不用新建工程 ,直接 在 libero 直接跳转到 仿真界面, 下面方法:

image

 

 

 

1、 IP 版本, RAM -Dual Port v2.2

image

 2、IP 参数配置, 单位 8bit , 一个字节, 深度 512 ,表示 512字节的 RAM ,  双端口 公用一个时钟  , 使能 仿真初始化 RAM 接口

 

  • Pass-Through:写数据直接绕过存储阵列、立即出现在 DOUT(同周期),保证数据一致性、无旧数据残留
  • Pass-Through:无输出寄存器、纯组合直通,地址 / 使能在时钟沿锁存后,数据经存储阵列直接输出,1 个时钟周期出数、零额外寄存器延迟
  • Pipelined:写数据先到阵列、再经输出寄存器,第 2 个时钟周期才出最新写数据
  • Pipelined:2 个时钟周期出数、多 1 级寄存器延迟,但可跑更高频率、时序更稳
  • Previous DOUT:勾选,WMODE = 0 → RAM Write, Output Retained(输出保持模式);
  • WMODE = 0 :写操作期间,DOUT 保持上一次读操作的有效数据,不更新为当前写入的 DIN 数据,双端口同时读写同一地址,需要避免写数据干扰读输出、保持读数据稳定
  • Previous DOUT:不勾选,WMODE = 1 → Write Pass-Through(写直通模式)
  • WMODE = 1 :写操作时,写入的 DIN 数据直接绕过存储阵列、立即出现在 DOUT(同周期更新),需写后立即读新数据、数据一致性要求高(如 FIFO、缓存、实时更新)
  • 以上内容来自豆包

image

 上图 我选择了  Pipelined   Previous DOUT , 写入和输出

 

image

 

官方手册里的读写时序图 Military ProASIC3/EL Low-Power Flash FPGAs Datasheet

 Pipelined:读时序

image

  Previous DOUT勾选, WMODE = 0:写时序

image

 

 复位时序:

image

 A3P250 最快读写速度:

image

 A3P250  tAS 地址,使能,blk 建立时间;

image

 

编写 测试文件 步骤:

  1、设置 时钟基准 

parameter SYSCLK_PERIOD = 100;// 10MHZ
 
// 定义 时钟信号和复位信号
reg SYSCLK;
reg NSYSRESET;
 
  2、产生时钟信号
always @(SYSCLK) begin
    #(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;
end
  3、产生复位信号
initial
begin
    #(SYSCLK_PERIOD * 10 )
        NSYSRESET = 1'b1;
end

 

3、 例化  RAM 模块 

 

4、 编写 RAM 写入 时序 

5、编写 RAM 读取时序 

 

开始仿真:

image

 

读取端口使能,地址设为1 ,  写入地址设为1 ,  写入端口使能和写入数据0x78. 下个时钟周期 写入端口 使能关闭, 再过2个时钟周期后, 端口B 输出数据

 

 

///////////////////////////////////////////////////////////////////////////////////////////////////
// Company: <Name>
//
// File: testbench_ram.v
// File history:
//      <Revision number>: <Date>: <Comments>
//      <Revision number>: <Date>: <Comments>
//      <Revision number>: <Date>: <Comments>
//
// Description: 
//
// <Description here>
//
// Targeted device: <Family::ProASIC3> <Die::A3P1000> <Package::144 FBGA>
// Author: <Name>
//
/////////////////////////////////////////////////////////////////////////////////////////////////// 

`timescale 1ns/100ps

module testbench_ram();

// 设置时钟基准
parameter SYSCLK_PERIOD = 100;// 10MHZ

// 定义 时钟信号和复位信号
reg SYSCLK;
reg NSYSRESET;

initial
begin
    SYSCLK = 1'b0;
    NSYSRESET = 1'b0;
end

//////////////////////////////////////////////////////////////////////
// Reset Pulse
//////////////////////////////////////////////////////////////////////
initial
begin
    #(SYSCLK_PERIOD * 1 )
        NSYSRESET = 1'b1;
end


//////////////////////////////////////////////////////////////////////
// Clock Driver
//////////////////////////////////////////////////////////////////////
always @(SYSCLK) begin
    #(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;
end

// sysclk 计数 方便观察时序
reg [31:0] clk_cnt;
always @(posedge SYSCLK or negedge NSYSRESET) begin
    if( !NSYSRESET ) begin
        clk_cnt <= 32'b0;
    end else begin
        clk_cnt <= clk_cnt + 32'b1;
    end
end

// RAM 读使能 对应 RW信号 高电平
parameter RAM_RW_READ_ENABLE  = 1'b1;
// RAM 写使能 对应 RW信号 低电平
parameter RAM_RW_WRITE_ENABLE = 1'b0;
// BLK 信号使能
parameter RAM_BLK_ENABLE  = 1'b0;
parameter RAM_BLK_DISABLE = 1'b1;

// 例化 双端口 模块
reg [8:0]  ram_addr_a;
reg [8:0]  ram_addr_b;
reg        ram_blk_a;
reg        ram_blk_b;
reg [7:0]  ram_din_a;
//wire [7:0] ram_dout_a;
wire [7:0] ram_dout_b;

ram_buff ram_0(
    // 512字节 读写同时钟 双端口 RAM
    .ADDRA(ram_addr_a),
    .ADDRB(ram_addr_b),
    .BLKA(ram_blk_a),
    .BLKB(ram_blk_b),
    .CLKAB(SYSCLK),
    .DINA(ram_din_a),
    .DINB(8'd0),
    .RESET(NSYSRESET),
    .RWA(RAM_RW_WRITE_ENABLE),
    .RWB(RAM_RW_READ_ENABLE),
    // Outputs
 //   .DOUTA(ram_dout_a),
    .DOUTB(ram_dout_b)
);

// 将 0x12345678 按顺序 写入 RAM
// 写完成 读取 RAM
reg [7:0] byte1 = 8'h78;
reg [7:0] byte2 = 8'h56;
reg [7:0] byte3 = 8'h34;
reg [7:0] byte4 = 8'h12;

reg [8:0] w_cnt = 0;
reg write_done = 0;

// 将数据写入到 RAM 中
always @(posedge SYSCLK or negedge NSYSRESET) begin
    if( !NSYSRESET ) begin
        w_cnt <= 9'b0;
        ram_blk_a <= RAM_BLK_DISABLE;
        ram_addr_a <= 9'b0;
        write_done <= 1'b0;
    end else begin
        
        if(w_cnt<4) begin
            w_cnt <= w_cnt + 9'b1;
            write_done <= 1'b0;
            ram_blk_a <= RAM_BLK_ENABLE;
            ram_addr_a <= w_cnt;
            case(w_cnt)
                0: ram_din_a <= byte1;
                1: ram_din_a <= byte2;
                2: ram_din_a <= byte3;
                3: ram_din_a <= byte4;
                default: ram_din_a <= 8'b0;
            endcase
        end else begin
            ram_blk_a <= RAM_BLK_DISABLE;
            write_done <= 1'b1;
            // w_cnt <= 9'b0; // 写完成后不再写入数据
        end
    end
end

// 读取 RAM 中的数据
// 读取 RAM 会延迟2个时钟周期
reg [8:0] r_cnt = 0;
reg [2:0] fsm_read;
parameter FSM_READ_IDLE    = 3'd0;
parameter FSM_READ_START   = 3'd1;
parameter FSM_READ_DONE    = 3'd2;

always @(posedge SYSCLK or negedge NSYSRESET) begin
    if( !NSYSRESET ) begin
        r_cnt <= 9'b0;
        ram_blk_b <= RAM_BLK_DISABLE;
        ram_addr_b <= 9'b0;
        fsm_read <= FSM_READ_IDLE;
    end else begin
        case(fsm_read)
            FSM_READ_IDLE: begin
                ram_blk_b <= RAM_BLK_DISABLE;
                if(write_done) begin
                    fsm_read <= FSM_READ_START;
                end
            end
            FSM_READ_START: begin
                if(r_cnt < 4) begin
                    ram_blk_b <= RAM_BLK_ENABLE;
                    ram_addr_b <= r_cnt;
                    r_cnt <= r_cnt + 9'b1;
                end else begin
                    fsm_read <= FSM_READ_DONE;
                end
            end
            FSM_READ_DONE: begin
                // 延迟两个时钟 关闭 BLK 信号
                // 采用 WMODE = 0模式,输出数据要延迟2个时钟
                fsm_read <= FSM_READ_IDLE;
            end
        endcase

    end
end

endmodule

 

image

 

 总结: 通过时序仿真:

    1、 写数据直接 blk_a拉低使能后,直接给地址和数据,就将数据写入到了对应地址中,   

    2、读数据 需要 blk_b 拉低后,给出地址后, 需要延迟 2个时钟周期 才能 流水线式 给出数据 。

 

 

 

posted on 2026-04-17 11:31  所长  阅读(8)  评论(0)    收藏  举报

导航