FPGA基础设计(八):串口收发之RAM存储

avatar
作者
筋斗云
阅读量:1

串口收发之RAM存储

前言

实现上位机通过串口发送数据到FPGA,FPGA接收到数据后将其存储在RAM的一段连续空间中,然后通过按键触发读出RAM数据,再通过串口发送到上位机。

整体设计

在这里插入图片描述

模块划分

1、串口接收模块;
2、按键消抖模块
3、创建RAM IP核模块
4、RAM IP核控制模块;
5、串口发送模块。
前面已经设计好了串口发送模块,串口接收模块和按键消抖模块,还剩RAM IP的创建和控制RAM模块的设计。

控制RAM读写的逻辑

1、简易双端口RAM,有两组地址:写地址wraddress、读地址rdaddress
2、只设置了写使能wren,没有设置读使能;
3、设置单时钟模式clock来控制所有寄存器,而且没有设置时钟使能 ;
4、data:要写入RAM的数据、q:RAM读出的数据。

1、控制写RAM

当需要写入数据时,把wren信号拉高的同时,给出写地址rdaddress和写数据data[7:0],数据就会按照指定的地址写入对应的存储单元;

   具体而言,FPGA接收到数据后将其存储在双口RAM的一段连续空间中,需要设计wren写使能的同时给一个wraddress写地址自加的控制;
   实现:在串口接收模块中,每接收一帧数据后会有一个时钟脉冲的标志信号Rx_Done表示数据接收完成,则Rx_Done作为写地址自加条件,同时作为写使能信号;写第一个字节时,直接写在地址0,然后出现Rx_Done信号,写地址wraddress加1,这样接收到的字节存储在一段连续空间中。

       always@(posedge Clk or negedge Rst_n)          if(!Rst_n)            wraddress <= 8'b0; 		 else if(Rx_Done)            wraddress <= wraddress + 1'b1; 	     else             wraddress <= wraddress;			 

2、控制读RAM

当需要读出数据时,这里没有设置读使能信号,直接给出当前读地址rdaddress,输出端口q[7:0]就会根据当前指定的地址输出对应存储单元的数据。

如何将数据连续发送出去
q始终连接串口发送模块的数据输入;
开始时读地址为0,输出端q为地址0对应的存储单元中的数据,第一次按键按下,Send_en使能将q端数据发送出去,然后触发Tx_Done,读地址加1,同时又作为Send_en的使能条件,将q对应的第二个字节发送出去,这样连续地读出RAM中数据。
串口使能发送Send_en的触发
第一次按键按下,Send_en使能将q端数据发送出去;
后续Send_en使能是上一帧数据发送完成标注Tx_Done和按键状态Send_flag共同触发。
为什么读RAM时候可以连续的读?
连续的读也就说明Send_en信号持续有效。上面也说了Send_en使能是由当前按键状态和上一帧数据发送完成标志信号Tx_Done共同触发,当第一次按下按键Send_flag就持续有效,所以当第一帧发送完成出现Tx_Done,然后触发Send_en使能,接着就继续发送下一帧,发送完成又会出现Tx_Done,则连续的读。
为什么将Send_en的触发信号(Send_flag & !Tx_Done) 寄存两拍
在对RAM IP进行仿真时,读出的数据总是延时对应的存储地址两拍。

RAM IP核

M9K存储器模块

通过对M9K存储器模块进行配置,可实现各种存储器功能:RAM、移位寄存器、ROM、FIFO。
下面是M9K存储器模块支持的模式

  1. 单端口RAM
    只有一组地址线,这组地址线控制着写数据端口和读数据端口;
    支持从单一地址上的异时读写操作;
  2. 简单双端口RAM
    有两组地址线,分别控制着写数据端口和读数据端口;
    支持不同位置的同时读写操作;
  3. 真正双端口RAM
    与简单双端口RAM相比,两个数据端口都可用做读/写;
    真双端口模式支持两个端口操作的任意组合:在两个不同时钟频率上的两个读操作、两个写操作、一个读操作和一个写操作。

简单双端口RAM端口框图

管脚说明
data:RAM写数据端口
wraddress:RAM写地址端口
wren:写使能信号,高电平有效
bytenena:字节使能控制,该功能屏蔽了输入数据,这样仅写入数据中指定字节,未被写入的字节保留之前写入的值【创建IP这个功能可选】
wr_addressstall、rd_addressstall:地址使能控制,为高电平时,有效地址时钟会保持之前的地址【创建IP时可选】;
wrclock、rdclock:输入与输出时钟,输入时钟控制存储器模块的所有输入寄存器,包括data、wraddress、wren、rden寄存器;输出时钟控制数据q寄存器;
wrclocken、rdclocken:使能输入输出时钟;
rdaddress:RAM读地址端口;
rden:读使能信号,高电平有效;
q:RAM读数据端口;
aclr:异步复位信号,对RAM中数据进行清零操作,高电平有效。

这里创建的RAM非常简易,实现基本的读写操作即可

1、简易双端口RAM,有两组地址:写地址wraddress、读地址rdaddress
2、只设置了写使能wren,没有设置读使能;
3、设置单时钟模式clock来控制所有寄存器,而且没有设置时钟使能 ;
4、data:要写入RAM的数据、q:RAM读出的数据。

创建RAM IP核

1、选择双端口RAM的IP
在这里插入图片描述
2、设置双端口RAM一个为读端口和一个为写端口【简单双端口RAM】
设置储存器大小的方式为按照字数确定
在这里插入图片描述
3、设置存储器容量;端口位宽为8【存储串口接收的一个字节数据】;
在这里插入图片描述
4、选择单时钟模式,即通过单时钟clock和一个时钟使能信号控制存储块所有的寄存器;
不创建读使能信号
在这里插入图片描述
5、对输出端口进行寄存;不创建时钟使能信号;不创建异步复位信号【是对RAM中的数据清零操作,本次实验不需要清零】
在这里插入图片描述
6、该页面指定在对RAM进行写操作时,读数据输出选择。
具体而言,写操作期间,RAM输出行为是可以配置的。如果在写操作期间激活了rden信号,则RAM输出端会显示相应地址上正在写入的数据【选择New Data】,或者原有的旧数据【Old memory contents appear】;如果在rden信号未激活的情况下执行写操作,那么RAM输出端将保留它们在最近的rden信号有效期间所保留的值。
本文没有使用rden信号,而且先把数据全部写入到RAM中,然后再一个字节一个字节的读出来,所以不考虑同时读写操作,就像选择了I do not care一样。那么如何读出对应地址上的存储单元中的数据呢?【具体看控制RAM读写模块设计】
在这里插入图片描述
7、创建RAM IP核,可以进行初始化也可以不进行;而创建ROM IP核必须进行初始化。
在这里插入图片描述
至此简易双端口RAM IP核已创建完毕,可以进行简单的测试.

IP核测试

输出q延时读地址两拍,所以在设计的时候要进行同步处理。
在这里插入图片描述

延时两拍的原因:
设计中使用锁存器的原因,会导致延时一拍;
创建IP核的时候,q被寄存了一拍,如下图,如果不勾选则只延时一拍。
在这里插入图片描述
在这里插入图片描述

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!