准备把de2-115上面的存储器外设都给驱动一下,首先就先从简单的sram开始。 Sram的驱动比较简单,和FPGA内部的ram差不多,只不过不是由时钟来控制读写,而是由控制信号来控制读写,读写都很快,基本上一个时钟就可以读取和写入数据,当然这时钟不能太快,不能超过芯片规定的最小时间。 首先肯定是先看datasheet。
首先看看sram的结构框图。 有20位地址总线,对地址进行译码,得到存储器的单元,然后根据控制电路,判断各个控制信号,从而判定是读还是写操作。读的话,数据线16位就是输出,输出数据。如果是写的话,数据线就是输入,从外部接收数据。 这里数据线高8位和低8位是分开的,因为这里有一个位屏蔽功能,可以屏蔽高8位数据线或者是屏蔽低8位数据线。 具体看芯片的真值表就知道了。
从真值表就可以看出芯片的功能了。
上图是管脚说明。 下面就是关键的时序图了。因为要驱动它的话,是肯定要按照规定的时序来的。 首先是读时序。
考虑通用的方式,即CE和OE来控制。而不是直接将OE和CE使能。 先解读下时序: 在地址数据发送后,要过10ns时间后,但是OE拉低6.5ns时间,并且CE拉低10ns时间,数据数据才是有效数据,当然要读数据的话,需要将OE和CE拉低,同时不要忘记WE要拉高,表示是读数据。 第二次读数据,要10ns之后,所以这个10ns就是读取数据的最小时间,才能发送地址。然后OE和CE要满足上图的保持时间。 总体来说,这个时序图还是很简单的。 然后是写的时序,
这时序图也是很简单的。写时候,OE为高为低都是可以的。 写数据间隔也是10ns,在写控制发出后,数据在5ns后为输入有效,且数据要有6ns的建立时间,保持时间可以为0. 搞定时序图后,就开始进行程序的编写了。。 首先是搞定sram的底层驱动。 首先是信号列表。 [color=blue !important][size=1em]
从注释可以看出各个信号的作用。 这里采用状态机来进行控制,首先是定义状态 [color=blue !important][size=1em]
定义了5个状态。看名字就知道是干什么的了。。。 状态机采用二段式设计。 核心代码如下。 [color=blue !important][size=1em]
大致说明一下。 在idle_state:如果判断start信号有效的话,就跳转到发送地址状态。 在send_address_state:这个状态就是将OE和CE给拉低。然后依据命令是读还是写,进行判断跳转到读还是写状态。 在write_state:保持OE,CE为低,同时拉低WE。然后状态跳转到finish_state。 在read_state:保持OE,CE为低,把sram_data上的数据给读取进来。然后状态跳转到finish_state. 在finish_state:就将finish信号给置1 ,然后状态跳转。 整个状态机设计是很简单的。就是要注意各个信号的时序,满足手册上要求的时序,因为系统时钟很慢,只有50M,周期为20ns,完全满足手册上要求的时序。 用状态机设计很简单,但是也有一个问题就是读写太慢了。。手册上写的是10ns就可以进行一次读写,但是这里设计的需要4个时钟,即80ns才能进行一次读写。 程序在说明一下,关于sram_data的处理,因为这个信号是双向的。 assign sram_data = command ? 16'bz : write_data; 这里使用的是双向口的通用处理方法,使用asignn赋值,因为command为1的时候,操作是读数据,所以这个时候赋值为高阻z,就表明是输入了。为0表示写数据,那么就赋值为write_data,作为输出,输出的值由write_data决定。 下面来对这个模块进行仿真看看。 核心的测试代码: [color=blue !important][size=1em]
第一个repeat是写数据,这里就观测写的数据是不是和sram_data的值一样的,这个时候sram_data是作为输出的。 第二个repeat是读数据,这里就观测读的数据是不是和sram_data_reg一样的,这个时候sram_data是作为输入的,而输入的值由sram_data_reg决定的。 对于testbench,最后结束的时候,最好用$stop,暂停仿真,不然仿真就一直继续下去了。。 使用modelsim仿真,因为quartus只能用modelsim仿真。
先观察黄线左边的部分,这部分是写数据。就看写的数据和sram_data是不是一样的,发现是一样的。说明功能正确。 然后观察黄线右边的部分,这部分是读数据。就看读的数据是不是和sram_data_reg一样的。发现sram_data_reg和sram_data值一样,这个肯定是当然的,然后有和read_data一样的。说明功能正确。 然后来看看时序部分: 先看写数据。
这个时钟周期是20ns。 Start为高,表明操作开始。这个时候地址数据已经送出,CE,OE,WE持续20ns的高电平,然后持续40ns的低电平,最后才拉高,是符合写的时序的,而且余量还很多。 在看读数据:
Start为高,表明操作开始。这个时候地址数据已经送出,CE,OE持续20ns的高电平,然后拉低,持续40ns的低电平,最后才拉高。也是符合读的时序的,而且余量也很多。 按照仿真的情况来看的话,似乎功能是正确的。那么就写个简单的顶层代码,对sram 驱动。 代码功能也很简单,每隔200ms对sram写一个数据,然后将刚写数据读出来,然后赋值给led。然后sram地址加1,写的数据也加1.
|
有这个完整文档吗?有的话,麻烦发下820632815@qq.com