用Verilog实现一个异步双端口ram,深度16,位宽8bit。A口读出,B口写入。支持片选,读写请求,要求代码可综合
module Asy_Ram#(
parameter ADDR_WIDTH = 4,
parameter DATA_WIDTH = 8,
parameter DATA_DEPTH = 1 << ADDR_WIDTH
)(
input clka,
input clkb,
input rst_n,
input csen_n,
input [ADDR_WIDTH-1:0] addra,
output reg [DATA_WIDTH-1:0] data_a,
input rdena_n,
input [ADDR_WIDTH-1:0] addrb,
input wrenb_n,
input [DATA_WIDTH-1:0] data_b
);
integer i;
reg [DATA_WIDTH-1:0] register[DATA_DEPTH-1:0];
always@(posedge clkb or negedge rst_n)begin
if(!rst_n)begin
for(i=0;i<DATA_WIDTH;i=i+1)
register[i] <= 'b0000_0000;
end
else begin
if(wrenb_n == 1'b0 && csen_n == 1'b0)
register[addrb] <= data_b;
end
end
always@(posedge clka or negedge rst_n)begin
if(!rst_n)begin
data_a <= 0;
end
else begin
if(rdena_n == 1'b0 && csen_n == 1'b0)
data_a <= register[addra];
else
data_a <= data_a;
end
end
endmodule
测试代码
module tb_AsyRam;
reg clka;
reg clkb;
reg rst_n;
reg csen_n;
reg [3:0] addra;
reg rdena_n;
reg [3:0] addrb;
reg wrenb_n;
reg [7:0] data_b;
reg enb;
reg ena;
wire [7:0] data_a;
Asy_Ram uut (
.clka(clka),
.clkb(clkb),
.rst_n(rst_n),
.csen_n(csen_n),
.addra(addra),
.data_a(data_a),
.rdena_n(rdena_n),
.addrb(addrb),
.wrenb_n(wrenb_n),
.data_b(data_b)
);
always #5 clka = ~clka;
always #10 clkb =~clkb;
initial begin
clka = 0;
clkb = 0;
rst_n = 0;
csen_n = 0;
enb = 0;
ena = 0;
#100 rst_n = 1;
#200 enb = 1;
#310 enb = 0;
#1000 ena = 1;
#1330 ena = 0;
end
always@(posedge clkb) begin
if(enb)begin
wrenb_n <= 0;
data_b <= data_b + 8'd2;
addrb <= addrb + 4'd1;
end
else begin
wrenb_n <= 1;
addrb <= 4'b0;
data_b <= 8'b0;
end
end
always@(posedge clka) begin
if(ena == 1'b0)begin
rdena_n <= 1;
addra <= 4'b0;
end
else begin
rdena_n <= 0;
addra <= 4'b1 + addra;
end
end
endmodule