概述:此处,我以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
001 | /*-----版权声明----- |
002 | * 艾米电子工作室——让开发变得更简单 |
003 | * 网站:http://www.amy-studio.com |
004 | * 淘宝:http://amy-studio.taobao.com |
005 | * QQ(邮箱):amy-studio@qq.com |
006 | *-----文件信息----- |
007 | * 文件名称:Amy_S_lcd12864_avalon_interface.v |
008 | * 最后修改日期:3.20, 2010 |
009 | * 描述:Lcd12864的Avalon接口描述文件 |
010 | *------------------ |
011 | * 创建者:张亚峰 |
012 | * 创建日期:3.20, 2009 |
013 | * 版本:1.0 |
014 | * 描述:原始版本 |
015 | *------------------ |
016 | * 修改者: |
017 | * 修改日期: |
018 | * 版本: |
019 | * 描述: |
020 | *------------------- |
021 | */ |
022 |
023 | module Amy_S_lcd12864_avalon_interface( |
024 | // Clcok Input |
025 | input csi_clk, |
026 | input csi_reset_n, |
027 | // Avalon-MM Slave |
028 | input avs_chipselect, |
029 | input [1:0] avs_address, |
030 | input avs_write, |
031 | input [31:0] avs_writedata, |
032 | input avs_read, |
033 | output [31:0] avs_readdata, |
034 | // Conduit End |
035 | // lcd12864 interface |
036 | output reg coe_e, |
037 | output reg coe_rw, |
038 | output reg coe_rs, |
039 | inout [7:0] coe_data_io |
040 | ); |
041 |
042 | //++++++++++++++++++++++++++++++++++++++ |
043 | // 写 开始 |
044 | //++++++++++++++++++++++++++++++++++++++ |
045 | reg [7:0] coe_data_o; |
046 |
047 | always @( posedge csi_clk, negedge csi_reset_n) |
048 | begin |
049 | if (!csi_reset_n) |
050 | begin |
051 | coe_e <= 1'b0 ; |
052 | coe_rw <= 1'b0 ; |
053 | coe_rs <= 1'b0 ; |
054 | coe_data_o <= 8'b0 ; |
055 | end |
056 | else if (avs_chipselect & avs_write) |
057 | begin |
058 | case (avs_address) |
059 | 0: coe_e <= avs_writedata[0]; |
060 | 1: coe_rw <= avs_writedata[0]; |
061 | 2: coe_rs <= avs_writedata[0]; |
062 | 3: coe_data_o <= avs_writedata[7:0]; |
063 | endcase |
064 | end |
065 | end |
066 | //-------------------------------------- |
067 | // 写 结束 |
068 | //-------------------------------------- |
069 |
070 | //++++++++++++++++++++++++++++++++++++++ |
071 | // 读 开始 |
072 | //++++++++++++++++++++++++++++++++++++++ |
073 | reg [7:0] readdata_r; |
074 | wire [7:0] coe_data_i; |
075 |
076 | always @( posedge csi_clk) |
077 | if (avs_chipselect & avs_read) |
078 | begin |
079 | if (avs_address == 3) |
080 | readdata_r <= coe_data_i; |
081 | else |
082 | readdata_r <= 8'b0 ; |
083 | end |
084 | else |
085 | readdata_r <= 8'b0 ; |
086 | |
087 | assign avs_readdata = { 24'b0 , readdata_r}; |
088 | //-------------------------------------- |
089 | // 读 结束 |
090 | //-------------------------------------- |
091 |
092 |
093 | //++++++++++++++++++++++++++++++++++++++ |
094 | // 双向口 开始 |
095 | //++++++++++++++++++++++++++++++++++++++ |
096 | reg coe_data_o_en; |
097 |
098 | always @( posedge csi_clk) |
099 | if (avs_chipselect & avs_write) |
100 | coe_data_o_en <= 1'b0 ; |
101 | else if (avs_chipselect & avs_read) |
102 | coe_data_o_en <= 1'b1 ; |
103 |
104 | assign coe_data_i = coe_data_io; |
105 | assign coe_data_io = coe_data_o_en ? 8'bz : coe_data_o; |
106 | //-------------------------------------- |
107 | // 双向口 结束 |
108 | //-------------------------------------- |
109 | |
110 | 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之后就不是必须的信号,此处加上,只为和以前的版本兼容。