FPGA开发实验(6)- IP核之双端口RAM实验

一、双端口RAN简介与实验任务

1.1双端口RAM

简单双端口 RAM 的端口 A 只能写不能读,端口 B 只能读不能写。
与单端口不同的是,伪双端口RAM有两路时钟信号CLKA/CLKB。两个独立的地址ADDRA和ADDRB;PortA提供数据总线,PortB提供数据总线。

1.2实验任务

本章实验任务是将 Xilinx BMG IP 核配置成一个同步的伪双端口 RAM 并对其进行读写操作,然后通过仿真观察波形是否正确,最后将设计下载到 FPGA 开发板中,并通过在线调试工具对实验结果进行观察。

二、程序设计

2.1RAM IP核的配置
“Basic”选项卡配置界面如下图所示。
在这里插入图片描述
对“Port A Options”和“Port B Options”选项卡进行配置,如下图所示:
在这里插入图片描述在这里插入图片描述

2.2 模块的设计

总体模块框图如下图所示:
在这里插入图片描述
RTL代码ip_2port_ram.v如下:

module ip_2port_ram(
    input sys_clk   ,
    input sys_rst_n
);

wire rd_flag;
wire ram_rd_en;
wire [5:0] ram_rd_addr;
wire [7:0] ram_rd_data;
wire ram_wr_en;
wire ram_wr_we;
wire [5:0] ram_wr_addr;
wire [7:0] ram_wr_data;

ram_rd u_ram_rd(
    .clk        (sys_clk),
    .rst_n      (sys_rst_n),
    .rd_flag    (rd_flag),
    .ram_rd_en  (ram_rd_en),
    .ram_rd_addr(ram_rd_addr),
    .ram_rd_data(ram_rd_data)
);

ram_wr u_ram_wr( 
    .clk        (sys_clk),
    .rst_n      (sys_rst_n),
    .rd_flag    (rd_flag),
    .ram_wr_en  (ram_wr_en),
    .ram_wr_we  (ram_wr_we),
    .ram_wr_addr(ram_wr_addr),
    .ram_wr_data(ram_wr_data)
);

blk_mem_gen_0 your_instance_name (
  .clka(sys_clk),    // input wire clka
  .ena(ram_wr_en),      // input wire ena
  .wea(ram_wr_we),      // input wire [0 : 0] wea
  .addra(ram_wr_addr),  // input wire [5 : 0] addra
  .dina(ram_wr_data),    // input wire [7 : 0] dina
  .clkb(sys_clk),    // input wire clkb
  .enb(ram_rd_en),      // input wire enb
  .addrb(ram_rd_addr),  // input wire [5 : 0] addrb
  .doutb(ram_rd_data)  // output wire [7 : 0] doutb
);

endmodule

写数据模块框图如下图:
在这里插入图片描述
RTL代码ram_wr.v如下

module ram_wr(
    input clk   ,
    input rst_n ,
    
    output reg rd_flag,
    output reg ram_wr_en,
    output ram_wr_we,
    output reg [5:0] ram_wr_addr,
    output reg [7:0] ram_wr_data
);

assign ram_wr_we = ram_wr_en;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin 
        ram_wr_en <= 1'b0;
    end
    else begin
        ram_wr_en <= 1'b1;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        ram_wr_addr <= 6'd0;
    else if(ram_wr_addr == 6'd63 && ram_wr_en)
        ram_wr_addr <= 6'd0;
    else if(ram_wr_en)
        ram_wr_addr <= ram_wr_addr + 6'b1;
    else 
        ram_wr_addr <= ram_wr_addr;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        rd_flag <= 1'b0;
    else if(ram_wr_addr == 6'd32)
        rd_flag <= 1'b1;
    else
        rd_flag <= rd_flag;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        ram_wr_data <= 8'd0;
    else if(ram_wr_data >= 8'd200 && ram_wr_en)
        ram_wr_data <= 8'd0;
    else if(ram_wr_en)
        ram_wr_data <= ram_wr_data + 8'd2;
    else    
        ram_wr_data <= ram_wr_data;
end
endmodule

读数据模块框图如下图:
在这里插入图片描述
RTL代码ram_rd.v如下:

module ram_rd(
    input clk   ,
    input rst_n ,
    input rd_flag,
    
    output ram_rd_en,
    output reg [5:0] ram_rd_addr,
    input [7:0] ram_rd_data
);

assign ram_rd_en = rd_flag;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        ram_rd_addr <= 6'd0;
    else if(ram_rd_addr == 6'd63 && rd_flag)
        ram_rd_addr <= 6'd0;
    else if(rd_flag)
        ram_rd_addr <= ram_rd_addr + 6'd1;
    else
        ram_rd_addr <= ram_rd_addr;
end 

endmodule

2.3 通过Vivado 自带仿真器仿真

仿真代码:

`timescale 1ns/1ps

module tb_ip_2port_ram();

parameter CLK_PERIOD = 20;

reg sys_clk; //周期20ns
reg sys_rst_n;


initial begin
    sys_clk <= 1'b0;
    sys_rst_n <= 1'b0;
    #200 
    sys_rst_n <= 1'b1;
end

always #(CLK_PERIOD/2) sys_clk = ~sys_clk;


ip_2port_ram u_ip_2port_ram(
    .sys_clk    (sys_clk),
    .sys_rst_n  (sys_rst_n)
);

endmodule

仿真结果:
在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HQAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值