自学内容网 自学内容网

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)!