手撕RAM(单端口,简单双端口,真双端口)

29 篇文章 30 订阅

单端口

rtl

module hand_ram_sp #(
	parameter DATAWIDTH	=8	,
	parameter ADDRSIZE	=8
)
(
	input 						clka		,
	input 						ena			,
	input 						wea			,
	input 			[ADDRSIZE-1:0]	addra	,
	input 			[DATAWIDTH-1:0]	dina	,
	output 	reg		[DATAWIDTH-1:0]	douta
);

localparam DATADEPTH = 1<<ADDRSIZE;
reg [DATAWIDTH-1:0]	mem	[DATADEPTH-1:0];

always @(posedge clka ) begin
	if(ena&&(~wea))begin
		douta <= mem[addra];
	end
	else 	begin
		douta <= 0;
	end
end

always @(posedge clka ) begin
	if(ena&&wea)	begin
		mem[addra] <= dina;
	end
	else 	begin
		mem[addra] <= mem[addra];
	end
end


	
endmodule

sim

//~ `New testbench
`timescale  1ns / 1ps

module tb_hand_ram_sp;

// hand_ram_sp Parameters
parameter PERIOD = 10;
parameter DATAWIDTH  = 8;
parameter ADDRSIZE  = 4;

// hand_ram_sp Inputs
reg   clk                                 		= 0 ;
reg   ena                                  		= 0 ;
reg   wea                                  		= 0 ;
reg   [ADDRSIZE-1:0]  	addra               	= 0 ;
reg   [DATAWIDTH-1:0]  	dina                 	= 0 ;

// hand_ram_sp Outputs
wire  [DATAWIDTH-1:0]  douta                   ;

initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

hand_ram_sp #(
    .DATAWIDTH ( DATAWIDTH ),
    .ADDRSIZE ( ADDRSIZE ))
 u_hand_ram_sp (
    .clka                    ( clk                ),
    .ena                     ( ena                ),
    .wea                     ( wea                ),
    .addra                   ( addra  [ADDRSIZE-1:0] 	),
    .dina                    ( dina   [DATAWIDTH-1:0] 	),

    .douta                   ( douta  [DATAWIDTH-1:0] 	)
);

initial
begin
    #(PERIOD*4)
	ena = 1;
	wea = 1;
	#(PERIOD*16)
	wea = 0;
end

always @(posedge clk) begin
	addra <= addra +1'b1;
end

always @(posedge clk) begin
	dina <= dina +1'b1;
end

endmodule

在这里插入图片描述

简单双端口

rtl

module hand_ram_hdp #(
	parameter DATAWIDTH=8,
	parameter ADDRSIZE=8
)
(
	input 						clka		,
	input 						ena			,
	input 						wea			,
	input 			[ADDRSIZE-1:0]	addra	,
	input 			[DATAWIDTH-1:0]	dina	,

	input 						clkb		,
	input 						enb			,
	input 			[ADDRSIZE-1:0]	addrb	,
	output 	reg		[DATAWIDTH-1:0]	doutb
);

localparam DATADEPTH = 1<<ADDRSIZE;
reg [DATAWIDTH-1:0]	mem	[DATADEPTH-1:0];

// 写
always @(posedge clka ) begin
	if(ena&&wea)begin
		mem[addra] <= dina;
	end
end

// 读
always @(posedge clkb ) begin
	if(enb&&(~wea))begin
		doutb <= mem[addrb];
	end
	else	begin
		doutb <= 0;
	end
end


endmodule

sim

//~ `New testbench
`timescale  1ns / 1ps

module tb_hand_ram_hdp;

// hand_ram_hdp Parameters
parameter PERIOD     = 10;
parameter DATAWIDTH  = 8;
parameter ADDRSIZE   = 4;

// hand_ram_hdp Inputs
reg   clka                                 = 0 ;
reg   ena                                  = 0 ;
reg   wea                                  = 0 ;
reg   [ADDRSIZE-1:0]  addra                = 0 ;
reg   [DATAWIDTH-1:0]  dina                = 0 ;
reg   clkb                                 = 0 ;
reg   enb                                  = 0 ;
reg   [ADDRSIZE-1:0]  addrb                = 0 ;

// hand_ram_hdp Outputs
wire  [DATAWIDTH-1:0]  doutb               ;


initial
begin
    forever #(PERIOD/2)  clka=~clka;
end

initial
begin
    forever #(PERIOD/2)  clkb=~clkb;
end



hand_ram_hdp #(
    .DATAWIDTH ( DATAWIDTH ),
    .ADDRSIZE  ( ADDRSIZE  ))
 u_hand_ram_hdp (
    .clka                    ( clka                   ),
    .ena                     ( ena                    ),
    .wea                     ( wea                    ),
    .addra                   ( addra  [ADDRSIZE-1:0]  ),
    .dina                    ( dina   [DATAWIDTH-1:0] ),
    .clkb                    ( clkb                   ),
    .enb                     ( enb                    ),
    .addrb                   ( addrb  [ADDRSIZE-1:0]  ),

    .doutb                   ( doutb  [DATAWIDTH-1:0] )
);

initial
begin
    #(PERIOD*4)
	ena = 1;
	wea = 1;
	#(PERIOD*16)
	ena = 0;
	enb = 1;
	wea = 0;


end

always @(posedge clka) begin
	addra <= addra +1'b1;
end

always @(posedge clka) begin
	dina <= dina +1'b1;
end

always @(posedge clkb) begin
	addrb <= addrb +1'b1;
end

endmodule

在这里插入图片描述

真双端口

rtl

module hand_ram_dp #(
	parameter DATAWIDTH=8,
	parameter ADDRSIZE=8
)
(
	input 						clka	,
	input 						ena		,
	input 						wea		,
	input 			[ADDRSIZE-1:0]	addra	,
	input 			[DATAWIDTH-1:0]	dina	,
	output 	reg		[DATAWIDTH-1:0]	douta	,

	input 						clkb	,
	input 						enb		,
	input 						web		,
	input 			[ADDRSIZE-1:0]	addrb	,
	input 			[DATAWIDTH-1:0]	dinb	,
	output 	reg		[DATAWIDTH-1:0]	doutb
);

localparam DATADEPTH = 1<<ADDRSIZE;
reg [DATAWIDTH-1:0]	mem	[DATADEPTH-1:0];

always @(posedge clka ) begin
	if(ena&&(~wea))begin
		douta <= mem[addra];
	end
	else 	begin
		douta <= 0;
	end
end

always @(posedge clka ) begin
	if(ena&&wea)	begin
		mem[addra] <= dina;
	end
end

always @(posedge clkb ) begin
	if(enb&&(~web))begin
		doutb <= mem[addrb];
	end
	else 	begin
		doutb <= 0;
	end
end

always @(posedge clkb ) begin
	if(enb&&web)	begin
		mem[addrb] <= dinb;
	end
end

endmodule

sim

//~ `New testbench
`timescale  1ns / 1ps

module tb_hand_ram_dp;

// hand_ram_dp Parameters
parameter PERIOD     = 10;
parameter DATAWIDTH  = 8;
parameter ADDRSIZE   = 4;

// hand_ram_dp Inputs
reg   clka                                 = 0 ;
reg   ena                                  = 0 ;
reg   wea                                  = 0 ;
reg   [ADDRSIZE-1:0]  addra                = 0 ;
reg   [DATAWIDTH-1:0]  dina                = 0 ;
reg   clkb                                 = 0 ;
reg   enb                                  = 0 ;
reg   web                                  = 0 ;
reg   [ADDRSIZE-1:0]  addrb                = 0 ;
reg   [DATAWIDTH-1:0]  dinb                = 0 ;

// hand_ram_dp Outputs
wire  [DATAWIDTH-1:0]  douta               ;
wire  [DATAWIDTH-1:0]  doutb               ;


initial
begin
    forever #(PERIOD/2)  clka=~clka;
end
initial
begin
    forever #(PERIOD/2)  clkb=~clkb;
end

hand_ram_dp #(
    .DATAWIDTH ( DATAWIDTH ),
    .ADDRSIZE  ( ADDRSIZE  ))
 u_hand_ram_dp (
    .clka                    ( clka                   ),
    .ena                     ( ena                    ),
    .wea                     ( wea                    ),
    .addra                   ( addra  [ADDRSIZE-1:0]  ),
    .dina                    ( dina   [DATAWIDTH-1:0] ),
    .clkb                    ( clkb                   ),
    .enb                     ( enb                    ),
    .web                     ( web                    ),
    .addrb                   ( addrb  [ADDRSIZE-1:0]  ),
    .dinb                    ( dinb   [DATAWIDTH-1:0] ),

    .douta                   ( douta  [DATAWIDTH-1:0] ),
    .doutb                   ( doutb  [DATAWIDTH-1:0] )
);

initial
begin
    #(PERIOD*2)
	#(PERIOD*2)
	ena = 1;
	enb = 0;
	wea = 1;
	web = 0;
	#(PERIOD*16)
	ena = 0;
	enb = 1;
	wea = 0;
	web = 0;


end

always @(posedge clka) begin
	addra <= addra +1'b1;
end

always @(posedge clka) begin
	dina <= dina +1'b1;
end

always @(posedge clkb) begin
	addrb <= addrb +1'b1;
end

endmodule

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值