学习汇总正点原子bi站教学视频。但由于目前的学习板PL端缺乏时钟晶振,所以需要从PS端调用时钟供给PL端使用,也就造成顶层文件的设置出现一些问题,在IP核创建调用和例化过程中一些功能会受到限制,所以以下仅作汇总参考。
zynq_7000家族中的7010和7020的ram资源如上图,每一片ram随机存储器的内存为36K,上图中的Block RAM对应的资源为多片ram拼凑起来的资源总和。其中单片ram又可以做灵活分割处理。
以下是创建RAM对应的IP核的两个步骤:
上图中标注的存储器类型分别包括单端ram(同时读写)、伪双端ram(一端读,一端写(但读写固定))、真双端ram(一端读、一端写,且读写端均可以切换读和写的功能)以及rom(关闭写的一端)等等,也可以看出ram和rom的资源是共用的。
另一幅图则涉及读写端口的设定,包括读写端口的数据宽度和深度,设置读写优先级以及端口使能的功能。
另附上顶层文件以及对应RAM的IP核的.v文件的程序:
`timescale 1ns / 1ps
// Create Date: 2024/12/31 10:31:35
// Design Name: top文件
// Module Name: test_026_ramIP
module test_026_ramIP(
input sys_clk,
input sys_rst_n
);
wire ram_en;
wire rw;
wire [4:0] ram_addr;
wire [7:0] ram_w_data;
wire [7:0] douta; //设置为线型避免输出端创建需要分配8个引脚
//lihua,IP核调用,ram读写控制
ram_IP_rw ram_IP_rw_u(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.ram_en (ram_en),
.rw (rw),
.ram_addr (ram_addr),
.ram_w_data (ram_w_data)
);
//lihua,IP核调用
ramIP_1 ramIP_1_u (
.clka(sys_clk), // input wire clka
.ena(ram_en), // input wire ena
.wea(rw), // input wire [0 : 0] wea
.addra(ram_addr), // input wire [4 : 0] addra
.dina(ram_w_data), // input wire [7 : 0] dina
.douta(douta) // output wire [7 : 0] douta
);
endmodule
//ram IP核读写控制
module ram_IP_rw(
input sys_clk,
input sys_rst_n,
output reg ram_en,
output reg rw,
output reg [4:0] ram_addr,
output reg [7:0] ram_w_data
);
//使能设置
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
ram_en <= 1'b0;
else
ram_en <= 1'b1;
end
reg [5:0] rw_cnt; //读写切换计数器
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rw_cnt <= 6'b0;
else if(rw_cnt == 6'd63)
rw_cnt <= 6'b0;
else
rw_cnt <= rw_cnt + 6'd1;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
ram_w_data <= 8'b0;
else if((rw_cnt >= 6'd31) && ram_en)
ram_w_data <= ram_w_data + 8'b1;
else
ram_w_data <= ram_w_data;
end
//读写切换:
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rw <= 1'b1;//初始默认为高,也就是写状态
else if(rw_cnt >= 6'd31)
rw <= 1'b1;
else
rw <= 1'b0;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
ram_addr <= 5'd0;
else
ram_addr <= rw_cnt[4:0]; //位宽设定,前31位读写
end
endmodule
示意图如下: