【28】Verilog进阶 - RAM的实现

本文详细记录了使用Verilog实现单端口RAM的过程,从最初的读写控制错误,到解决读取数据延迟和不定值问题,再到尝试组合逻辑写入RAM的编译错误,最终实现可行的RAM读写方案。作者强调了理解RAM深度的重要性,并分享了通过观察时序波形图来确定数据采集时刻的经验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VL53 单端口RAM

1 思路

简简单单,读取存储器单元值操作即可

2 功能猜想版

说明:
下面注释就是我对模块端口信号 自己猜测的理解。
因为题目并没有说清楚,甚至连参考波形都没有给出。
唉,这就完全是让人猜测呢,如果一点学术背景的人来刷题,指定不容易!!
好在,我有较为深厚的学术背景

(1)代码

`timescale 1ns/1ns

module RAM_1port(
    input clk,
    input rst,
    input enb,          //读写使能:0-写;1-读 
    input [6:0]addr,    //读写地址
    input [3:0]w_data,  //写入数据
    output wire [3:0]r_data//读出数据
);
//*************code***********//

//ROM
reg [3:0] ROM [6:0];

//写入数据
always@(posedge clk, negedge rst)begin 
    if(rst==0) ROM[addr] <=ROM[addr];
    else ROM[addr] <= (enb==0) ? w_data :ROM[addr];
end
//读出数据
reg [3:0] data_out;
always@(posedge clk, negedge rst)begin
    if(rst==0) data_out<=0;
    else data_out<= enb ? ROM[addr] : 0;
end

assign r_data =data_out;

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

(2)问题:读写控制搞反

【修改】将代码中用到enb的地方,高改低,低改高 即可

(3)仿真结果

enb=0 控制读取数据 确实无误
但是读取的数据是不对的。
在这里插入图片描述

3 不断试错版

(1)问题2:读取数据晚半拍

还是上面程序的仿真波形。
仔细观察,发现问题:
在这里插入图片描述

仔细观察上面的仿真波形,发现问题所在:人家读数据是在clk 下降沿读的

(2)解决2:用【下降沿读取数据】

代码
//读出数据
reg [3:0] data_out;
always@(negedge clk, negedge rst)begin
    if(rst==0) data_out<=0;
    else data_out<= (enb==0) ? ROM[addr] : 0;
end

assign r_data =data_out;
仿真结果

在这里插入图片描述
在这里插入图片描述
可见修改后的输出,基本上都对应上了。

(3)问题3:读出数据为不定值

但是从上面代码的仿真结果中发现了另一个问题:
当enb=1表示 写功能时,RAM的值没有写进去
噢!不对!!!这里的r_data是读RAM的值,所以写进RAM的值在这里暂且是看不到的。
所以这里的问题是从RAM中读出的数据为不定值啦
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
而此时【读数据】是下降沿有效,要么读到的是地址10要么是地址0上的值,好像更可能是地址0上的值为不定值
所以这个问题定位到,向RAM写入数据时的逻辑,看为什么导致地址0上的数据为不定值

(4)解决3:解决了很多次,但都没解决

原来写入RAM的代码为:

//写入数据
always@(posedge clk, negedge rst)begin 
    if(rst==0) ROM[addr] <= ROM[addr];
    else ROM[addr] <=enb ? w_data :ROM[addr];
end

针对这个问题,我修改了无数次可能,但最终都没有修改成功。心情被搞坏了,气炸了
最后的代码是这样的:

`timescale 1ns/1ns

module RAM_1port(
    input clk,
    input rst,
    input enb,          //读写使能:0-写;1-读 //根据提交的错误结果,知道这里逻辑是 1-写 0-读
    input [6:0
### Verilog 高级用法概述 Verilog 是一种用于描述电子系统的硬件描述语言 (HDL),广泛应用于 FPGA 和 ASIC 设计中。对于掌握 Verilog 的高级特性,理解一些复杂的设计模式和技术至关重要。 #### 跨 Die 设计 跨 Die 设计涉及到多个芯片之间的信号传输和同步问题。为了确保数据的一致性和可靠性,在不同芯片之间传递控制信号时应考虑延迟补偿机制[^1]: ```verilog // 延迟线实现 reg [7:0] delay_line; always @(posedge clk) begin delay_line <= {delay_line[6:0], input_signal}; end assign output_signal = delay_line[7]; ``` #### 多时钟域处理 多时钟域是指电路中有两个或更多独立工作的时钟源。当需要在这类环境中交换信息时,必须采取措施防止亚稳态现象造成的数据错误: ```verilog module async_fifo #(parameter WIDTH=8, DEPTH=16)( input wire wr_clk, input wire rd_clk, ... ); reg full_flag_sync_ffs[1:0]; // 同步寄存器 always @(posedge rd_clk or negedge rst_n) if (!rst_n) full_flag_sync_ffs <= 2'b00; else full_flag_sync_ffs <= {full_flag_sync_ffs[0], fifo_full}; assign sync_full_flag = full_flag_sync_ffs[1]; endmodule ``` #### 双端口 RAM 实现 双端口 RAM 提供了在同一时刻由两个不同的地址访问同一存储空间的能力。这在某些应用场景下可以显著提高性能: ```verilog module dual_port_ram( input wire wr_clk, input wire rd_clk, ... ); reg [DATA_WIDTH-1:0] ram_array [ADDR_SIZE-1:0]; always @(posedge wr_clk) if (we) ram_array[waddr] <= din; always @(posedge rd_clk) dout <= ram_array[raddr]; endmodule ``` #### FIFO 结构构建 先进先出队列(FIFO)是一种重要的缓存结构,能够有效缓解读写速度不匹配带来的瓶颈问题。下面是一个简单的异步 FIFO 示例代码片段: ```verilog module async_fifo ( input wire wr_clk, input wire rd_clk, ... ); // 写指针读指针管理逻辑... endmodule ``` #### 仲裁算法应用 在资源共享的情况下,比如多个模块竞争同一个外设接口时,则需要用到仲裁策略来决定哪个请求优先得到服务。轮询调度是最简单的一种方式: ```verilog integer i; wire grant_signals[NUM_REQUESTERS-1:0]; for(i=0; i<NUM_REQUESTERS; i=i+1)begin : gen_grant assign grant_signals[i] = requesters[i] & ~(|grant_signals[(i+1):0]); end ``` 以上就是关于 Verilog 中几个重要概念及其具体实现的例子介绍。深入理解和灵活运用这些技术可以帮助工程师们更高效地完成复杂的数字系统设计工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值