IP核RAM调用及验证(1)

前言

        随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。它与ROM的最大区别是数据的易失性,即一旦断电所存储的数据将随之丢失。RAM在计算机和数字系统中用来暂时存储程序、数据和中间结果。

       本章节将练习如何使用FPGA设计并使用RAM。         

正文

一、IP核ram调用及验证

        1.项目需求

        ram称为随机存储器,能够控制往里面写入数据,也可以控制将里面写入的数据读取出来,对于一个存储位置,在写入时可以一直覆盖写入,能够控制读取的数据最多只有两个。可以随时随地更新存储的数据,也可以随时随地将写入的数据读取出来;ram也分为单端口ram和双端口ram,单端口ram可以用来对数据进行缓存,数据在写入和读取时需要在同一个时钟域下;双端口主要应用在跨时钟域下的数据信号出来。

        2.技术介绍

        在写入时需要根据写地址控制数据写入到该地址上,地址和数据需要保持同拍,在同一个时钟周期下,同时也需要写使能信号wren进行控制写入。在读取时需要根据读地址读取当前地址上的数据,在对读使能信号rden没有进行设置时,默认读使能信号一直有效。

       单端口ram只有一个地址变量,那么地址变量就包含两层含义:写地址含义,读地址含义;在写使能和读使能同时有效时,地址变量既是写地址,同时也表示读地址。将Ip核rom中的数据写入到单端口ram中,并全部读取出来,在写入时不进行数据的读取。

调用单端口RAM,配置总线宽度8,数据深度256

添加读使能信号,后面设置保持默认

生成inst.v文件

        3.顶层架构

        这里调用rom将rom中数据写入到ram中,并通过ram读出数据。

        4.端口描述

clk时钟(50Mhz)
rst_n复位按键(低电平有效)
[7:0] data数据读出

二、代码验证

        wr_ram_ctrl模块:,读取rom数据,写入到RAM中,读取RAM中的数据

module wr_ram_ctrl(

	input clk,
	input rst_n,
	input [7:0] data,//从rom读取的数据
	
	output reg [7:0] addr,//写/读RAM的地址
	output  [7:0] rom_addr,//传递给rom的地址
	output reg wren,//写使能信号
	output  rden,//读使能信号
	output [7:0] wr_data//写入RAM的数据
);

reg en;
reg [7:0] cnt;

assign wr_data = data;//写入RAM的数据=从rom读取的数据

assign rden = ~wren;//读完写,写完读,什么时候读完?

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		begin
			en <= 1'b1;
			cnt <= 8'd0;
		end
	else
		if(cnt == 255)//0~255,读/写到第255位数据时,rom的数据读/写完
			begin
				en <= ~en;
				cnt <= 8'd0;
			end 
		else
			begin
				en <= en;
				cnt <= cnt + 8'd1;
			end 
end 

assign rom_addr = (en == 1)?cnt:8'd0;//传递给rom的地址,组合逻辑赋值,立即传递
 
reg wren_r;
wire pos_flag;
wire neg_flag;
always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		begin
			wren <= 1'b1;
			wren_r <= 1'b1;
		end 
	else
		begin
			wren <= en;/en为写信号
			wren_r <= wren;
		end 
end 

assign pos_flag = ~wren_r & wren;

assign neg_flag = ~wren & wren_r;

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		addr <= 8'd0;
	else
		addr <= cnt;//读/写ram的地址与读rom的地址相同,
//但是赋值的更新是在时钟边沿之后的一个时钟周期内发生的
end 

endmodule 

        ram_test模块:顶层连线

module ram_test(

	input clk,
	input rst_n,
	
	output [7:0] data
);

wire wren;
wire rden;
wire [7:0] addr;
wire [7:0] wr_data;
wire [7:0] rom_addr;
wire [7:0] rom_data;

wr_ram_ctrl wr_ram_ctrl_inst(

	.clk(clk),
	.rst_n(rst_n),
	.data(rom_data),
	
	.addr(addr),
	.rom_addr(rom_addr),
	.wren(wren),
	.rden(rden),
	.wr_data(wr_data)
);

my_rom	my_rom_inst (
	.address ( rom_addr ),
	.clock ( clk ),
	.q ( rom_data )
	);


single_ram	single_ram_inst (
	.address ( addr ),
	.clock ( clk ),
	.data ( wr_data ),
	.rden ( rden ),
	.wren ( wren ),
	.q ( data )
	);
	
endmodule 

仿真代码

`timescale 1ns/1ps
module ram_test_tb;

	reg clk;
	reg rst_n;
	
	wire [7:0] data;

double_ram_test ram_test_inst(

			.clk(clk),
			.rst_n(rst_n),
			
			.data(data)
);

initial clk = 1;
always #10 clk = ~clk;

initial begin
	rst_n = 0;
	#200
	rst_n = 1;
	#10000
	$stop;
end 

endmodule 

三、仿真验证

        数据都可正常读出,下面验证数据是否正确

ROM的数据读取会延迟地址一个时钟

读出的数据在同一时钟下写入到RAM中,

当cnt记到255时,即写地址到255时,数据从ROM中读完,RAM中写完

大多数RAM IP核,特别是同步RAM IP核,设计时会考虑时钟边沿对数据稳定性的要求。为了确保数据读取操作的稳定性,RAM通常会在读取操作时引入延迟。这个延迟通常表现为两个时钟周期:

        第一个时钟周期:地址和读信号被传递到RAM。在这一周期内,RAM完成地址的解码,并开始内部读取操作。

        第二个时钟周期:在地址稳定的情况下,RAM内部完成数据准备并将数据输出到数据总线。这通常意味着数据将在下一个时钟周期变为有效。

读出地址到255后,数据从RAM读完毕,由于RAM的特性,数据需要延后2个时钟才能完全读出,读完毕后立刻进入写模式。

参考资料

随机存取存储器

Altera系列FPGA芯片IP核详解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

张明阳.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值