两套地址线数据线
//真双端口RAM同步读写 module dualram #(parameter ADDR_WIDTH=8,DATA_WIDTH=8,RAM_DEPTH=1<<ADDR_WIDTH)( clk, cs_0,//chip select we_0,//write en oe_0,//output en address_0, data_0, cs_1, we_1, oe_1, address_1, data_1 ); input clk; input cs_0; input we_0; input oe_0; input [ADDR_WIDTH-1:0]address_0; inout [DATA_WIDTH-1:0]data_0; input cs_1; input we_1; input oe_1; input [ADDR_WIDTH-1:0]address_1; inout [DATA_WIDTH-1:0]data_1; reg [DATA_WIDTH-1:0]mem[RAM_DEPTH-1:0]; reg [DATA_WIDTH-1:0]data_0_out; reg [DATA_WIDTH-1:0]data_1_out; //initial //synopsys_translate_off integer i; initial begin for(i=0;i<RAM_DEPTH;i=i+1)begin mem[i]=8'h00; end end //synopsys_translate_on //write always@(posedge clk)begin if(cs_0&&we_0) mem[address_0]<=data_0; else if(cs_1&&we_1) mem[address_1]<=data_1; end //read 0 always@(posedge clk) if(cs_0&&!we_0) data_0_out<=mem[address_0]; else data_0_out <=0; assign data_0=(cs_0&&!we_0&&oe_0)?data_0_out:8'bz; //read 1 always@(posedge clk) if(cs_1&&!we_1) data_1_out<=mem[address_1]; else data_1_out<=0; assign data_1=(cs_1&&!we_1&&oe_1)?data_1_out:8'bz; endmodule
tb:
`timescale 1ns/1ns module dualram_tb(); reg clk; reg cs_0; reg we_0; reg oe_0; reg [7:0]address_0; wire [7:0]data_0; reg cs_1; reg we_1; reg oe_1; reg [7:0]address_1; wire [7:0]data_1; dualram #(.ADDR_WIDTH(8),.DATA_WIDTH(8))//给定参数 dualram ( .clk(clk), .cs_0(cs_0),//chip select .we_0(we_0),//write en .oe_0(oe_0),//output en .address_0(address_0), .data_0(data_0), .cs_1(cs_1), .we_1(we_1), .oe_1(oe_1), .address_1(address_1), .data_1(data_1) ); initial clk=0; always #2 clk=~clk; reg [7:0] data_in0; //写数据时候,双向总线与data_in0连接(这样做的目的是保证总线在某一时刻读和写,二者之一有效) assign data_0=(cs_0&&we_0&&!oe_0)?data_in0:8'bz; reg [7:0]data_in1; assign data_1=(cs_1&&we_1&&!oe_1)?data_in1:8'bz; integer i=0; initial begin oe_0=0; cs_0=0; we_0=0; oe_1=0; cs_1=0; we_1=0; address_0=0; address_1=0; data_in0=0; data_in1=0; //先读出初始值,两组数据地址线一起读 #4 cs_0=1; cs_1=1; oe_0=1; oe_1=1; for(i=0;i<256;i=i+1)begin @(negedge clk)begin address_0=i; address_1=i; end end #1040; //地址0写,地址1读 @(negedge clk)begin we_0=1; oe_0=0; we_1=0; oe_1=1; end #4; for(i=0;i<256;i=i+1)begin @(negedge clk)begin address_0=i; data_in0=data_in0+1; address_1=i; end end #1040; //地址0读,地址1读 @(negedge clk)begin we_0=0; oe_0=1; we_1=0; oe_1=1; end #4; for(i=0;i<256;i=i+1)begin @(negedge clk)begin address_0=i; address_1=i; end end #1040; //片选结束 @(negedge clk)begin cs_0=0; cs_1=0; end #100; $stop; end endmodule
波形:
全局概览:
1.两端口同时读存储器的初值
2.端口0写,同时端口1读
3.两端口同时读