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

双口RAM定义 及多个ram verilog rtl仿真

程序员文章站 2024-02-22 21:30:52
...

自己写的采用这种数组形式写的RAM块占用存储器容量的大小,是满足定义的最小的2的n次方。

reg [dw-1:0] mem [(1<<aw) -1:0] /* synthesis syn_ramstyle="block_ram" */;

如果129个数据,>128需要256的ram
所以mem为[7:0],8位地址线

比方写了一个有300K的存储器块,那实际会生成一个512K的存储块,因为256K不够。

reg [dw-1:0] mem [300*1024 -1:0] 

实际上

reg [dw-1:0] mem [512*1024 -1:0] 

如果想节约空间怎么办,写一个256K的存储器RAM之后再写一个64K的存储器RAM,两种通过选择器连接形成一个新的256K + 64K的RAM。

code

module ram(
    rclk    ,raddr,dout,

    //其他信号,举例dout
    wclk,waddr,wdin,wen
    );

    //参数定义
    parameter      ADDR_W =         18; //2^8-1个
    parameter      DATA_W =         8;
    //read输入信号定义
    input               rclk    ;
    input [ ADDR_W -1:0]   raddr  ; 
    //read输出信号定义
    output[DATA_W-1:0]  dout   ;

    //write输入信号定义
    input               wclk    ;
    input               wen    ; // write enable, active high
    input [ ADDR_W -1:0]   waddr  ;     
    input [ DATA_W -1:0]   wdin  ;     


    //中间信号ram定义
    reg[DATA_W -1:0] mem[(1<<ADDR_W)-1:0]  ;//block ram
    reg [ ADDR_W -1:0] ra_buffer;
    
    
    //read 
    always  @(posedge rclk )begin
         ra_buffer<=raddr;
    end
    assign dout=mem[ra_buffer];//数据在地址后的一个周期
    //write 
    always  @(posedge wclk )begin
        if(wen)
         mem[waddr]=wdin;
    end
    initial $readmemh("init_mem",mem);
  
 
    endmodule


双口RAM定义 及多个ram verilog rtl仿真
双口RAM定义 及多个ram verilog rtl仿真

RAMB36E1为bram,
BUFG两个时钟,
LUT2/3/6
IBUF
双口RAM定义 及多个ram verilog rtl仿真
寄存器
双口RAM定义 及多个ram verilog rtl仿真

对于640480一共需要640480个数据,640*480/1024=300K,所以为了省bram空间,拆成256K+64K,用addr[18]作为分界线

初始化mem文件
通过载入ram
initial $readmemh(“bmp_256K.mem”,mem);

module vga_dpram(
    input wr_clk ,
    input  [11:0] wr_din,
    input [18:0] wr_addr,
    input   wr,

    input rd_clk,
    input [18:0] rd_addr ,
    output   [11:0] rd_dout


);
    wire[11:0]  rd_dout_256K;
    wire[11:0]  rd_dout_64K;
    //地址延迟一拍出data
    reg addr18;
    always  @(posedge rd_clk  )begin 
        addr18<=rd_addr[18];
    end

    assign rd_dout=(addr18==0)?rd_dout_256K:rd_dout_64K;
    generic_dpram_256Kx12 ram_256Kx12(
            .rclk (    rd_clk     ),
            .raddr(    rd_addr[17:0] ),
            .dout (    rd_dout_256K    ),
            .wclk (     wr_clk    ),
            .waddr(     wr_addr[17:0]    ),
            .wdin (     wr_din     ),
            .wen  (     wr&~rd_addr[18]       )
    );
    generic_dpram_64Kx12 ram_64Kx12(
            .rclk (    rd_clk     ),
            .raddr(    rd_addr[17:0]),
            .dout (    rd_dout_64K    ),
            .wclk (     wr_clk    ),
            .waddr(     wr_addr[17:0]    ),
            .wdin (     wr_din     ),
            .wen  (     wr  &rd_addr[18]      )
    );
    endmodule
 

module generic_dpram_256Kx12(

        rclk    ,raddr,dout,

    //其他信号,举例dout
    wclk,waddr,wdin,wen
    );

    //参数定义
    parameter      ADDR_W =         18;  
    parameter      DATA_W =         12;
    //read输入信号定义
    input               rclk    ;
    input [ ADDR_W -1:0]   raddr  ; 
    //read输出信号定义
    output[DATA_W-1:0]  dout   ;

    //write输入信号定义
    input               wclk    ;
    input               wen    ; // write enable, active high
    input [ ADDR_W -1:0]   waddr  ;     
    input [ DATA_W -1:0]   wdin  ;     


    //中间信号bram定义
    reg[DATA_W -1:0] mem[(1<<ADDR_W)-1:0]  ;//block ram
    reg [ ADDR_W -1:0] ra_buffer;
    
    
    //read 
    always  @(posedge rclk )begin
         ra_buffer<=raddr;
    end
    assign dout=mem[ra_buffer];//数据在地址后的一个周期
    //write 
    always  @(posedge wclk )begin
        if(wen)
         mem[waddr]=wdin;
    end
    initial $readmemh("bmp_256k.mem",mem);
  
 
endmodule


module generic_dpram_64Kx12(

        rclk    ,raddr,dout,

    //其他信号,举例dout
    wclk,waddr,wdin,wen
    );

    //参数定义
    parameter      ADDR_W =         16;  
    parameter      DATA_W =         12;
    //read输入信号定义
    input               rclk    ;
    input [ ADDR_W -1:0]   raddr  ; 
    //read输出信号定义
    output[DATA_W-1:0]  dout   ;

    //write输入信号定义
    input               wclk    ;
    input               wen    ; // write enable, active high
    input [ ADDR_W -1:0]   waddr  ;     
    input [ DATA_W -1:0]   wdin  ;     


    //中间信号bram定义
    reg[DATA_W -1:0] mem[(1<<ADDR_W)-1:0]  ;//block ram
    reg [ ADDR_W -1:0] ra_buffer;
    
    
    //read 
    always  @(posedge rclk )begin
         ra_buffer<=raddr;
    end
    assign dout=mem[ra_buffer];//数据在地址后的一个周期
    //write 
    always  @(posedge wclk )begin
        if(wen)
         mem[waddr]=wdin;
    end
    initial $readmemh("bmp_64k.mem",mem);
  
 
endmodule

双口RAM定义 及多个ram verilog rtl仿真
tb
按地址读出数据,测试是否初始化数据正确

module ram_dout_tb();

 
 
    parameter CNT_LEN=640*480;
    reg rst_n;

    //uut的输入信号
    reg[11:0]  wr_din  ;
    reg[18:0] wr_addr  ;
    reg wr;
    initial begin
         wr = 0;
         wr_din=0;
         wr_addr=0;
    end

    reg rd_clk;
    reg [18:0] rd_addr ;
    wire   [11:0] rd_dout;
    always  @(posedge rd_clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            rd_addr<=0;
        end
        else if(rd_addr==CNT_LEN-1)begin
            rd_addr<=0;
        end
        else begin
            rd_addr<=rd_addr+1;
        end
    end
 
   //时钟周期,单位为ns,可在此修改时钟周期。
   parameter CYCLE    = 40;

   //复位时间,此时表示复位2个时钟周期的时间。
   parameter RST_TIME = 2 ;


   vga_dpram uut(
    .  wr_clk (    rd_clk       ),
    .   wr_din(     wr_din      ),
    .   wr_addr(    wr_addr      ),
    .   wr      (   wr               ),
                          
   .  rd_clk  (   rd_clk         ),
   .  rd_addr (   rd_addr        ),
   .  rd_dout (   rd_dout        )


   );


     //生成本地时钟25M
     initial begin
         rd_clk = 0;
         forever
         #(CYCLE/2)
         rd_clk=~rd_clk;
     end

     //产生复位信号
     initial begin
         rst_n = 1;
         #2;
         rst_n = 0;
         #(CYCLE*RST_TIME);
         rst_n = 1;
     end
endmodule

数据应该在地址后一个时钟输出。
双口RAM定义 及多个ram verilog rtl仿真
双口RAM定义 及多个ram verilog rtl仿真
双口RAM定义 及多个ram verilog rtl仿真
双口RAM定义 及多个ram verilog rtl仿真
双口RAM定义 及多个ram verilog rtl仿真
抽样检测正确

相关标签: verilog