单端口RAM IP核

单端口RAM IP核

RAM

RAM(Random Access Memory ):即随机访问存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。

RAM的分类

单端口RAM IP核端口

DINA:数据写入端口

ADDRA:数据写入对应地址

WEA:读写控制信号

ENA:使能端口,高电平有效

RSTA:复位端口

REGCEA:寄存器使能端口

CLKA:时钟

DOUTA:读出数据

实验任务

使用Vivado软件生成一个单端口的RAM并对其进行读写操作,然后通过仿真观察波形是否正确,最后通过在线调试工具对实验结果进行验证。如:将RAM设置的深度和宽度分别为32和8进行读写测试。

系统框图

波形图
IP核配置


ram_rw读写模块代码

复制代码
module ram_rw(
    input               clk        ,  //时钟信号
    input               rst_n      ,  //复位信号,低电平有效
    
    output  reg         ram_en     ,  //ram使能信号
    output              ram_we     ,  //ram读写选择
    output  reg  [4:0]  ram_addr   ,  //ram读写地址
    output  reg  [7:0]  ram_wr_data,  //ram写数据
    input        [7:0]  ram_rd_data   //ram读数据        
    );

//reg define
reg    [5:0]  rw_cnt ;                //读写控制计数器

//*****************************************************
//**                    main code
//*****************************************************

//rw_cnt计数范围在0~31,写入数据;32~63时,读出数据
assign ram_we = (rw_cnt <= 6'd31 && ram_en == 1'b1) ? 1'b1 : 1'b0;

//控制RAM使能信号
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_en <= 1'b0;    
    else
        ram_en <= 1'b1;    
end 

//读写控制计数器,计数器范围0~63
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        rw_cnt <= 6'b0;    
    else if(rw_cnt == 6'd63  && ram_en)
        rw_cnt <= 6'b0;
    else if(ram_en)
        rw_cnt <= rw_cnt + 1'b1; 
    else
        rw_cnt <= 6'b0;      
end  

//读写地址信号 范围:0~31
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_addr <= 5'b0;
    else if(ram_addr == 5'd31 && ram_en)
        ram_addr <= 5'b0;
    else if (ram_en)   
        ram_addr <= ram_addr + 1'b1;
    else
        ram_addr <= 5'b0;         
end

//在WE拉高期间产生RAM写数据,变化范围是0~31
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_wr_data <= 8'b0;  
    else if(ram_wr_data < 8'd31 && ram_we)
        ram_wr_data <= ram_wr_data + 1'b1;
    else
        ram_wr_data <= 8'b0 ;   
end  

ila_0 u_ila_0 (
    .clk(clk),           // input wire clk

    .probe0(ram_en),     // input wire [0:0]  probe0  
    .probe1(ram_we),     // input wire [0:0]  probe1 
    .probe2(ram_addr),   // input wire [4:0]  probe2 
    .probe3(ram_wr_data),// input wire [7:0]  probe3 
    .probe4(ram_rd_data) // input wire [7:0]  probe4 
);

endmodule

顶层模块代码,例化ram_rw模块和IP核

复制代码
module ram_rw(
    input               clk        ,  //时钟信号
    input               rst_n      ,  //复位信号,低电平有效
    
    output  reg         ram_en     ,  //ram使能信号
    output              ram_we     ,  //ram读写选择
    output  reg  [4:0]  ram_addr   ,  //ram读写地址
    output  reg  [7:0]  ram_wr_data,  //ram写数据
    input        [7:0]  ram_rd_data   //ram读数据        
    );

//reg define
reg    [5:0]  rw_cnt ;                //读写控制计数器

//*****************************************************
//**                    main code
//*****************************************************

//rw_cnt计数范围在0~31,写入数据;32~63时,读出数据
assign ram_we = (rw_cnt <= 6'd31 && ram_en == 1'b1) ? 1'b1 : 1'b0;

//控制RAM使能信号
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_en <= 1'b0;    
    else
        ram_en <= 1'b1;    
end 

//读写控制计数器,计数器范围0~63
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        rw_cnt <= 6'b0;    
    else if(rw_cnt == 6'd63  && ram_en)
        rw_cnt <= 6'b0;
    else if(ram_en)
        rw_cnt <= rw_cnt + 1'b1; 
    else
        rw_cnt <= 6'b0;      
end  

//读写地址信号 范围:0~31
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_addr <= 5'b0;
    else if(ram_addr == 5'd31 && ram_en)
        ram_addr <= 5'b0;
    else if (ram_en)   
        ram_addr <= ram_addr + 1'b1;
    else
        ram_addr <= 5'b0;         
end

//在WE拉高期间产生RAM写数据,变化范围是0~31
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_wr_data <= 8'b0;  
    else if(ram_wr_data < 8'd31 && ram_we)
        ram_wr_data <= ram_wr_data + 1'b1;
    else
        ram_wr_data <= 8'b0 ;   
end  

ila_0 u_ila_0 (
    .clk(clk),           // input wire clk

    .probe0(ram_en),     // input wire [0:0]  probe0  
    .probe1(ram_we),     // input wire [0:0]  probe1 
    .probe2(ram_addr),   // input wire [4:0]  probe2 
    .probe3(ram_wr_data),// input wire [7:0]  probe3 
    .probe4(ram_rd_data) // input wire [7:0]  probe4 
);

endmodule

FPGA激励文件(Testbench)编写,其用于验证FPGA设计功能正确性的测试脚本,通过模拟输入信号并检查输出响应,确保设计符合预期。

复制代码
`timescale 1ns / 1ps        //仿真单位/仿真精度

module tb_ip_1port_ram();

//parameter define
parameter  CLK_PERIOD = 20; //时钟周期 20ns

//reg define
reg     sys_clk;
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_1port_ram u_ip_1port_ram(
    .sys_clk          (sys_clk        ),
    .sys_rst_n        (sys_rst_n      ) 
    );

endmodule
相关推荐
stay_cloud16 小时前
HDMI字符显示 —— 基于Genesys2
fpga·hdmi·genesys2
zhongxon2 天前
ORIN+FPGA高速采集AI智能处理板
无人机·rk3588·fpga·orin·orin+fpga·cameralink·coaxpress
XINVRY-FPGA6 天前
XCVP1802-2MSILSVC4072 AMD Xilinx Versal Premium Adaptive SoC FPGA
人工智能·嵌入式硬件·fpga开发·数据挖掘·云计算·硬件工程·fpga
9527华安6 天前
国产安路FPGA开发设计培训课程,提供开发板+工程源码+视频教程+技术支持
fpga开发·fpga·安路·视频教程·培训·安路fpga
brave and determined7 天前
可编程逻辑器件学习(day36):从沙粒到智能核心:芯片设计、制造与封装的万字全景解析
fpga开发·制造·verilog·fpga·芯片设计·硬件设计·芯片制造
XINVRY-FPGA8 天前
XCVU9P-2FLGC2104I Xilinx AMD Virtex UltraScale+ FPGA
嵌入式硬件·机器学习·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
brave and determined9 天前
可编程逻辑器件学习(day34):半导体编年史:从法拉第的意外发现到塑造现代文明的硅基浪潮
人工智能·深度学习·fpga开发·verilog·fpga·设计规范·嵌入式设计
stay_cloud9 天前
《Verilog语言与FPGA实现》课程实验
verilog·fpga·数码管
brave and determined10 天前
可编程逻辑器件学习(day30):数字电路设计中的流水线技术:原理、实现与优化
学习·fpga开发·verilog·fpga·数字电路·硬件设计·嵌入式设计
brave and determined11 天前
可编程逻辑器件学习(day29):Verilog HDL可综合代码设计规范与实践指南
深度学习·fpga开发·verilog·fpga·设计规范·硬件编程·嵌入式设计