| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2019-02-27 | gingko | 初次建立 | ===== 实验十八:基于单口 RAM 的 ARM+FPGA 数据存取实验 ===== ==== 一、 实验目的与意义 ==== - 了解单口 RAM 读写的工作原理。 - 掌握单口 RAM 使用方法。 - 掌握 QuartusII 集成开发环境使用方法。 ==== 二、 实验设备及平台 ==== - iCore3 双核心板。[[https://item.taobao.com/item.htm?id=524229438677|点击购买]] - Blaster(或相同功能)仿真器和 USB 线缆。[[https://item.taobao.com/item.htm?id=554869837940|点击购买]] - Micro USB 线缆。 - QuartusII 开发平台。 - Keil MDK 开发平台。 - 装有 WIN XP(及更高版本)系统的计算机。 ==== 三、 实验原理 ==== * 实验通过Commix向STM32发送读写命令,STM32收到信息后,通过STM32F407的FSMC总线实现与 FPGA 通信,FPGA 内部建立单口 RAM 块,FPGA桥接STM32和RAM块,把 FSMC 总线发送过来的数据放入指定的地址中。本实验首先通过 Commix 向RAM 块的某些地址中写入数据,再通过 Commix 发送读命令读取这些地址的数据进行验证。实验的原理如下图所示: {{ :icore3:icore3_fpga_18_1.png?direct |实验原理图}} ==== 四、 Quartus 内部单口 RAM 块调用 ==== 1、 打开 Tools——MegaWizard Plug-In Manager. {{ :icore3:icore3_fpga_18_2.png?direct |图1}} 2、 直接点击 Next. {{ :icore3:icore3_fpga_18_3.png?direct |图2}} 3、 在方框 1、方框 2、方框 3 处如图所示做选择,在方框 4 处选择 RAM 块的路径及命 名,然后点击 Next. {{ :icore3:icore3_fpga_18_4.png?direct |图3}} 4、接下来是对单口RAM进行设置,如图中所示,设置RAM的存储位宽和存储深度,本实验设置存储宽度16bit,存储深度256个字节。这里可以把RAM想象成一个表格,每行有16个格子,总共256行,这里的每个格子相当于1个bit。然后设置例化RAM在FPGA内部占用资源的类型。因为用逻辑门例化为存储器的话占用逻辑资源较多,因此FPGA内部有专门用于构建存储器用的逻辑单元,如M9K、M144K等。本次实验选择Auto,在设计中可根据实际需求进行设置。之后是时钟的选择,这里选择单时钟,即输入输出使用同一时钟。点击next进行下一项设置。 {{ :icore3:icore3_fpga_18_5.png?direct |图4}} 5、输出信号设置和读使能信号设置。 {{ :icore3:icore3_fpga_18_6.png?direct |图5}} 6、这里选择Old Data。 {{ :icore3:icore3_fpga_18_7.png?direct |图6}} 7、设置RAM初始状态值。可以通过hex文件给例化的RAM存入初始数据。这里选择不存储初始数据,而是通过FPGA控制数据的写入。 {{ :icore3:icore3_fpga_18_8.png?direct |图7}} 8、默认设置,最后点击finish。 {{ :icore3:icore3_fpga_18_9.png?direct |图8}} {{ :icore3:icore3_fpga_18_10.png?direct |图9}} ==== 五、 代码讲解 ==== * 例化好RAM块后,即可编写代码,实现原理部分介绍的功能了。整个系统可以看做是将FPGA内部例化的RAM作为STM32的外部存储器,并通过FSMC总线对RAM进行读写操作。对于FPGA来说,只需配置好单口RAM的相关参数,并检测FSMC总线的读写信号即可。通过检测出来的读写信号进行相应的操作,从而实现STM32对FPGA例化的RAM进行读写操作的实验流程。FPGA只需根据FSMC总线信号判断出读写信号即可。代码如下: //--------------------------fsmc---------------------------// wire rd = (CS0 | RD); //提取读信号 wire wr = (CS0 | WR); //提取写信号 reg wr_clk1,wr_clk2; always @(posedge PLL_100M or negedge rst_n) begin if(!rst_n) begin wr_clk1 <= 1'd1; wr_clk2 <= 1'd1; end else {wr_clk2,wr_clk1} <= {wr_clk1,wr}; //提取写时钟 end wire clk = (!wr_clk2 | !rd); assign DB = !rd ? DB_OUT : 16'hzzzz; ==== 六、实验步骤 ==== - 把仿真器与 iCore3 的 SWD 调试口连接(直接相连或者通过转换器相连); - 将 USB-Blaster 与 iCore3 的 JTAG 调试口相连; - 将跳线帽插在 USB UART; - 把 iCore3(USB_UART)通过 Micro USB 线与计算机连接,为 iCore3 供电; - 打开 Commix 串口精灵,找到对应的 COM 端口打开; - 打开 Quartus II 开发环境,并打开实验工程; - 烧写 FPGA 程序到 iCore3 上; - 打开 Keil MDK 开发环境,并打开实验工程; - 烧写 ARM 程序到 iCore3 上; - 输入串口命令,观察实验现象。 ==== 七、 实验现象 ==== * 通过 Commix 发送写命令向 RAM 块中指定的某些地址写入数据,再通过读命令读取这 些地址中的某些数据,对比写入与读取的数据,可以知道写入数据与读取的数据相同。 * 命令格式: * 写命令:ram+空格+write+空格+address+空格+data_out+\cr\lf * 例如:ram write 123 456\cr\lf * 解析:在ram的第123个地址中写入“456”的数据。 * 读命令:ram+空格+read+空格+address+\cr\lf * 例如:ram read 123\cr\lf * 解析:读取 ram 的第 123 地址的数据。