赞
踩
Xilinx7系列器件的存储器资源是由一系列存储器模块组成的。通过对这些BRAM进行配置,就可以实现各种存储器的功能,如RAM,ROM,FIFO以及移位存储器。
Vivado自带了BMG IP核,可配置成RAM或ROM。RAM是一种随机存取存储器,不仅可以存储数据,而且可以对存储的数据进行修改。而ROM是只读的,正常工作时只能读出数据而不能写数据。(因为不能写数据,所以ROM需要导入初始值)
配置成RAM:
分为真双端口RAM(两个端口都可以用来读/写)、伪双端口RAM(两个端口只能一个读一个写)和单端口RAM(只有一个端口,可以读/写)。单端口RAM只有一组数据总线、地址总线和其他控制信号,双端口就有两组。
各个端口功能描述:
DINA:RAM端口 A写数据信号。
ADDRA:RAM端口 A读写地址信号,对于单端口 RAM来说,读地址和写地址共用同该地址线。
WEA:RAM端口 A写使能信号,高电平表示向 RAM中写入数据,低电平表示从 RAM中读出数据。
ENA:端口 A的使能信号,高电平表示使能端口 A,低电平表示端口 A被禁止,禁止后端口 A上的读写操作都会变成无效。另外 ENA信号是可选的,当取消该使能信号后, RAM会一直处于有效状态。
RSTA:RAM端口 A复位信号,可配置成高电平或者低电平复位,该复位信号是一个可选信号。
REGCEA:RAM端口 A输出寄存器使能信号,当 REGCEA为高电平时, DOUTA保持最后一次输出的数据, REGCEA同样是一个可选信号。
CLKA :RAM端口 A的时钟信号。
DOUTA :RAM端口 A读出的数据。
实验任务:配置成单端口RAM,完成读写RAM的操作,并执行行为仿真。
硬件设计:输入端口只有系统时钟和系统复位。
具体配置思维导图如上。
注意:ram_rw模块设置了读/写什么,读/写进去哪里,也就是数据和地址。
ram_rw.v
module ram_rw( input clk , //时钟信号 input rst_n , //复位信号,低电平有效 output ram_en , //ram使能信号 output ram_wea , //ram读写选择 output reg [4:0] ram_addr , //ram读写地址 output reg [7:0] ram_wr_data, //ram写数据 input [7:0] ram_rd_data //ram读数据 ); //reg define reg [5:0] rw_cnt ; //读写控制计数器 //***************************************************** //** main code //***************************************************** //控制RAM使能信号 assign ram_en = rst_n; //rw_cnt计数范围在0~31,写入数据;32~63时,读出数据 assign ram_wea = (rw_cnt <= 6'd31 && ram_en == 1'b1) ? 1'b1 : 1'b0; //读写控制计数器,计数器范围0~63 always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) rw_cnt <= 1'b0; else if(rw_cnt == 6'd63) rw_cnt <= 1'b0; else rw_cnt <= rw_cnt + 1'b1; end //产生RAM写数据 always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_wr_data <= 1'b0; else if(rw_cnt <= 6'd31) //在计数器的0-31范围内,RAM写地址累加 ram_wr_data <= ram_wr_data + 1'b1; else ram_wr_data <= 1'b0 ; end //读写地址信号 范围:0~31 always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_addr <= 1'b0; else if(ram_addr == 5'd31) ram_addr <= 1'b0; else ram_addr <= ram_addr + 1'b1; end endmodule
此模块主要涉及到计数器的应用,较为简单。
顶层模块ip_ram.v
module ip_ram( input sys_clk , //系统时钟 input sys_rst_n //系统复位,低电平有效 ); //wire define wire ram_en ; //RAM使能 wire ram_wea ; //ram读写使能信号,高电平写入,低电平读出 wire [4:0] ram_addr ; //ram读写地址 wire [7:0] ram_wr_data ; //ram写数据 wire [7:0] ram_rd_data ; //ram读数据 //***************************************************** //** main code //***************************************************** //ram读写模块 ram_rw u_ram_rw( .clk (sys_clk ), .rst_n (sys_rst_n ), //RAM .ram_en (ram_en ), .ram_wea (ram_wea ), .ram_addr (ram_addr ), .ram_wr_data (ram_wr_data ), .ram_rd_data (ram_rd_data ) ); //ram ip核 blk_mem_gen_0 blk_mem_gen_0 ( .clka (sys_clk ), // input wire clka .ena (ram_en ), // input wire ena .wea (ram_wea ), // input wire [0 : 0] wea .addra (ram_addr ), // input wire [4 : 0] addra .dina (ram_wr_data ), // input wire [7 : 0] dina .douta (ram_rd_data ) // output wire [7 : 0] douta ); endmodule
tb_ip_ram.v
module tb_ip_ram(); reg sys_clk; reg sys_rst_n; always #10 sys_clk = ~sys_clk; initial begin sys_clk = 1'b0; sys_rst_n = 1'b0; #200 sys_rst_n = 1'b1; #5000 sys_rst_n = 1'b0; end ip_ram u_ip_ram( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n) ); endmodule
那么如何配置成ROM呢?
只需要在配置页面,选择单端口ROM,宽度选择24,在nodepad++打开coe文件查看深度,同样流水线寄存器不需要,之后导入初始值即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。