概述:此处,我以Lcd12864(ST7920)作为范例,进行粗浅讲解,望各位网友踊跃拍砖。

 

0 软硬件环境

软件:Altera Quartus II 9.1 + Nios II  9.1 Software Build Tools for Eclipse

硬件:艾米电子EP2C8开发板(EP2C8Q208C8 + 16 bit SDRAM 64MB + EPCS4)

 

1 硬件部分

1.1 Avalon-MM接口(读作:阿窝龙妹妹接口)

Avalon Memory-Mapped接口,简称为 Avalon-MM接口,用于在存储映射系统中描述主从元件(component)的读/写接口。

图1.1 Amy_S_lcd12864 IP与System Interconnect Fabric的连线框图

图1.2 某带有Amy_S_lcd12864 IP的Avalon系统框图

1.2 从设备读写时序

请参考手册《Avalon Interface Specification》,此处略去。

1.3 HDL模块及说明

1.3.1 模块介绍

表1.1 Amy_S_lcd12864 IP的HDL源代码模块介绍

文件名称 功能描述
Amy_S_lcd12864_avalon_interface.v Amy_S_lcd12864 Avalon接口文件
1.3.2 源代码

注:本文所涉及verilog代码,是按照Verilog 2001规范编写的。Avalon信号类型命名参考图1.3。

图1.3 Naming Convention for Avalon Signal Type

1.3.2.1 Amy_S_lcd12864_avalon_interface.v
/*-----版权声明-----*     艾米电子工作室——让开发变得更简单 *     网站:http://www.amy-studio.com*     淘宝:http://amy-studio.taobao.com*     QQ(邮箱):amy-studio@qq.com*-----文件信息-----*     文件名称:Amy_S_lcd12864_avalon_interface.v*     最后修改日期:3.20, 2010*     描述:Lcd12864的Avalon接口描述文件*------------------*     创建者:张亚峰*     创建日期:3.20, 2009*     版本:1.0*     描述:原始版本*------------------*     修改者:*     修改日期:*     版本:*     描述:*-------------------*/module Amy_S_lcd12864_avalon_interface(// Clcok Inputinput         csi_clk,input         csi_reset_n,// Avalon-MM Slaveinput         avs_chipselect,input [1:0]   avs_address,input         avs_write,input [31:0]  avs_writedata,input         avs_read,output [31:0] avs_readdata,  // Conduit End // lcd12864 interfaceoutput reg    coe_e,output reg    coe_rw, output reg    coe_rs,inout [7:0]   coe_data_io
);//++++++++++++++++++++++++++++++++++++++
// 写 开始
//++++++++++++++++++++++++++++++++++++++
reg  [7:0] coe_data_o;always@(posedge csi_clk, negedge csi_reset_n)
beginif (!csi_reset_n)begin coe_e      <= 1'b0;coe_rw     <= 1'b0;coe_rs     <= 1'b0;coe_data_o <= 8'b0;endelse if (avs_chipselect & avs_write)begincase (avs_address)0: coe_e      <= avs_writedata[0];1: coe_rw     <= avs_writedata[0];2: coe_rs     <= avs_writedata[0];3: coe_data_o <= avs_writedata[7:0];endcaseend
end
//--------------------------------------
// 写 结束
//--------------------------------------//++++++++++++++++++++++++++++++++++++++
// 读 开始
//++++++++++++++++++++++++++++++++++++++
reg  [7:0] readdata_r;
wire [7:0] coe_data_i;always@(posedge csi_clk)if (avs_chipselect & avs_read)beginif (avs_address == 3)readdata_r  <= coe_data_i;else readdata_r  <= 8'b0;endelsereaddata_r <= 8'b0;assign avs_readdata = {24'b0, readdata_r};
//--------------------------------------
// 读 结束
//--------------------------------------//++++++++++++++++++++++++++++++++++++++
// 双向口 开始
//++++++++++++++++++++++++++++++++++++++
reg coe_data_o_en;always@(posedge csi_clk)if (avs_chipselect & avs_write)coe_data_o_en <= 1'b0;else if (avs_chipselect & avs_read)coe_data_o_en <= 1'b1;assign coe_data_i   = coe_data_io;
assign coe_data_io  = coe_data_o_en ? 8'bz : coe_data_o;
//--------------------------------------
// 双向口 结束
//--------------------------------------endmodule
1.3.3 一些说明

ST7920的E、RW和RS都是单向的,而DATA总线是双向的;故在此处nios既需要写数据给ST7920,又需要从ST7920读数据。

从42行到68行,即nios向ST7920写数据。注意,谁给nios写数据呢?请看图1.4。

图1.4 NII、nios cpu和ST7920通信框图

从70行到90行,是nios从ST7920读数据。由于只有DATA总线需要读,其他的管脚就不写了,呵呵。

从93行到108行,是对DATA双向总线的处理。读或写只是简单由Avalon的读、写信号来控制的。这个技巧是我从open-cores里面的基于wishbone总线的IIC从设备的IP上学到的。注意:ST7920是低速设备,此处只做简单处理;高速设备请大家自行斟酌。

还有一点需要说明,chipselect在Nios II 9.0之后就不是必须的信号,此处加上,只为和以前的版本兼容。

 

2 软件部分

表2.1 Amy_S_lcd12864 IP的C源代码模块介绍

文件名称 功能描述
Amy_S_lcd12864.h Amy_S_lcd12864 的C头文件
Amy_S_lcd12864.c Amy_S_lcd12864 的C源文件

2.1 C头文件

2.1.1 Amy_S_lcd12864.h
/*-----版权声明-----*     艾米电子工作室——让开发变得更简单 *     网站:http://www.amy-studio.com*     淘宝:http://amy-studio.taobao.com*     QQ(邮箱):amy-studio@qq.com*-----文件信息-----*     文件名称:Amy_S_lcd12864.h*     最后修改日期:3.20, 2009*     描述:Lcd12864驱动宏文件*------------------*     创建者:张亚峰*     创建日期:3.20, 2009*     版本:1.0*     描述:原始版本*------------------*     修改者:*     修改日期:*     版本:*     描述:*-------------------*/#ifndef __Amy_S_LCD12864_H__
#define __Amy_S_LCD12864_H__//++++++++++++++++++++++++++++++++++++++
// 基地址 开始
// 根据SOPC Builder设置编写
//++++++++++++++++++++++++++++++++++++++
#include "system.h"#define lcd12864_addr LCD12864_BASE
//--------------------------------------
// 基地址 开始
//--------------------------------------//++++++++++++++++++++++++++++++++++++++
// 寄存器映射 开始
// 根据HDL编写
//++++++++++++++++++++++++++++++++++++++
#include #define IOWR_LCD12864_E(base, data)     IOWR(base, 0, data)
#define IOWR_LCD12864_RW(base, data)    IOWR(base, 1, data)
#define IOWR_LCD12864_RS(base, data)    IOWR(base, 2, data)
#define IOWR_LCD12864_DATA(base, data)  IOWR(base, 3, data)
#define IORD_LCD12864_DATA(base)        IORD(base, 3)
//--------------------------------------
// 寄存器映射 结束
//--------------------------------------//++++++++++++++++++++++++++++++++++++++
// 管脚操作 开始
//++++++++++++++++++++++++++++++++++++++
#define SET_E         IOWR_LCD12864_E(lcd12864_addr, 1)
#define CLR_E         IOWR_LCD12864_E(lcd12864_addr, 0)
#define SET_RW        IOWR_LCD12864_RW(lcd12864_addr, 1)
#define CLR_RW        IOWR_LCD12864_RW(lcd12864_addr, 0)
#define SET_RS        IOWR_LCD12864_RS(lcd12864_addr, 1)
#define CLR_RS        IOWR_LCD12864_RS(lcd12864_addr, 0)
#define WR_DATA(data) IOWR_LCD12864_DATA(lcd12864_addr, data)
#define RD_DATA       IORD_LCD12864_DATA(lcd12864_addr)
//--------------------------------------
// 管脚操作 结束
//--------------------------------------//++++++++++++++++++++++++++++++++++++++
// 函数声明 开始
//++++++++++++++++++++++++++++++++++++++
extern void LCD12864_CheckBusy(void);
extern void Lcd12864_WrCmd(alt_u8 cmd);
extern void Lcd12864_WrData(alt_u8 data);
extern void Lcd12864_Init(void);
extern void Lcd12864_WrChar(alt_u8 row, alt_u8 col, alt_u8 *pCN, alt_u8 n);
//--------------------------------------
// 函数声明 结束
//--------------------------------------#endif /* __Amy_S_LCD12864_H__ */
2.1.2 一些说明

最后面的那个</io.h>是发布博客的时候带出来的,不属于头文件。

从28行到37行,是根据SOPC Builder设置编写的lcd12864的基地址,需要system.h的支持。注:system.h就是和SOPC Builder设置一一对应的;当在NII中建立工程时,system.h就根据sopcinfo(Nios II  9.1 Software Build Tools for Eclipse使用,不是Nios II 9.1 IDE)文件自动生产。

第40行到第53行,是自己编写的一些宏,这个叫Register Map(寄存器映射),以前都是单独放在一个头文件里(如xxx_regs.h)。由于NII 9.1貌似不支持HAL的自动初始化(我研究的结果是不行,不知道Altera公司有没有相关的变动声明),因此就没有向8.1那样书写HAL。注意,0、1~3是OFFSET(偏移地址),请参考HDL代码编写。

从56行到69行,是一些管脚操作的宏,这样写,主要是方便移植。大家也可以不写寄存器映射,直接写管脚操作的宏也行,注意替换哟。

实际上大家也可以使用ARM方式的寄存器访问方式,譬如

#define CS  *(volatile unsigned *) CS_BASE  // 片选信号 --低有效

这种貌似更好操作。由于我没有深入研究这种寄存器访问方式,这里就不多说了。

下面的几行和各种MCU大同小异。

2.2 C源文件

2.2.1 Amy_S_lcd12864.c
/*-----版权声明-----*     艾米电子工作室——让开发变得更简单 *     网站:http://www.amy-studio.com*     淘宝:http://amy-studio.taobao.com*     QQ(邮箱):amy-studio@qq.com*-----文件信息-----*     文件名称:Amy_S_lcd12864.c*     最后修改日期:3.20, 2009*     描述:Lcd12864驱动源文件*------------------*     创建者:张亚峰*     创建日期:3.20, 2009*     版本:1.0*     描述:原始版本*------------------*     修改者:*     修改日期:*     版本:*     描述:*-------------------*/#include "Amy_S_lcd12864.h"
#include "alt_types.h"
#include "unistd.h"void LCD12864_CheckBusy(void)
{CLR_RS;                               // 指令SET_RW;                               // 读SET_E;while((RD_DATA&0x80) == 0x80);        // 检测busy flagCLR_E;usleep(72);                           // 72us
}void Lcd12864_WrCmd(alt_u8 cmd)
{LCD12864_CheckBusy();CLR_RS;                               // 指令CLR_RW;                               // 写SET_E;WR_DATA(cmd);CLR_E;usleep(72);                           // 72us
}void Lcd12864_WrData(alt_u8 data)
{LCD12864_CheckBusy();SET_RS;                               // 数据CLR_RW;                               // 写SET_E;WR_DATA(data);CLR_E;usleep(72);                           // 72us
}void Lcd12864_Init(void)
{usleep(40*1000);Lcd12864_WrCmd(0x30);                 // 8bitusleep(100);Lcd12864_WrCmd(0x30);                 // basic functionusleep(37);Lcd12864_WrCmd(0x0F);                 // 整体显示开 游标开 反白usleep(100);Lcd12864_WrCmd(0x10);                 // 游标左移usleep(100);Lcd12864_WrCmd(0x01);usleep(10*1000);Lcd12864_WrCmd(0x06);                 // 画面整体右移
}void Lcd12864_WrChar(alt_u8 row, alt_u8 col, alt_u8 *pCN, alt_u8 n)
{alt_u8 i, addr;row &= 0x03;                          // row < 4col &= 0x07;                          // col < 8switch(row){case 0: addr = 0x80; break;case 1: addr = 0x90; break;case 2: addr = 0x88; break;case 3: addr = 0x98; break;}addr += col;Lcd12864_WrCmd(addr);for(i=0; i<2*n; i++){Lcd12864_WrData(pCN[i]);            // 写字符数据}
}
2.2.2 一些说明

呵呵,这个就不说明了,大家自己看。

 

3 使用举例

注意:9.1环境。

3.1 在SOPC Builder中添加组件

从File-New Component..打开Component Editor,单击HDL Files标签,添加所编写的HDL文件。如图3.1所示。

图3.1 添加HDL文件

由于所编写的HDL完全是按照规范的,因此直接单击Component Wizard即可,编写IP信息,如图3.2所示。

图3.2 编写IP信息

单击Finish,IP添加成功,如图3.3所示。

图3.4 添加成功后的IP

3.2 在SOPC Builder中例化

这个就不多说了,直接上图,请看图3.5。

图3.5 例化后的IP 1

注意lcd12864是随便起的名字哟,只要不叫IP的名字(Ams_S_lcd12864)就行。

图3.6  例化后的IP 2

3.3 在Nios II中的使用范例

先将Amy_S_lcd12864.h和Amy_S_lcd12864.c拷贝到软件工程内。

3.3.1 使用范例main.c
/*-----版权声明-----*     艾米电子工作室——让开发变得更简单 *     网站:http://www.amy-studio.com*     淘宝:http://amy-studio.taobao.com*     QQ(邮箱):amy-studio@qq.com*-----文件信息-----*     文件名称:main.c*     最后修改日期:3.20, 2009*     描述:Lcd12864测试文件*------------------*     创建者:张亚峰*     创建日期:3.20, 2009*     版本:1.0*     描述:原始版本*------------------*     修改者:*     修改日期:*     版本:*     描述:*-------------------*/ #include                      // strlen()
#include "Amy_S_lcd12864.h"             // 根据SOPC Builder的设置,修改该头文件中的Lcd12864基地址int main()
{Lcd12864_Init();                      // 初始化Lcd12864Lcd12864_WrChar(0, 0, "这不是单片机吗?", strlen("这不是单片机吗?")>>1);Lcd12864_WrChar(1, 0, "这就是单片机呀。", strlen("这就是单片机呀。")>>1);Lcd12864_WrChar(2, 0, "艾米电子出品。", strlen("艾米电子出品。")>>1);Lcd12864_WrChar(2, 0, "艾米电子出品。", strlen("艾米电子出品。")>>1);Lcd12864_WrChar(3, 0, "Amy-studio Pub.", strlen("Amy-studio Pub.")>>1);return 0;
}
3.3.2 一些说明

最后面的那个</string.h>是发布博客的时候带出来的,不属于头文件。

3.4 使用效果

图3.7 Amy_S_lcd12864 IP使用效果

4 参考资料

1.李兰英等.Nios II嵌入式软核SOPC设计原理及应用.北京航空航天大学出版社.2006

2.周立功等.SOPC嵌入式系统实验教程(一).北京航空航天大学出版社.2006

3.蔡伟刚.Nios II软件架构解析.西安电子科技大学出版社.2007

4.Altera Handbook.Quartus II Handbook Volume4: SOPC Builder.2009

5.Altera Handbook.Avalon Interface Specifications.2009

6.Altera Handbook.HAL API Reference.2009

7.Altera Website.Avalon Component Interfaces Supported in the Component Editor Version 7.2 and Later

8.Altera Website..Examples of Changes to Typical Avalon Interfaces for the Component Editor Version 7.2 and Later

9. 小時不識月.七段数码管动态显示IP的研究及设计.(Nios II)(SOPC Builder).2009

转载于:https://www.cnblogs.com/yuphone/archive/2010/03/25/1694547.html

[原创].怎样制作一个简单ip,以方便在Quartus II和Nios II中使用?相关推荐

  1. [转载].怎样制作一个简单ip,以方便在Quartus II和Nios II中使用?

    1 硬件部分 1.1 Avalon-MM接口(读作:阿窝龙妹妹接口) Avalon Memory-Mapped接口,简称为 Avalon-MM接口,用于在存储映射系统中描述主从元件(component ...

  2. 32位mips运算器logisim_大神教你制作一个简单的16位CPU

    如何制作一个简单的16位CPU,首先我们要明确CPU是做什么的,想必各位都比我清楚,百度的资料也很全..... 如果想要制作一个CPU,首先得明白下计算机的组成结构(或者计算机的替代品,因为并不是只有 ...

  3. 如何制作一个简单的16位CPU

    http://www.acfun.tv/v/ac362187 我果然标题党了吗?不是转载那本日本人写的书啊!纯手打表诚意,希望猴子给过,第一次投稿各位大神帮帮忙...... 如何制作一个简单的16位C ...

  4. 使用Hprose制作一个简单的分布式应用程序

    2019独角兽企业重金招聘Python工程师标准>>> 使用Hprose制作一个简单的分布式应用程序只需要几分钟的时间.本文将用一个简单的实例来带您快速浏览使用Hprose for ...

  5. 如何用php做每天日程安排,PHP开发制作一个简单的活动日程表Calendar,日程表calendar...

    PHP开发制作一个简单的活动日程表Calendar,日程表calendar 材料取之深入PHP与JQuery开发,这本书实际上就是讲述一个活动日程表. 此文章适合从其它语言(如java,C++,pyt ...

  6. 使用 Flutter 制作一个简单的笑话生成器应用程序

    在本教程中,我将向您展示如何使用 Flutter 制作一个简单的笑话生成器应用程序 对于这个项目,我们将从 RESTful API 获取数据 API的链接: 随机笑话 对于这个项目,我不会关注应用程序 ...

  7. 实例学习SSIS(一)--制作一个简单的ETL包

    http://www.cnblogs.com/tenghoo/archive/2009/10/archive/2009/10/archive/2009/10/16/ssis_lookup.html 导 ...

  8. python计算器教程,用Python程序制作一个简单的计算器

    用Python程序制作一个简单的计算器 在此示例中,您将学习创建一个简单的计算器,该计算器可以根据用户的输入进行加,减,乘或除. 要理解此示例,您应该了解以下Python编程主题: 通过函数创建简单计 ...

  9. (译)如何使用GameCenter制作一个简单的多人游戏教程:第一部分

    免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作 ...

最新文章

  1. 在windows程序中嵌入Lua脚本引擎--编写自己的Lua库
  2. Python wordcloud库使用说明
  3. IE提示console未定义问题解决
  4. 复习java基础第二天(异常处理)
  5. Python numpy函数hstack() vstack() stack() dstack() vsplit() concatenate()
  6. 1.23 实例:正则表达式验证IP地址
  7. k8s容器探针:就绪检测、存活检测
  8. 算法训练营01-学习总览
  9. mongodb 性能测试_MongoDB性能测试
  10. nacos配置ap_Nacos 1.0.0 功能预览
  11. 【JZOJ4819】【NOIP2016提高A组模拟10.15】算循环
  12. mysql计算用户平均下单周期
  13. Spark的性能调优
  14. HTML中的表格和表单控件详解
  15. 什么是ooa,oop
  16. Android Jni开发,报com.android.ide.common.process.ProcessException: Error configuring 错误解决方案...
  17. ELAS_ROS算法在KITTI数据集上生成稠密点云
  18. php在线拍照代码,PHP+Javascript实现在线拍照功能实例_php技巧
  19. 3dmax室内模型导入Unity3d 快速烘焙光照【2020】
  20. ruby语言学习-开启篇

热门文章

  1. 使用JSON JavaScriptSerializer 进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength属性...
  2. 使用DeviceOne实现微信小程序功能
  3. 给公司员工上的培训1——微观规范
  4. 初级和高级产品运营的分水岭指标:大局观和节奏感
  5. 互联网金融产品需要什么样的产品经理?
  6. PMCAFF | 智能硬件2.0时代:用户导向,内容连接
  7. 【pmcaff】从 Lending Club 的 IPO,我们能学到些什么
  8. Android Handler原理
  9. 地形图绘制过程中的自然斜坡、陡坎、斜坡的区别
  10. Micropython Turnipbit自动窗帘模拟系统