资源描述
SOPC课程设计报告
NIOSII软核的点阵控制设计
2015.7.4
引言
当今,数字系统的设计可以直接面向用户的需求,根据系统功能的要求,从上到下逐层完成相应的描述、综合、优化、仿真与验证,直到生成器件。而FPGA(Field Programmable Gate Array,现场可编程门镇列)以设计灵活及速度快的特点,在数字专用集成电路的设计中得到了广泛应用。
一、实验内容
本实验要求完成的任务是利用 Nios 软核处理器为核心控制器,在软核 CPU 中添加点阵控制接口并搭建对应电路,利用软件控制点阵的运行,在点阵的循环显示每个组员的名字、学号等信息。
二、点阵显示原理
1 点阵模块说明
此设计采用4块8*8的点阵块组成16*16的点阵显示模块
1.1 8*8点阵块工作原理
如图1所示。8*8点阵块工作方式:Q端加正电压,COM端接地时发光二管点亮。例如,当COM8接地且Q1~Q8分别接高电平时,第一行亮。同理,当COM7接地,Q1~Q8分别接高电平时,第二行亮。依此类推。当Q5端加高电平时,分别让COM1~COM8接地,第一列亮。其它列依此类推。
1.2 16*16点阵模块
用4块8*8的点阵块组成16*16的点阵模块显示汉字,连接关系如图2所示。Q0~Q15成为点阵块的行线,COM0~COM15形成点阵块的列线。
1.3 行列驱动
由循环计数器输出经放大后的驱动点阵,形成动态扫描,分别控制一列中的每个灯,当列线发出信号后,行线同时发出数据,这样就将一个汉字由左到右分成16列。在完成各列的同时,行线发出行数据,一个循环就可以将一个汉字完整的重现在16*16的点阵模块上。
本实验主要完成汉字字符在LED上的显示,16*16扫描LED点阵的工作原理与8位扫描数码管类似,只是显示的方式与结果不一样而已。下面就本实验系统的16*16点阵的工件原理做一些简单的说明。
16*16点阵由此256个LED通过排列组合而形成16行*16列的一个矩阵式的LED阵列,俗称16*16点阵。单个的LED的电路如下图11-1所示:
图11-1 单个LED电路图
由上图可知,对于单个LED的电路图当Rn输入一个高电平,同时Cn输入一个低电平时,电路形成一个回路,LED发光。也就是LED点阵对应的这个点被点亮。16*16点阵也就是由16行和16列的LED组成,其中每一行的所有16个LED的Rn端并联在一起,每一列的所有16个LED的Cn端并联在一起。通过给Rn输入一个高电平,也就相当于给这一列所有LED输入了一个高电平,这时只要某个LED的Cn端输入一个低电平时,对应的LED就会被点亮。具体的电路如下图11-2所示:
图11-2 16*16点阵电路原理图
在点阵上显示一定有字符是根据其字符在点阵上的显示的点的亮灭来表示的如下图11-3所示:
图11-3 字符在点阵上的显示
在上图中,显示的是一个“汉”字,只要将被“汉”字所覆盖的区域的点点亮,则在点阵中就会显示一个“汉”字。根据前面我们所介绍的点阵显示的原理。当我们选中第一列后,根据要显示汉字的第一列中所需要被点亮的点对应的Rn置为高电平,则在第一列中需要被点亮的点就会被点亮。依此类推,显示第二列、第三列……第N列中需要被点亮的点。然后根据人眼的视觉原理,将每一列显示的点的间隔时间设为一定的值,那么我们就会感觉显示一个完整的不闪烁的汉字。同时也可以按照这个原理来显示其它的汉字。下
在上图中,在系统时钟的作用下,首先选取其中的一列,将数据输入让这列的LED显示其数据(当为高电平时LED发光,否则不发光)。然后选取下一列来显示下一列的数据。当完成一个16*16点阵的数据输入时,即列选择计数到最后一列后,再从第一列开始输入相同的数据。这样只要第一次显示第一列的数据和第二次显示第一列的数据的时间足够短,那么人的眼睛就会看到第一列的数据总是显示的,而没有停顿现象。同样的道理其它列也是这样,直到显示下一个汉字。
在实际的运用当中,一个汉字是由多个八位的数据来构成的,那么要显示多个汉字的时候,这些数据可以根据一定的规则存放到存储器中,当要显示这个汉字的时候只要将存储器中对应的数据取出显示即可。本实验的示例程序依次显示的是“欢迎使用嵌入式SOC开发系统 ”。数据量不大,所以没有放入存储器中,而在程序中直接输入对应的一个16位的数据。示例程序的字库数据的格式如下图11-5所示:
图11-5 字库格式
图11-7 16*16点阵显示的电路框图
在此实验中,16*16点阵由4个8*8点阵组成,考虑到LED电流功耗与FPGA电流功耗的关系,在实验的电路中加入驱动电路。具体电路如下图11-6所示。与FPGA的管脚连接如表11-1所示。
图11-6 16*16点阵电路图
信号名称
对应FPGA管脚名
说明
DOT-C0
W19
点阵的第1列输入端口
DOT-C1
U17
点阵的第2列输入端口
DOT-C2
R8
点阵的第3列输入端口
DOT-C3
T8
点阵的第4列输入端口
DOT-C4
U7
点阵的第5列输入端口
DOT-C5
W8
点阵的第6列输入端口
DOT-C6
W10
点阵的第7列输入端口
DOT-C7
Y11
点阵的第8列输入端口
DOT-C8
AB18
点阵的第9列输入端口
DOT-C9
AA18
点阵的第10列输入端口
DOT-C10
AB20
点阵的第11列输入端口
DOT-C11
AA20
点阵的第12列输入端口
DOT-C12
AB21
点阵的第13列输入端口
DOT-C13
W17
点阵的第14列输入端口
DOT-C14
Y15
点阵的第15列输入端口
DOT-C15
Y13
点阵的第16列输入端口
DOT-R0
AD8
点阵的第1行输入端口
DOT-R1
AC9
点阵的第2行输入端口
DOT-R2
AD10
点阵的第3行输入端口
DOT-R3
AC10
点阵的第4行输入端口
DOT-R4
AD11
点阵的第5行输入端口
DOT-R5
AC11
点阵的第6行输入端口
DOT-R6
AD12
点阵的第7行输入端口
DOT-R7
AC12
点阵的第8行输入端口
DOT-R8
AD4
点阵的第9行输入端口
DOT-R9
AC5
点阵的第10行输入端口
DOT-R10
AD5
点阵的第11行输入端口
DOT-R11
AC6
点阵的第12行输入端口
DOT-R12
AD6
点阵的第13行输入端口
DOT-R13
AC7
点阵的第14行输入端口
DOT-R14
AD7
点阵的第15行输入端口
DOT-R15
AC8
点阵的第16行
表11-1 16X16点阵与FPGA的管脚连接表
三、设计步骤
1. 下面我们建立一个点阵显示的工程
1)选择 开始 > 程序 > Altera > QuartusII5.1,运行QUARTUSII软件。或者双击桌面上的QUARTUSII的图标运行QUARTUSII软件,出现如图1-3所示。
图1-3 QUARTUSII软件运行界面
2)选择软件中的菜单File > New Project Wizard,新建一个工程。如图1-4所示。
图1-4 新建工程对话框
3)点击图1-4中的NEXT进入工作目录,工程名的设定对话框如图1-5所示。第一个输入框为工程目录输入框,用户可以输入如e:/eda等工作路径来设定工程的目录,设定好后,所有的生成文件将放入这个工作目录。第二个输入框为工程名称输入框,第三个输入框为顶层实体名称输入框。用户可以设定如EXP1,一般情况下工程名称与实体名称相同。使用者也可以根据自已的实际情况来设定工程名和顶层文件名。注:本处的顶层文件名必须和程序的实体名一致,否则编译会出错。
图1-5 指定工程名称及工作目录
4)点击NEXT,进入下一个设定对话框,按默认选项直接点击NEXT进行器件选择对话框。如图1-6所示。这里我们以选用CycloneII系列芯片EP2C35F672C8为例进行介绍。用户可以根据使用的不同芯片来进行设定。
图1-6 器件选择界面
首先在对话框的左上方的Family下拉菜单中选取CycloneII,在中间右边的Speed grade下拉菜单中选取8,在左下方的Available devices框中选取EP2C35F672C8,点击NEXT完成器件的选取,进入EDA TOOL设定界面如图1-7所示。
图1-7 EDA TOOL对话框
5)按默认选项,点击Next出现新建工程以前所有的设定信息,如图1-8所示,点击Finish完成新建工程的建立。
图1-8 新建工程信息
2.硬件模块添加
通过SOPC Builder添加工程所需组件。在QuartusII中,点击工具栏中右侧的
图标,或者通过单击菜单“Tools->SOPC Builder…”都可以启动它。
1)添加NiosII CPU Core
双击左侧选择组件栏中的NiosII Processor,弹出配置对话框
2)添加RAM
添加内部RAM:选择memory→on-chip memory,改名RAM;
3)添加JTAG UART
双击左侧选择组件栏中interface Protocols->Serial->JTAG UART。选用所有的默认设置,点击“Finish”完成添加,如下图所示。
4)添加pio
在左组件栏中添加GPIO。 因为要定制4个按键输入I/O口,所以设定数据宽度“Width”为4,设定方向为“Itput ports only”,点击“Finish”,如下图所示。
依次添加下图pio
5)添加完元件后,就要为每个外设分配基地址以及中断号(IRQ)。SOPC Builder给我们提供了配置这两个的命令,通过这两个命令就可分别快速简单分配外设基地址和中断。下图是添加完所有组件后的SOPC Builder配置情况。然后生成硬件系统。
6)设计顶层文件
在quartus II中的图形编辑界面中进行管脚连接锁定工作将生成模块以图标形式添加到BDF文件中:于Quartus 界面New→Block Diagram/Schematic File,于弹出画图界面双击空白弹出添加界面完成模块的输入输出接口连接
7)引脚锁定和编译
新建引脚锁定命令文件,File→New→Tcl Script File,弹出新窗口,将引脚锁定文件输入进去,通过查阅引脚文件从而对相应输入输出对应到硬件引脚上。然后编译工程: Process→Start compilation。
8)配置FPGA
这里要打开实验板电源、连接USB下载线将生成的SOF文件下载到目标板上。步骤:Tools→Programmer目标文件夹下载,选择USB-Blaster模式,通过JTAG口对FPGA进行配置;然后点Start,进度达到100%便可将其关闭
9)NIOS II软件设计
a) 打开NIOS II IDE, 新建工程:File→New→Project,选择C/C++Application,Browse选择工程里面的ptf后缀文件,选择hello world small→Finish。
b) 添加.c主程序文件:选中工程右击New→NIOS II C/C++Application,输入程序。完成程序的添加后右击工程→Builder Projectd对工程编译。
c) 选择RUN→RUN·····,系统自动检测JTAG连接电缆于弹出窗口Main中选中工程,在Target Connection选择电缆USB-Blaster→RUN,观察实验结果。
四、程序文件
----下面是引用库
library ieee; --库函数
use ieee.std_logic_1164.all;
--定义了std_logic数据类型及相应运算
use ieee.std_logic_arith.all;
--定义了signed和unsigned数据类型、相应运算和相关类型转--换函数
use ieee.std_logic_unsigned.all;
--定义了一些函数,可以使std_logic_vector类
--型被当作符号数或无符号数一样进行运算
--------------------------------------------------------------------
entity exp11 is --exp11为实体名
port( clk : in std_logic; --时钟输入
keyc : out std_logic_vector(15 downto 0); --点阵列控制
keyr : out std_logic_vector(15 downto 0) --点阵行显示
);
end exp11;--结束实体
--------------------------------------------------------------------
architecture behave of exp11 is --behave为结构体名
signal cdount : std_logic_vector(3 downto 0);--信号量 表示列扫描频率
signal dount : std_logic_vector(8 downto 0);--计数,
signal S : std_logic_vector(3 downto 0);--单个汉字的扫描周期
begin
process(clk) --显示时序控制 进程1
begin --以begin为标志开始结构体的描述
if clk'event and clk='1' then --上升沿
dount<=dount+1;--计数累加
if dount=255 then
if S=15 then
S<="0000";
else
s<=S+1;
end if;
s<=s+1;
else
s<=S;
end if;
if cdount<15 then --控制列扫描频率
cdount<=cdount+1;
else
cdount<="0000";
end if;
end if;
end process; --结束进程1
process(cdount,s)--进程2 汉字扫描
begin
case cdount is --列扫描频率
when "0000"=>keyc<="0000000000000001";
when "0001"=>keyc<="0000000000000010";
when "0010"=>keyc<="0000000000000100";
when "0011"=>keyc<="0000000000001000";
when "0100"=>keyc<="0000000000010000";
when "0101"=>keyc<="0000000000100000";
when "0110"=>keyc<="0000000001000000";
when "0111"=>keyc<="0000000010000000";
when "1000"=>keyc<="0000000100000000";
when "1001"=>keyc<="0000001000000000";
when "1010"=>keyc<="0000010000000000";
when "1011"=>keyc<="0000100000000000";
when "1100"=>keyc<="0001000000000000";
when "1101"=>keyc<="0010000000000000";
when "1110"=>keyc<="0100000000000000";
when "1111"=>keyc<="1000000000000000";
when others=>keyc<="0000000000000000";
end case;
if s="0000" then
case cdount is
when "0000"=>keyr<="1101111111100011";
when "0001"=>keyr<="1100111111000011";
when "0010"=>keyr<="1010001110011011";
when "0011"=>keyr<="1011000000111011";
when "0100"=>keyr<="1011110000011011";
when "0101"=>keyr<="1001000010000011";
when "0110"=>keyr<="1101011111000011";
when "0111"=>keyr<="1100111111100001";
when "1000"=>keyr<="1110001111100001";
when "1001"=>keyr<="1111000000010001";
when "1010"=>keyr<="1111100000010111";
when "1011"=>keyr<="1110000111110111";
when "1100"=>keyr<="1100011111010111";
when "1101"=>keyr<="1000111111000111";
when "1110"=>keyr<="1001111111100011";
when "1111"=>keyr<="1001111111110011";
when others=>keyr<="1111111111111111";
end case;
elsif s="0001" then
case cdount is
when "0000"=>keyr<="1011111110111111"; --
when "0001"=>keyr<="1001111110111101";
when "0010"=>keyr<="1100000000100001";
when "0011"=>keyr<="1100000000100011";
when "0100"=>keyr<="1100111111110111";
when "0101"=>keyr<="1011100000000111";
when "0110"=>keyr<="1011100000000111";
when "0111"=>keyr<="1011110011110011";
when "1000"=>keyr<="1011111011111011";
when "1001"=>keyr<="1010000000000011";
when "1010"=>keyr<="1010000000000111";
when "1011"=>keyr<="1011110111110111";
when "1100"=>keyr<="1011100111110111";
when "1101"=>keyr<="1011100000000111";
when "1110"=>keyr<="1011110000000111";
when "1111"=>keyr<="1011111111111111";
when others=>keyr<="1111111111111111";
end case;
elsif s="0010" then
case cdount is
when "0000"=>keyr<="1111111101111111"; -
when "0001"=>keyr<="1111111100111111";
when "0010"=>keyr<="1000000000011111";
when "0011"=>keyr<="1000000000000111";
when "0100"=>keyr<="1011111111000001";
when "0101"=>keyr<="1011110000010001";
when "0110"=>keyr<="1001110000010011";
when "0111"=>keyr<="1100011011010111";
when "1000"=>keyr<="1110011011010111";
when "1001"=>keyr<="1110000000000001";
when "1010"=>keyr<="1110100000000001";
when "1011"=>keyr<="1100111011010111";
when "1100"=>keyr<="1100111011010111";
when "1101"=>keyr<="1001110000010111";
when "1110"=>keyr<="1001110000010111";
when "1111"=>keyr<="1101111111110111";
when others=>keyr<="1111111111111111";
end case;
elsif s="0011" then
case cdount is
when "0000"=>keyr<="1111111111111111"; --
when "0001"=>keyr<="1001111111111111";
when "0010"=>keyr<="1100011111111111";
when "0011"=>keyr<="1110000000000001";
when "0100"=>keyr<="1111100000000001";
when "0101"=>keyr<="1111111011011101";
when "0110"=>keyr<="1111111011011101";
when "0111"=>keyr<="1111111011011101";
when "1000"=>keyr<="1000000000000001";
when "1001"=>keyr<="1000000000000001";
when "1010"=>keyr<="1111111011011101";
when "1011"=>keyr<="1101111011011101";
when "1100"=>keyr<="1001111011011101";
when "1101"=>keyr<="1000000000000001";
when "1110"=>keyr<="1100000000000001";
when "1111"=>keyr<="1111111111111111";
when others=>keyr<="1111111111111111";
end case;
elsif s="0100" then
case cdount is
when "0000"=>keyr<="1111111111111111"; --
when "0001"=>keyr<="1111111110111111";
when "0010"=>keyr<="1100000000010011";
when "0011"=>keyr<="1100000000010011";
when "0100"=>keyr<="1110110110110111";
when "0101"=>keyr<="1100000000010111";
when "0110"=>keyr<="1000000000010111";
when "0111"=>keyr<="1001111010110001";
when "1000"=>keyr<="1100111001110001";
when "1001"=>keyr<="1110011100010111";
when "1010"=>keyr<="1110000010010111";
when "1011"=>keyr<="1111000010110111";
when "1100"=>keyr<="1100011010110011";
when "1101"=>keyr<="1000111000110011";
when "1110"=>keyr<="1001111100111111";
when "1111"=>keyr<="1101111111111111";
when others=>keyr<="1111111111111111";
end case;
elsif s="0101" then
case cdount is
when "0000"=>keyr<="1011111111111111"; --
when "0001"=>keyr<="1001111111111111";
when "0010"=>keyr<="1101111111111111";
when "0011"=>keyr<="1110111111111111";
when "0100"=>keyr<="1110001111111101";
when "0101"=>keyr<="1111000011111001";
when "0110"=>keyr<="1111110000010001";
when "0111"=>keyr<="1111111100000011";
when "1000"=>keyr<="1111111100001111";
when "1001"=>keyr<="1111111000111111";
when "1010"=>keyr<="1111100011111111";
when "1011"=>keyr<="1111000111111111";
when "1100"=>keyr<="1100011111111111";
when "1101"=>keyr<="1000111111111111";
when "1110"=>keyr<="1001111111111111";
when "1111"=>keyr<="1101111111111111";
when others=>keyr<="1111111111111111";
end case;
elsif s="0110" then
case cdount is
when "0000"=>keyr<="1111111111100111"; --
when "0001"=>keyr<="1101111111100111";
when "0010"=>keyr<="1001111011001111";
when "0011"=>keyr<="1000111011001111";
when "0100"=>keyr<="1100000011001111";
when "0101"=>keyr<="1110000011001111";
when "0110"=>keyr<="1110011011001111";
when "0111"=>keyr<="1111011011001111";
when "1000"=>keyr<="1111011000000001";
when "1001"=>keyr<="1111100000000001";
when "1010"=>keyr<="1110000111001111";
when "1011"=>keyr<="1100011111001001";
when "1100"=>keyr<="1001111111001001";
when "1101"=>keyr<="1011111111001111";
when "1110"=>keyr<="1000111111001111";
when "1111"=>keyr<="1000111111100111";
when others=>keyr<="1111111111111111";
end case;
elsif s="0111" then
case cdount is
when "0000"=>keyr<="1111101110011111"; --
when "0001"=>keyr<="1111001000001111";
when "0010"=>keyr<="1111000011001111";
when "0011"=>keyr<="1111100111011111";
when "0100"=>keyr<="1111111111111111";
when "0101"=>keyr<="1111110000111111";
when "0110"=>keyr<="1111100000011111";
when "0111"=>keyr<="1111001111001111";
when "1000"=>keyr<="1111001111001111";
when "1001"=>keyr<="1111100000011111";
when "1010"=>keyr<="1111110000111111";
when "1011"=>keyr<="1111111111111111";
when "1100"=>keyr<="1111100000011111";
when "1101"=>keyr<="1111001111001111";
when "1110"=>keyr<="1111001111001111";
when "1111"=>keyr<="1111101111011111";
when others=>keyr<="1111111111111111";
end case;
elsif s="1000" then
case cdount is
when "0000"=>keyr<="11111
展开阅读全文