RAM IP核

1.原理

数据使能信号充当掩码的作用。1表示1字节就是8个位有效。

2.1 ram_ctrl.v

复制代码
module ram_ctrl#(
	parameter CNT_MAX=24'd9_999_999
)
(
	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 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地址开始读写入的数据。

相关推荐
黄埔数据分析1 小时前
RecoNIC 入门:SmartNIC 上支持 RDMA 的计算卸载-FPGA-智能网卡-AMD-Xilinx
fpga开发
nanxl13 小时前
FPGA-数字时钟
fpga开发·verilog·vivado
尤老师FPGA16 小时前
LVDS系列9:Xilinx 7系可编程输入延迟(二)
单片机·嵌入式硬件·fpga开发
内有小猪卖20 小时前
时序约束 记录
fpga开发
Cao1234567893211 天前
FPGA时钟设计
fpga开发
JNTeresa1 天前
锁存器知识点详解
fpga开发
Cao1234567893211 天前
FPGA基础之基础语法
fpga开发
一大Cpp1 天前
通过Quartus II实现Nios II编程
fpga开发
7yewh1 天前
Verilog 语法 (二)
fpga开发
边缘计算社区2 天前
FPGA与边缘AI:计算革命的前沿力量
人工智能·fpga开发