双口RAM同步读写

两套地址线数据线
//真双端口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
View Code

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
View Code

波形:

全局概览:

1.两端口同时读存储器的初值

 2.端口0写,同时端口1读

 3.两端口同时读

猜你喜欢

转载自www.cnblogs.com/ajiaoa/p/12821421.html