RAM简介:
RAM(Random Access Memory),即随机存取存储器。它是双端口的,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。
一片RAM中分为许多小格,每一片容量为36k,根据设定的位宽决定了这片RAM可以存放分为几格,位宽一啊不能设定为1、2、4、8、16、32等,每相邻的两片RAM可以合成一片RAM,这片RAM同样是双端口,可以独立的完成读写操作,且在读和写都可以配置位宽。
- 单端口:只有一个端口,读写数据不能同时进行,共用数据通道。
- 伪双端口:拥有两个数据通道,一个用来写一个用来读。
- 真双端口:拥有两个数据通道,两个通道都可以用来读或写。
建立工程:
1、打开vivado,选择add sources->add or creat a new sources名称为ip_ram->finish即可。
2、添加ram ip,ip catalog-> 搜索ram选择block memory generate(bram),双击打开配置界面,配置如下图,配置成单端口、写位宽和读位宽为8,写深度和读深度便会自动配置,operating mode既可以设置成write frist也可以no change,这个设置项的影响是在读和写数据时的优先级。
3、在添加一个文件,用于描述在读和写的过程,文件名取为ram_rw,代码如下:
module ram_rw(
input clk,
input rst,
output reg ram_en,
output reg rw,
output reg [4:0] ram_addr,
output reg [7:0] ram_wr_data
);
reg [5:0] rw_cnt;
always@(posedge clk or negedge rst)begin
if(rst)
ram_en<=1'b0;
else
ram_en<=1'b1;
end
//rw_cnt
always @(posedge clk or posedge rst) begin
if (rst) begin
rw_cnt <= 6'd0;
end
else if (rw_cnt == 6'd63) begin
rw_cnt <= 6'd0;
end
else begin
rw_cnt <= rw_cnt + 6'd1;
end
end
//ram_wr_data
always @(posedge clk or posedge rst) begin
if (rst) begin
ram_wr_data <= 8'd0;
end
else if ((rw_cnt <= 6'd31) && ram_en == 1'b1) begin
ram_wr_data <= ram_wr_data + 8'd1;
end
else begin
ram_wr_data <= ram_wr_data;
end
end
//rw
always @(posedge clk or posedge rst) begin
if (rst) begin
rw <= 1'b1;
end
else if (rw_cnt <= 6'd31) begin
rw <= 1'b1;
end
else begin
rw <= 1'b0;
end
end
//ram_addr
always @(posedge clk or posedge rst) begin
if (rst) begin
ram_addr <= 5'd0;
end
else begin
ram_addr <= rw_cnt[4:0];
end
end
endmodule
4、编辑ip_ram代码:
根据ip sources中的ip选项中选择instantiation template(例化模板),选择veo文件,复制其例化模板粘贴至ip_ram中,并手动例化ram_rw中的代码块,并定义了系统时钟和复位。
5、添加ILA IP
添加ila ip用来探测信号,同样的操作在ip catalog中搜索ila双击打开配置界面,因为要探测五个信号:ram使能信号、读写操作信号、ram地址信号、ram读写数据信号、最后输出的信号douta。所以number of probes 探针的数量为5,在每个探针的位宽中配置相对应的数据位宽。同样的在ip sources中的veo文件拷贝ila的例化模板,粘贴到顶层模块ip_ram的代码中,最终其代码如下:
module ip_ram(
input sys_clk,
input sys_rst
);
wire ram_en;
wire rw;
wire [4:0] ram_addr;
wire [7:0] ram_wr_data;
wire [7:0] douta;
ram_rw ram_rw_u(
.clk (sys_clk),
.rst (sys_rst),
.ram_en (ram_en),
.rw (rw),
.ram_addr (ram_addr),
.ram_wr_data(ram_wr_data)
);
blk_mem_gen_0 blk_mem_gen_0_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_wr_data), // input wire [7 : 0] dina
.douta(douta) // output wire [7 : 0] douta
);
ila_0 your_instance_name (
.clk(sys_clk), // input wire clk
.probe0(ram_en), // input wire [0:0] probe0
.probe1(rw), // input wire [0:0] probe1
.probe2(ram_addr), // input wire [4:0] probe2
.probe3(ram_wr_data), // input wire [7:0] probe3
.probe4(douta) // input wire [7:0] probe4
);
endmodule
6、综合文件:
点击run synthesis进行综合,综合完成后可点击open synthesis design查看相应的框架图如下:
7、绑定管脚并生成bitstream
本实验只用到了PL端的资源,因此需要对引脚进行绑定,只需要绑定两个管脚:时钟和复位,在Layout中选择i/o planing即可对引脚进行配置,在zedboard原理图可以查阅GCLK可以看出时钟的管脚为Y9,而PL端的复位按键集成在了BTNL中,因此查阅可知其管脚为N15,两个管脚的电压均为lvcmos3.3v,ctrl+s保存对约束文件命名为ip_ram即可自动生成约束文件。最后generate bitstream即可。
8、连接板子:
连接开发板并上电,点击open target->auto connect->program device再点击启动即可看到通过ila探测到的信号,通过看时序图即可验证设计是否正确。
|