Quartus 平台 FPGA 片内 RAM 使用

Quartus 平台 FPGA 片内 RAM 使用

本文将以 Quartus 自带的 RAM:2-PORT 为例,介绍 EP4CE6E22C8 On Chip Memory 的使用

一、在 IP Catalog 搜索 RAM

位于 On Chip Memory 下有两个 RAM IP 核
分别是单端口 RAM 和双端口 RAM:
单端口RAM只有一组地址线,这组地址线控制着写数据端口和读数据端口,
而双端口RAM具有两组地址线,这两组地址线分别控制着写数据端口和读数据端口,
双端口 RAM 可以帮助我们更容易地实现的同时读写和双缓存(个人暂时的理解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4tukskTk-1650630103345)(vx_images/246025119246922.png)]
这里双击打开 RAM:2-PORT

二、配置

(1)设置双地址线
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ZHnb4nZ-1650630103347)(vx_images/399885819239591.png)]
(2)根据需求设置 memory 大小以及数据总线宽度
在这里插入图片描述
(3)时钟线的分配
将输入输出 clock 给入不同的时钟,可以实现写入读取速度不对等的应用(个人暂时的理解
在这里插入图片描述
(4)时钟使能、异步清除功能的开关
在这里插入图片描述
(5)对相同地址同时读写时,数据输出的状态
在这里插入图片描述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5YiGEL8P-1650630103351)(vx_images/21201020244886.png)]
(6)RAM 内容初始化
在这里插入图片描述
(7)Finish 生成模块

三、读写测试 逻辑实现

(1)端口 a 作为写端口,端口 b 作为读端口
(2)一个时钟周期可以完成一次读操作或者写操作
下面代码实现的是,周期性的对同一地址写入同上一个数据 + 1 的值,然后周期性的读出该地址的数据,串口周期性的发送该数据:文章来源地址https://uudwc.com/A/Z4xWR

module FPGA_RAM (
	input clk,
	input rst_n,
	input uart_rx,
	output uart_tx
);

reg uart_send_valid;
wire uart_send_ready;

reg [31:0] counter = 32'd0;
parameter state_wait = 4'd0;
parameter state_send = 4'd1;
reg [3:0] state = state_wait;
reg [7:0] data_len = 8'd0;

always@(posedge clk_200M or negedge rst_n) begin
	if(!rst_n) begin
		uart_send_valid <= 0;
		counter <= 32'd0;
		state <= state_wait;
		data_len <= 8'd0;
	end
	else begin
		case (state)
			state_wait: begin
				counter <= counter + 32'd1;
				if(counter >= 32'd4999999) begin
					counter <= 32'd0;
					state <= state_send;
				end
			end
			state_send: begin
				if(uart_send_ready && data_len <= 8'd0) begin
					uart_send_valid <= 1;
					data_len <= data_len + 8'd1;
				end
				else begin
					uart_send_valid <= 0;
					data_len <= 8'd0;
					state <= state_wait;
				end
			end
		endcase
	end
end

uart uart0 (
	.clk_clk                 (clk_200M),                 // clk.clk
	.reset_reset_n           (rst_n),           // reset.reset_n
//	.rs232_0_from_uart_ready (<connected-to-rs232_0_from_uart_ready>), // rs232_0_avalon_data_receive_source.ready
//	.rs232_0_from_uart_data  (<connected-to-rs232_0_from_uart_data>),  // .data
//	.rs232_0_from_uart_error (<connected-to-rs232_0_from_uart_error>), // .error
//	.rs232_0_from_uart_valid (<connected-to-rs232_0_from_uart_valid>), // .valid
	.rs232_0_to_uart_data    (data_read),    //  rs232_0_avalon_data_transmit_sink.data
//	.rs232_0_to_uart_error   (<connected-to-rs232_0_to_uart_error>),   // .error
	.rs232_0_to_uart_valid   (uart_send_valid),   // .valid
	.rs232_0_to_uart_ready   (uart_send_ready),   // .ready
	.rs232_0_UART_RXD        (uart_rx),        // rs232_0_external_interface.RXD
	.rs232_0_UART_TXD        (uart_tx)         // .TXD
);

reg [7:0] data_write = 8'd00;
reg [7:0] address_write = 8'h00;
reg write_en = 0;
wire [7:0] data_read;
reg [7:0] address_read = 8'h00;
reg read_en = 0;

reg [31:0] counter_ram = 32'd0;
parameter state_ram_wait = 4'd0;
parameter state_ram_write = 4'd1;
parameter state_ram_wait_read = 4'd2;
parameter state_ram_read = 4'd3;
reg [3:0] state_ram = state_ram_wait;
reg [7:0] state_ram_delay = 8'd0;
parameter delay = 8'd0;

always@(posedge clk_200M or negedge rst_n) begin
	if(!rst_n) begin
		data_write <= 8'd0;
		write_en <= 0;
		read_en <= 0;
		counter_ram <= 32'd0;
		state_ram <= state_ram_wait;
	end
	else begin
		case (state_ram)
			state_ram_wait: begin
				counter_ram <= counter_ram + 32'd1;
				if(counter_ram >= 32'd49999999) begin
					counter_ram <= 32'd0;
					state_ram <= state_ram_write;
				end
			end
			state_ram_write: begin
				if(write_en) begin
					write_en <= 0;
					state_ram <= state_ram_wait_read;
					data_write <= data_write + 8'd1;
				end
				else begin
					write_en <= 1;
				end
			end
			state_ram_wait_read: begin
				counter_ram <= counter_ram + 32'd1;
				if(counter_ram >= 32'd49999999) begin
					counter_ram <= 32'd0;
					state_ram <= state_ram_read;
				end
			end
			state_ram_read: begin
				if(read_en) begin
					read_en <= 0;
					state_ram <= state_ram_wait;
				end
				else begin
					read_en <= 1;
				end
			end
		endcase
	end
end

ram ram0 (
	.data (data_write),
	.wraddress (address_write),
	.wren (write_en),
	.rdaddress (address_read),
	.rden (read_en),
	.clock (clk_200M),
	.q (data_read)
);

wire clk_200M;

pll pll0 (
	.inclk0 (clk),
	.c0 (clk_200M)
);

endmodule

原文地址:https://blog.csdn.net/qq_39641836/article/details/124354212

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月20日 12:01
使用Coco2d-x2.2.3版本开发水果忍者游戏环境配置
下一篇 2023年06月20日 12:03