1.IDE:Quartus II
2.设备:Cyclone II EP2C8Q208C8N
3.实验:调用单端口RAM仿真读取写入
4.时序图:
5.步骤:
(1)添加一个初始化文件做对比,255递减到0(HEX文件)
(2)仿真时出现报错,为配置的ram的.v文件没有添加,按如下方式解决。
6.代码:
ram_ctrl.v
/*
*因为工程名失误,应该是ram_ctrl
*/
module ram_ip(
input wire sys_clk ,
input wire sys_rst_n ,
input wire wr_flag ,
input wire rd_flag ,
output reg wr_en ,
output reg [7:0] addr ,
output wire [7:0] wr_data ,
output reg rd_en
);
parameter CNT_MAX =24'd1000_0000; //计数值200ms 20ns per clk
reg [23:0] cnt_200ms;
/*
*计时器(用于数码管显示,数码管需要留存时间)
*/
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
cnt_200ms <= 24'd0;
else if((cnt_200ms == CNT_MAX) || (wr_flag == 1'b1) || (rd_flag == 1'b1)) //有读、写直接清零,计满时间也清零
cnt_200ms <= 24'd0;
else if(rd_en == 1'b1)
cnt_200ms <= cnt_200ms + 1'b1; //读ram期间计数(读出来数码管显示需要时间)
else
cnt_200ms <= cnt_200ms;
end
/*
*写使能控制
*/
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
wr_en <= 1'b0;
else if(addr == 8'd255) //地址到达最大禁止写入
wr_en <= 1'b0;
else if(wr_flag == 1'b1) //写标志位拉高,使能写
wr_en <= 1'b1;
else
wr_en <= wr_en;
end
/*
*地址控制
*/
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
addr <= 8'd0;
else if((addr == 8'd255 && wr_en == 1'b1) || (addr == 8'd255 && cnt_200ms == CNT_MAX) || (wr_flag == 1'b1) || (rd_flag == 1'b1))
addr <= addr + 1'b1;
else
addr <= addr;
end
/*
*写入的数据赋值
*/
assign wr_data = (wr_en == 1'b1) ? addr : 8'd0; //写使能期间将地址作为数据
/*
*读使能控制
*/
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
rd_en <= 1'b0;
else if(wr_flag == 1'b1) //写信号到来,直接失能读操作
rd_en <= 1'b0;
else if(rd_flag == 1'b1 && wr_en == 1'b0) //读信号到来且写信号失能才会将读信号使能
rd_en <= 1'b1;
else
rd_en <= rd_en;
end
endmodule
tb_ram_ctrl.v文章来源:https://www.toymoban.com/news/detail-826581.html
/*
*ram_ip仿真代码
*/
`timescale 1ns/1ns
module tb_ram_ctrl();
reg sys_clk ;
reg sys_rst_n ;
reg wr_flag ;
reg rd_flag ;
wire wr_en ;
wire [7:0] addr ;
wire [7:0] wr_data ;
wire rd_en ;
wire [7:0] data_out ;
/*
*读,写,再读
*/
initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
wr_flag <= 1'b0;
rd_flag <= 1'b0;
#20
sys_rst_n <= 1'b1;
#1000
//rd_flag
rd_flag <= 1'b1; //读信号拉高一个时钟周期
#20
rd_flag <= 1'b0;
#60_000 // > CNT_MAX * 20ns * 255 =10 * 20 * 256 = 51200
//wr_flag
wr_flag <= 1'b1; //写信号拉高一个时钟周期
#20
wr_flag <= 1'b0;
#60_000
//rd_flag
rd_flag <= 1'b1; //写完之后再读看写入是否正确
#20
rd_flag <= 1'b0;
end
always #10 sys_clk = ~ sys_clk; //模拟时钟
defparam ram_ip_inst.CNT_MAX = 10 ; //用于仿真(10 * 20ns = 200ns per data)
/*
*实例化ram_ctrl
*/
ram_ip ram_ip_inst(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n) ,
.wr_flag (wr_flag ) ,
.rd_flag (rd_flag ) ,
.wr_en (wr_en ) ,
.addr (addr ) ,
.wr_data (wr_data ) ,
.rd_en (rd_en )
);
/*
*实例化IP核,CYCLONE II 没有读使能控制信号?
*/
ram_8x256_one ram_8x256_one_inst (
.aclr (~sys_rst_n), //异步清零信号(高电平有信号)
.address (addr),
.clock (sys_clk),
.data (wr_data),
.wren (wr_en),
.q (data_out)
);
endmodule
文章来源地址https://www.toymoban.com/news/detail-826581.html
到了这里,关于#FPGA(IP_RAM 调用 )的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!