欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Verilog实现RAM(5-双端口同步读写SRAM)

程序员文章站 2022-04-01 16:39:07
...

在之前的工作中,我们对常见存储器件进行了名词扫盲,并通过调用IP核实现了简单的单端口同步读写SRAM、对单端口同步读写SRAM进行了Verilog描述、并进一步对单端口同步写,异步读SRAM进行了设计与分析;这部分工作见:

Verilog实现RAM(1)

Verilog实现RAM(2-单端口同步读写SRAM)

Verilog实现RAM(3-单端口同步写、异步读SRAM)

Verilog实现RAM(4-单端口异步读写SRAM)

现在在之前工作的基础上,进一步实现双端口同步读写SRAM

一、原理

双端口同步读写SRAM与单端口同步读写SRAM,唯一区别就在于有两套信号(控制信号、数据输入输出、地址信号)

输入端口有:

    reg clk;

    reg [3:0]a1;//输入地址(RAM深度为16,对应地址位宽为4)

    reg we1;// write enable,写使能时进行RAM写操作

    reg oe1;// output enable,输出使能时RAM读取的结果才能输出

    reg cs1;// 片选信号,选择读取哪一个RAM

//  第二套

    reg [3:0]a2;//输入地址(RAM深度为16,对应地址位宽为4)

    reg we2;// write enable,写使能时进行RAM写操作

    reg oe2;// output enable,输出使能时RAM读取的结果才能输出

    reg cs2;// 片选信号,选择读取哪一个RAM

输入输出端口有:
    wire [7:0]d1;//读取RAM时数据输出/写入RAM时数据输入   

    wire [7:0]d2;//读取RAM时数据输出/写入RAM时数据输入

 

工作过程:

时钟来临时,两组端口分别根据cs/we/oe的值执行不同的操作;cs有效(为1)、we为1时,写使能,将d输入数据写入a对应地址处;cs有效(为1)、we为0时,读使能,oe有效(为1)时将a地址处的数据读出到d上;

双端口RAM同时进行读操作时不会冲突,即可以对同一地址进行读取,结果分别通过各自输出端口进行输出;但是双端口同时进行写操作时就可能出现写入冲突,即双端口对同一地址写入时就会出现问题;

为避免这一问题出现,将双端口SRAM设计为双端口同步读,非同步写;(可同时读,可同时一读一写,但是无法同时写,同时写时只能执行优先级高的端口写


二、代码实现:

接着之前的工作,对双端口同步读写SRAM进行Verilog描述----实现一个位宽8bit,深度16bit的单端口SRAM;只需在之前单端口同步读写的基础上简单修改即可;

verilog描述如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: CLL
// 
// Create Date: 2020/02/24 19:10:35
// Design Name: 
// Module Name: sram_dp_srsw
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module sram_dp_srsw
#(parameter DW = 8,AW = 4)
(
    input clk,
    input [AW-1:0]a1,//address
    input cs1,// chip select
    input oe1,// output enable
    input we1,// write enable
    inout [DW-1:0]d1,// data
    // 
    input [AW-1:0]a2,//address
    input cs2,// chip select
    input oe2,// output enable
    input we2,// write enable
    inout [DW-1:0]d2// data
    );

// 
parameter DP = 1 << AW;// depth 
reg [DW-1:0]mem[0:DP-1];
reg [DW-1:0]reg_d1;
// port2
reg [DW-1:0]reg_d2;
//initialization
// synopsys_translate_off
integer i;
initial begin
    for(i=0; i < DP; i = i + 1) begin
        mem[i] = 8'h00;
    end
end
// synopsys_translate_on

// read declaration
// port1
aaa@qq.com(posedge clk)
begin
    if(cs1 & !we1 & oe1)
        begin
            reg_d1 <= mem[a1];
        end
    else
        begin
            reg_d1 <= reg_d1;
        end
end
// port2
aaa@qq.com(posedge clk)
begin
    if(cs2 & !we2 & oe2)
        begin
            reg_d2 <= mem[a2];
        end
    else
        begin
            reg_d2 <= reg_d2;
        end
end

// wrirte declaration
aaa@qq.com(posedge clk)
begin
    if(cs1 & we1)//port1 higher priority
        begin
            mem[a1] <= d1;
        end
    else if(cs2 & we2)
        begin
            mem[a2] <= d2;
        end
    else
        begin
            mem[a1] <= mem[a1];
            mem[a2] <= mem[a2];
        end    
end

// 三态逻辑
assign d1 = (cs1 & !we1 & oe1) ? reg_d1 : {DW{1'bz}};
assign d2 = (cs2 & !we2 & oe2) ? reg_d2 : {DW{1'bz}};
endmodule

测试文件如下:

同步读,port1读地址0-15,port2读地址15-0

port1读地址15-0,port2写1-16到地址0-15

同步写地址0-15,port1写1,port2写2

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: CLL
// 
// Create Date: 2020/02/24 19:25:55
// Design Name: 
// Module Name: sram_dp_srsw_tsb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module sram_dp_srsw_tsb(

    );
// port declaration
reg clk;
// port1
reg [3:0]a1;//address
reg cs1;
reg oe1;
reg we1;// write enable
wire [7:0]d1;//datain/out 
// port2
reg [3:0]a2;//address
reg cs2;
reg oe2;
reg we2;// write enable
wire [7:0]d2;//datain/out 
// reg declaration
reg [7:0]din1;
reg [7:0]din2;
// 
initial
begin
    clk = 1'b0;
    forever #10 clk = ~clk;//period = 20
end
//
assign d1 = (cs1 & we1)?din1:8'bzzzz_zzzz;
assign d2 = (cs2 & we2)?din2:8'bzzzz_zzzz;
//
initial
begin
    a1 = 4'b0000;
    din1 = 8'd1;
    we1 = 1'b0;
    oe1 = 1'b1;
    cs1 = 1'b1;
    a2 = 4'b1111;
    din2 = 8'd1;
    we2 = 1'b0;
    oe2 = 1'b1;
    cs2 = 1'b1;
    #20//同步读,port1读0-15,port2读15-0
    repeat(15) begin
        #20 a1 = a1+1'b1;
        a2 = a2-1'b1;
    end
    #20//port1读15-0,port2写0-15
    we2 = 1'b1;
    repeat(15) begin
        #20 a1 = a1-1'b1;
        a2 = a2+1'b1;
        din2 = din2+1'b1;
    end
    #20//同步写0-15,port1写1,port2写2
    we1 = 1'b1;
    we2 = 1'b1;
    a1 = 4'b0000;
    a2 = 4'b0000;
    repeat(15) begin
        #20 a1 = a1+1'b1;
        din1 = 1'b1;
        a2 = a2+1'b1;
        din2 = 2'd2;
    end   
end
sram_dp_srsw inst (
  .clk(clk),
  .a1(a1),      // input wire [3 : 0] a
  .d1(d1),      // input wire [7 : 0] d
  .we1(we1),    // input wire we
  .cs1(cs1), 
  .oe1(oe1),  
  .a2(a2),      // input wire [3 : 0] a
  .d2(d2),      // input wire [7 : 0] d
  .we2(we2),    // input wire we
  .cs2(cs2), 
  .oe2(oe2)  
);

endmodule

仿真结果如下:

Verilog实现RAM(5-双端口同步读写SRAM)

可以看出:

同步读时,port1读地址0-15,port2读地址15-0,输出均为0

port1读地址15-0,port2写1-16到地址0-15时:mem值从0-15逐步改变,d1输出从0直到port2写入了值的部分,证明确实可以同步读写

同步写地址0-15,port1写1,port2写2,输出为1,证明同时写时确实port1优先级较高;

三、参考文献:

Verilog实现RAM(2-单端口同步读写SRAM)

【FPGA】双端口RAM的设计(同步读写)