【牛客网刷题系列 之 Verilog进阶挑战】~ 存储器专题

0. 前言

关于RAM的分类以及相关知识,可以参考以下几篇文章:
1. BRAM和DRAM
2. 细分与归类
在这里插入图片描述
在这里插入图片描述

1. VL53 单端口RAM

1.1 题目描述

设计一个单端口RAM,它有: 写接口,读接口,地址接口,时钟接口和复位;存储宽度是4位,深度128。

注意rst为低电平复位

1.1.1 信号示意图

在这里插入图片描述

1.1.2 波形示意图

1.1.3 输入描述

输入信号 enb, clk, rst addr w_data
类型 wire
在testbench中,clk为周期5ns的时钟,rst为低电平复位

1.1.4 输出描述

输出信号 r_data
类型 wire

1.2 解题思路

该题是一个单端口RAM,读和写是不能同时进行的,要么读,要么写,这里还有一个需要区分的点,那就是关于块RAM(BRAM)和分布式RAM(DRAM),记住一点区别就行,BRAM采用的是读写同步时钟,而DRAM采用的是读写不同步时钟,也就是说,读和写是异步的。

关于手撕RAM,记住结构就行,参考代码实现!!!

1.3 代码实现

`timescale 1ns/1ns

module RAM_1port(
    input clk,
    input rst,
    input enb,
    input [6:0]addr,
    input [3:0]w_data,
    output wire [3:0]r_data
);
//*************code***********//
    // [位宽] name [深度] ===> 表示单端口分布式ram,特点是读写时钟异步
    //或者说读需要时钟,写不需要时钟。
    reg [3:0] s_dram [127:0]; 
    
    //for 或者 generate...for都可以实现,区别在于后者需要将always块包住,前者写在always块里边
    integer i; 
    always @ (posedge clk or negedge rst) begin
        if(!rst) begin
            for(i = 0; i < 128; i = i+1) begin
                s_dram[i] <= 4'd0;
            end
        end
        else begin
            if(enb) begin
                s_dram[addr] <= w_data; 
            end
            else begin
                s_dram[addr] <= s_dram[addr];
            end
        end
    end
    
    assign r_data = enb ? 4'd0 : s_dram[addr];

//*************code***********//
endmodule

1.4 测试文件

待更新。。。

1.5 仿真波形

待更新。。。

2. VL54 RAM的简单实现

2.1 题目描述

实现一个深度为8,位宽为4bit的双端口RAM,数据全部初始化为0000。具有两组端口,分别用于读数据和写数据,读写操作可以同时进行。当读数据指示信号read_en有效时,通过读地址信号read_addr读取相应位置的数据read_data,并输出;当写数据指示信号write_en有效时,通过写地址信号write_addr 和写数据write-data,向对应位置写入相应的数据。

2.1.1 信号示意图

在这里插入图片描述

2.1.2 波形示意图

无

2.1.3 输入描述

clk:系统时钟信号
rst_n:异步复位信号,低电平有效
read_en,write_en:单比特信号,读/写使能信号,表示进行读/写操作
read_addr,write_addr:8比特位宽的信号,表示读/写操作对应的地址
write_data:4比特位宽的信号,在执行写操作时写入RAM的数据

2.1.4 输出描述

read_data:4比特位宽的信号,在执行读操作时从RAM中读出的数据

2.2 解题思路

该题是一个双端口RAM,读和写可以同时进行的,需要注意的是,写使能为0时,写入的是0哦!读使能为0时,读出的也是0哦!

关于手撕RAM,记住结构就行,参考代码实现!!!

2.3 代码实现

`timescale 1ns/1ns
module ram_mod(
	input clk,
	input rst_n,
	
	input write_en,
	input [7:0]write_addr,
	input [3:0]write_data,
	
	input read_en,
	input [7:0]read_addr,
	output reg [3:0]read_data
);
    reg [3:0]d_dram[7:0];
    //write
    integer i;
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            for(i=0; i<8; i=i+1) begin
                d_dram[write_addr] <= 4'd0; 
            end
        end
        else begin
            if(write_en) begin
                d_dram[write_addr] <= write_data; 
            end
            else begin
                d_dram[write_addr] <= 4'd0;  // 注意:写使能为0时,写入的是0哦!
            end
        end
    end
    //read
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            read_data <= 4'd0;
        end
        else begin
            if(read_en) begin
                read_data <= d_dram[read_addr];
            end
            else begin
                read_data <= 4'd0; // 注意:读使能为0时,读出的也是0哦!
            end
        end
    end
endmodule

2.4 测试文件

待更新。。。

2.5 仿真波形

待更新。。。

声明

本人所有系列的文章,仅供学习,不可商用,如有侵权,请告知,立删!!!

本人主要是记录学习过程,以供自己回头复习,再就是提供给后人参考,不喜勿喷!!!

如果觉得对你有用的话,记得收藏+评论!!!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值