双口RAM
利用Xilinx提供的IP核构建真双口RAM,通过状态机实现从A口写数据,从B口读取数据。同样也可以在B口写入数据,A口读取数据。这样的双口RAM可以用在异构系统中。
IP核配置
IP核Block Memory Generator配置过程如下:
- Basic 类型选择Native,True Dual Port RAM;
2.Port A:
3.Port B:
- Other options:
- Summary:
Verilog代码
top文件
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2018/12/18 16:28:04
// Design Name:
// Module Name: ram_ftt
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ram_ftt(
input clk,
input rst,
input ena,
input enb,
input wea,
input [9:0]addr,
input [15:0]din,
output [15:0]douta,
output [15:0]dout
);
reg rst_n;
// reg ena;
// reg enb;
// reg wea;
reg web;
reg [9:0]addra;
reg [9:0]addrb;
reg [15:0]dina;
reg [15:0]dinb;
// reg [15:0]douta;
reg [15:0]doutb;
reg [15:0]din_reg;
// reg [31:0]dout;
reg [3:0] current_state,next_state;
reg write_end;
reg read_end;
reg [15:0]ram [9:0];
reg [15:0]read_ram [9:0];
// integer i=0;
parameter
idle=4'b0000,
write=4'b0001,
read=4'b0010;
// assign din=dina;
// assign dout=doutb;
//第一个always块,时序逻辑,描述现态转移到次态
always @ (posedge clk or negedge rst) begin
if(!rst) begin
current_state<=idle;
end
else
current_state<=next_state;
end
//第二个always块,组合逻辑,描述状态转移的条件
always @ (current_state or wea) begin
case(current_state)
idle:begin
if(wea) next_state <= write;//状态转移
else next_state <= idle;
end
write:begin
if(!wea) next_state <= read;//状态转移
else next_state <= write;
end
read:begin
if(addr==10) next_state <= idle;//状态转移
else next_state <= read;
end
default: begin
next_state = idle;//状态转移
end
endcase
end
//第三个always块,时序逻辑,描述输出
always @ (negedge clk or negedge rst) begin
if(!rst)begin
//addra<=0;
//addra<=addr;
//dina <= din;
// dina<=0;
// addrb<=0;
end
else
case(current_state)
idle: begin
// addra<=0;
addra<=0;
dina<=0;
// addrb<=0;
end
write: begin
//i=i+1;
addra<=addr;
//addra<=i;
dina<=din;
end
read:begin
addrb=addr;
end
default:begin
write_end<=0;
read_end<=0;
end
endcase
end
blk_mem_gen_0 sim(
.clka(clk),
.clkb(clk),
.ena(ena),
.enb(enb),
.wea(wea),
.web(),
.addra(addra),
.addrb(addrb),
.dina(dina),
.dinb(),
.douta(douta),
.doutb(dout)
);
endmodule
testbench
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2018/12/17 15:06:05
// Design Name:
// Module Name: sim
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module simu;
//module top(clka,clkb,ena,enb,wea,web,addra,addrb,dia,dib,doa,dob);
reg clk;
reg rst;
reg ena;
reg enb;
reg wea;
reg [9:0]addr;
reg [15:0]din;
wire [15:0]douta;
wire [15:0]dout;
reg[15:0] ram_a [9:0];
integer i=0;
initial $readmemh("F:/date0.txt",ram_a);
initial begin
clk=0;
rst=1;
addr=0;
ena=0;
enb=0;
wea=0;
din=1;
#50 rst= 0;
#50 rst=1;
ena= 1;
wea=1;
enb=1;
addr=0;
end
always #10 clk = ~clk;
always @(negedge clk or negedge rst)
begin
if(!rst)begin
addr<=1;
end
else begin
addr<=addr+1;
if(addr>=10) begin
wea<=!wea;
addr<=1;
end
if(wea) din<= ram_a[addr];
end
end
ram_ftt sim(.clk(clk),.rst(rst),.addr(addr),.din(din),.ena(ena),.enb(enb),.wea(wea),.douta(douta),.dout(dout));
endmodule