RAM IP核
1.原理
数据使能信号充当掩码的作用。1表示1字节就是8个位有效。
2.1 ram_ctrl.v
module ram_ctrl#(
parameter CNT_MAX=24'd9_999_999
)
(
input wiresys_clk,
input wire sys_rst_n,
input wire wr_flag,
input wire rd_flag,
output reg wr_en,
output reg [7:0]addr,
output reg[7:0] wr_data,
output reg rd_en
);
reg [23:0] cnt_200ms;
assign wr_data=(wr_en==1'b1)?(addr):1'b0;
always@(posedge sys_clk or negedge sys_rst_n)
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;
always@(posedge sys_clk or negedge sys_rst_n)
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;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
addr<=8'd0;
else if(((addr==8'd255)&&(wr_en==1'b1))||((addr==8'd255)&&(cnt_200ms==24'd255))||rd_flag==1'b1||wr_flag==1'b1)
addr<=8'd0;
else if((wr_en==1'b1)||((rd_en==1'b1)&&(cnt_200ms==CNT_MAX)))
addr<=addr+1'b1;
else
addr<=addr;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt_200ms<=24'd0;
else if((wr_flag==1'b1)||(cnt_200ms==CNT_MAX)||(rd_flag==1'b1))
cnt_200ms<=24'd0;
else if(rd_en==1'b1)
cnt_200ms<=cnt_200ms+1'b1;
else
cnt_200ms<=24'd0;
endmodule
2.2 tb_ram_ctrl.v
`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;
#60000 //一个数据显示11个时钟周期,256个数据,256*11=2816个时钟周期,就是2816*20=56320
//wr_flag
wr_flag<=1'b1;
#20
wr_flag<=1'b0;
#60000 //20*256=5120
//rd_flag
rd_flag<=1'b1;
#20
rd_flag<=1'b0;
end
assign #10 sys_clk=~sys_clk;
ram_ctrl#(
.CNT_MAX (4'd10)
)
ram_ctrl_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 )
);
ram_8x256_one ram_8x256_one_inst
(
.aclr(~sys_rst_n),
.address(addr),
.clock(sys_clk),
.data(wr_data),
.rden(rd_en),
.wren(wr_en),
.q(data_out)
);
endmodule
2.3 ram.v
module ram(
input wire sys_clk,
input wire sys_rst_n,
input wire wr_key,
input wire rd_key,
output wire ds,
output wire oe,
output wire shcp,
output wire stcp
);
wire wr_flag;
wire rd_flag;
wire wr_en ;
wire [7:0]addr ;
wire [7:0]wr_data ;
wire rd_en ;
wire [7:0]data_out;
key_filter
#(
.CNT_MAX (20'd999_999)
)
key_filter_wr_inst
(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.key_in(wr_key),
.key_flag(wr_flag)
);
key_filter
#(
.CNT_MAX (20'd999_999)
)
key_filter_rd_inst
(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.key_in(rd_key),
.key_flag(rd_flag)
);
ram_ctrl #(
.CNT_MAX(24'd9_999_999)
)
(
.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 )
);
ram_8x256_one ram_8x256_one_inst
(
.aclr(~sys_rst_n),
.address(addr),
.clock(sys_clk),
.data(wr_data),
.rden(rd_en),
.wren(wr_en),
.q(data_out)
);
seg_595_dynamic(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.data({12'b0,data_out}),
.point(6'b000_000),
.sign(1'b0),
.seg_en(1'b1),
.ds(ds),
.oe(oe),
.shcp(shcp),
.stcp(stcp)
);
endmodule
2.4 tb_ram.v
`timescale 1ns/1ns
module tb_ram();
reg sys_clk ;
reg sys_rst_n ;
reg wr_key ;
reg rd_key ;
wire ds ;
wire oe ;
wire shcp ;
wire stcp ;
initial
begin
sys_clk=1'b1;
sys_rst_n<=1'b0;
wr_key=1'b1;
rd_key=1'b1;
#20
sys_rst_n<=1'b1;
#1000
//读操作rd_key
//模拟产生读操作按键前抖动
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#20
//模拟产生的稳定状态
rd_key=1'b0;
#200
//模拟产生按键信号的后抖动
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
//此时就会读出在ip核事先初始化的数据
#200000
//模拟读数据的过程
//
wr_key=1'b0;
#20
wr_key=1'b1;
#20
wr_key=1'b0;
#20
wr_key=1'b1;
#20
//模拟稳定状态
wr_key=1'b0;
#200
//后抖动
wr_key=1'b1;
#20
wr_key=1'b0;
#20
wr_key=1'b1;
#20
wr_key=1'b0;
#20
wr_key=1'b1;
#1000
//rd_key
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#200
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#200000
//在读数据的过程中再次按下读操作按键
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#200
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#20
rd_key=1'b0;
#20
rd_key=1'b1;
#200000
end
always #10 sys_clk=~sys_clk;
defparam ram_inst.key_filter_wr_inst.CNT_MAX=9;
defparam ram_inst.key_filter_wr_inst.CNT_MAX=9;
defparam ram_inst.ram_ctrl_inst.CNT_MAX=99;
ram ram_inst(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.wr_key(wr_key),
.rd_key(rd_key),
.ds(ds),
.oe(oe),
.shcp(shcp),
.stcp (stcp )
);
endmodule
对顶层模块的仿真主要是查看各个模块之间的信号传递是否正确,因为之前各个模块已经仿真过了。
总的过程就是刚开始读初始化的数据,然后再次读一次发现还是从0地址开始读,然后在读的过程中按下写的按钮,此时就不再读了,数据定格在最后的一瞬间,再次按下读按钮,又从0地址开始读写入的数据。
原文地址:https://blog.csdn.net/m0_51133942/article/details/137092001
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!