你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

FPGA设计——RAM的实现方法

[复制链接]
gaosmile 发布时间:2020-11-14 14:43
       RAM是用来在程序运行中存放随机变量的数据空间,使用时可以利用 Quartus II 的LPM功能实现RAM的定制。       软件环境:Quartus II 11.0
       操作系统:win7
      

实现方法一:利用LPM_RAM

利用LPM_RAM:     1、首先准备好存储器初始化文件,即.mif文件。
如何生成mif文件?如下:            
mif文件就是存储器初始化文件,即memory initialization file,用来配置RAM或ROM 中的数据。生成 Quartus II 11.0可用的mif文件,有如下几种方式:

方法A:利用Quartus自带的mif编辑器      
优点:对于小容量RAM可以快速方便的完成mif文件的编辑工作,不需要第三方软件的编辑;      
缺点:一旦数据量过大,一个一个的输入会使人崩溃;       使用方法:在quartus中,【file】/【new】,选择Memory Initialization file,弹出如下窗口:   
    微信图片_20201114143129.png       
Number of words:可寻址的存储单元数,对于8bit地址线,此处选择256;      
words size:存储单元宽度,8bit;   
然后点击“OK”.
    微信图片_20201114143125.jpg       
* 在表格中输入初始化数据;   * 右键单击左侧地址值,可以修改地址和数据的显示格式;  * 表中任一数据的地址=列值+行值,如图中蓝色单元的地址=24+4=28。         对每个单元填写初始值之后,将文件保存即可。
      
方法B:利用mif软件来生成      
无论使用什么编辑器,必须保证mif文件的格式如下:冒号左边是地址,右边是数据;分号结尾;  

  1. DEPTH = 256;  
  2. WIDTH = 8;  
  3. ADDRESS_RADIX = HEX;  
  4. DATA_RADIX = HEX;  
  5. CONTENT  
  6. BEGIN  
  7. 0000 : 0000;  
  8. 0001 : 0000;  
  9. 0002 : 0000;
  10.   
  11. ……(此处省略一千字*.*)  
  12. 00FA : 00FF;  
  13. 00FB : 00FF;  
  14. 00FC : 00FF;  
  15. 00FD : 00FF;  
  16. 00FE : 00FF;  
  17. 00FF : 00FF; 
  18. END;
复制代码

这里推荐一款mif生成器:Mif_Maker2010.exe,可以在公众号内部获取对应软件安装包;这里超链接一下。
Vivado 2017.2 安装教程(含多版本各类安装包)
软件使用方法见如下:      
(1) 打开软件,【文件】/【新建】;   

(2) 设置全局参数


微信图片_20201114143121.png
微信图片_20201114143118.png      
(3) 生成波形
以生成正弦波为例:【设定波形】/【正弦波】
    微信图片_20201114143113.jpg   
(4) 修改波形
【手绘波形】/【线条】,鼠标左键选择两个起点,鼠标右键结束,即可绘制任意波形;
绘制完毕后,再次选择【手绘波形】/【取消手绘】,结束绘制状态。
      
微信图片_20201114143110.jpg
(5) 保存文件。
方法C:使用高级语言          
用 C 语言或者 matlab 语言等来生成,C 语言生成代码如下:本代码生成一个正弦波的数据波形,保存在 TestMif.mif 中。

  1. #include <stdio.h>
  2. #include <math.h>

  3. #define PI 3.141592
  4. #define DEPTH 128     /*数据深度,即存储单元的个数*/
  5. #define WIDTH 8       /*存储单元的宽度*/

  6. int main(void)
  7. {
  8.    int i,temp;
  9.    float s;

  10.    FILE *fp;
  11.    fp = fopen("TestMif.mif","w");   /*文件名随意,但扩展名必须为.mif*/
  12.    if(NULL==fp)
  13.        printf("Can not creat file!\r\n");
  14.    else
  15.    {
  16.        printf("File created successfully!\n");
  17.        /*
  18.        *    生成文件头:注意不要忘了“;”
  19.        */
  20.        fprintf(fp,"DEPTH = %d;\n",DEPTH);
  21.        fprintf(fp,"WIDTH = %d;\n",WIDTH);
  22.        fprintf(fp,"ADDRESS_RADIX = HEX;\n");
  23.        fprintf(fp,"DATA_RADIX = HEX;\n");
  24.        fprintf(fp,"CONTENT\n");
  25.        fprintf(fp,"BEGIN\n");

  26.        /*
  27.        * 以十六进制输出地址和数据
  28.        */
  29.        for(i=0;i<DEPTH;i++)
  30.        {
  31.             /*周期为128个点的正弦波*/
  32.            s = sin(PI*i/64);   
  33.            /*将-1~1之间的正弦波的值扩展到0-255之间*/
  34.            temp = (int)((s+1)*255/2);
  35.            /*以十六进制输出地址和数据*/
  36.            fprintf(fp,"%x\t:\t%x;\n",i,temp);
  37.        }//end for
  38.       
  39.        fprintf(fp,"END;\n");
  40.        fclose(fp);
  41.    }
  42. }  
复制代码
 
验证生成的数据是否正确:用记事本打开生成的mif文件,同时用 Quartus 打开 mif文件,内容如下:
微信图片_20201114143106.jpg               
能成功导入,且数据一致,说明生成正确。     
前面的推荐的软件的使用方法以及mif文件生成完毕后,开始接下来的设计。      
本篇预先生成了一个正弦波的数据文件,TEST1.mif,可以在 Quartus II 中打开,以便查看内容:【file】/【open】,在文件类型中选择memory files,打开TEST1.mif,内容如下:
微信图片_20201114143100.jpg          

2、生成LPM_RAM块      
1)在Quartus II 中,【tools】/【megawizard plugin manager】,打开向导,选择【memory compiler】文件夹下的RAM:这里选择单口RAM,
即:RAM:1-PORT,命名为RAM1P;
微信图片_20201114142914.jpg            
2)设置存储深度为128,数据宽度为8bit、选择嵌入式M4K RAM实现、使用单时钟方案;       微信图片_20201114142917.jpg


3)取消选择“数据输出锁存”,不需要时钟使能端;
微信图片_20201114142921.png      
4)使用mif初始化该RAM块、允许“在系统(In System)存储器读写”,并将此RAM的ID设置为RAM1;
* 载入前面生成的存储器初始化文件:TEST1.mif;
* ID主要用于多RAM系统时,对不同RAM的识别,此处命名为RAM1;
* 关于“在系统存储器读写”的含义,各位大侠可以自行查阅资料。
微信图片_20201114142925.jpg       
经过以上设置,即可生成一个名字为RAM1P.v的文件,以后就可以对其进行例化和使用。

3、对RAM1P.v进行例化
对RAM1P.v进行例化,就可以使用,例化方法如下:
微信图片_20201114142928.png       
推荐使用Verilog文本的方式进行例化,十分不赞成用原理图的方式来例化各个模块。      
生成的RTL图:
       微信图片_20201114142932.png
4、对该RAM块进行仿真
对该RAM块进行仿真,以便了解端口的特性:
微信图片_20201114142937.png    
* 由于使用的时钟方案为单时钟(single clock),因此无论wren=0还是1,Q都输出address指定的地址中的数据;可以从Verilog描述中看出这是利用assign语句实现的(verilog代码见下文)。      
* 当wren=1时,将数据输入端data的数据写入到address指定的存储单元内。
         
输出的数据依次为0x80,0x86,0x8c,0x92……,对比前文所显示的mif文件内容,可以验证mif文件已经成功导入,而接下来输出的数据0x0c、0x0d、0x0c、0x0c,是在wren=1期间,由数据输入端data写入到地址04、05、06、07中的数据,接下来继续输出0xb0、0xb6……,则仍然为 mif 中对应地址的初始化数据。      
说明:在编译过程中,如果使用 cyclone II 器件,可能会出现错误“Error: M4K memory block WYSIWYG primitive……”,解决办法如下:【ASSIGNMENTS 】/【 SETTING】,找到如下位置,在name中输入“CYCLONEII_SAFE_WRITE”,在DEFAULT SETTING中输入“VERIFIED_SAFE”;  
然后点击add按钮:   
    微信图片_20201114142941.jpg      

方法二、使用verilog纯文本的描述方式


生成同样功能的RAM块,代码如下:
微信图片_20201114142946.png       
注意此时mif文件载入RAM的方法,是利用文本描述的方式实现的,此种方式有一个缺点,就是不能在modelsim中进行仿真:      (*  ram_init_file = "TEST1.mif " *)  reg [7:0] mem[127:0];      
对比两种方法的优缺点:      
微信图片_20201114142949.jpg           
经过 Quartus II 的编译报告可以看出,方法二比方法一相比,占用了很多的LE,同时还使用了1024个register,因此方法二是十分不经济的,这里给出只是提供一个参考,便于理解LPM_RAM的工作方式,应用时,建议使用方法一来构建RAM。

收藏 评论0 发布时间:2020-11-14 14:43

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版