单端口
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
`timescale 1ns / 1ps
module tb_hand_ram_sp;
parameter PERIOD = 10;
parameter DATAWIDTH = 8;
parameter ADDRSIZE = 4;
reg clk = 0 ;
reg ena = 0 ;
reg wea = 0 ;
reg [ADDRSIZE-1:0] addra = 0 ;
reg [DATAWIDTH-1:0] dina = 0 ;
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
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0ba3f6dc7abb9d8579c80916e1d3e682.png)
简单双端口
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
`timescale 1ns / 1ps
module tb_hand_ram_hdp;
parameter PERIOD = 10;
parameter DATAWIDTH = 8;
parameter ADDRSIZE = 4;
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 ;
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
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c2b754e56390dc5e859af7afba5ecc48.png)
真双端口
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
`timescale 1ns / 1ps
module tb_hand_ram_dp;
parameter PERIOD = 10;
parameter DATAWIDTH = 8;
parameter ADDRSIZE = 4;
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 ;
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
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6f40f16a2333650ddb92db8afd317997.png)