FPGA——伪双端RAM极简入门

前言

本文不介绍RAM的基本概念,适用于快速上手使用RAM IP核

一、伪双端口RAM IP核配置

在这里插入图片描述
ECC(全称 Error Correcting Code,即纠错码) Options”,纠错码选项只有在伪双端口 RAM类型下才可以进行配置。
Write Enable(写使能)”:可以选择是否使用字节写使能功能,启用后可设置字节大小为 8位(无奇偶校验)或 9 位(包括奇偶校验),需要注意的是启用后内存的数据位宽必须设置为所选字节大小的整数倍。
Algorithm Options(算法选项)”:算法选项主要用于决定 BRAM 的拼接的方式,一般在BRAM 深度、宽度较大的时候起作用,有三种算法可选,分别为“Minimum Area(最小面积算法)”、“Low Power(低功耗算法)”和“Fixed Primitives(固定单元算法)”。
在这里插入图片描述
Operating Mode:RAM 运作模式。该选项决定了我们在进行写操作期间,DOUT(读数据线)上的数据变化,有三种模式可选,分别为:
①Write First(写优先模式):当我们在对某个地址进行写操作时,则会将写入的数据传递到读数据线
上。
②Read First(读优先模式):当我们在对某个地址进行写操作时,则会将上次写入该地址的数据递到读
数据线上。
③No Change(不变模式):在该模式下,进行写操作时,读数据线上的数据保持不变。
在这里插入图片描述
注意是,若勾选Primitives Output Register的话,读数据会多延迟一个时钟周期
在这里插入图片描述
在这里插入图片描述

二、IP核读写测试

1.IP核端口介绍

在这里插入图片描述

2.测试代码

`timescale 1ns / 1ps


module RAM_top(
    input clk,
    input rst,

    input data_in_flag,
    input [11:0] data_in,

    output [11:0] data_rd
    );



reg wea;
always@(posedge clk or negedge rst)
begin
	if(~rst)
		wea <= 0;
	else wea <= 1;
end


reg data_in_flag0;
reg data_in_flag1;
always @(posedge clk or negedge rst) 
begin
	if(~rst) begin
		data_in_flag0 <= 0;
		data_in_flag1 <= 0;
	end 
	else begin
		data_in_flag0 <= data_in_flag;
		data_in_flag1 <= data_in_flag0;
	end
end

wire data_in_flag_pose;
wire data_in_flag_nege;
assign data_in_flag_pose = (data_in_flag0)&(!data_in_flag1);
assign data_in_flag_nege = (!data_in_flag0)&(data_in_flag1);

reg wirte_flag;
reg read_flag;
reg read_en;
always @(posedge clk or negedge rst) 
begin 
	if(~rst) begin
		wirte_flag <= 0;
		read_flag <= 0;
		read_en <= 0;
	end 
	else if(data_in_flag_pose)begin
		wirte_flag <= 1;
		read_flag <= 0;
	end	
	else if(data_in_flag_nege)begin
		wirte_flag <= 0;
		read_flag <= 1;
		read_en <= 1;
	end
	else if(read_done)begin
		wirte_flag <= 0;
		read_flag <= 0;
	end
	else begin
		wirte_flag <= wirte_flag;
		read_flag <= read_flag;	
		read_en <= 0;	
	end

end

reg [10:0] addr;
reg read_done;
reg [10:0] addr_temp;
always @(posedge clk or negedge rst) 
begin
	if(~rst) begin
		addr <= 0;
		addr_temp <= 0;
		read_done <= 0;
	end 
	else if(data_in_flag_pose)begin
		addr <= 0;
		addr_temp <= 0;
	end
	else if(wirte_flag)begin
		addr <= addr + 1;
		addr_temp <= addr;
	end
	else if(read_en)begin
		addr <= 0;
	end
	else if(read_flag)begin
		addr <= addr + 1;
		if(addr == addr_temp)begin
			read_done <= 1;
		end
	end
	else begin
		addr <= 0;
		addr_temp <= 0;
		read_done <= 0;		
	end
end


RAM0 RAM0(
    .clka(clk),				//写时钟
    .ena(wirte_flag),		//端口a使能
    .wea(wea),				//端口a写使能
    .addra(addr),			//写地址
    .dina(data_in),			//写入数据
    .clkb(clk),				//读时钟
    .enb(read_flag),		//端口b使能
    .addrb(addr),			//读地址
    .doutb(data_rd)			//输出数据
  );


endmodule

3.测试结果

3.1写端

在这里插入图片描述
使用本算法进行伪双端RAM的操作写端的数据data_in需要延迟写信号data_in_flag两个时钟周期

3.2读端

在这里插入图片描述
读端由于没有选择输出端加一个寄存器的选项,因此输入地址,在下一个时钟周期便可以输出RAM里的数据。
由于地址125的位置没有数据写入,因此读出的为默认值0.

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值