您当前的位置: 首页 >  fpga开发

正点原子

暂无认证

  • 0浏览

    0关注

    382博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【正点原子FPGA连载】 第三十章 IO扩展模块实验-摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

正点原子 发布时间:2022-01-11 16:08:34 ,浏览量:0

1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-301505-1-1.html 4)对正点原子FPGA感兴趣的同学可以加群讨论:994244016 5)关注正点原子公众号,获取最新资料更新 在这里插入图片描述

第三十章 IO扩展模块实验

随着时间的推进,正点原子的 FPGA 开发板款式越来越多,外设也越来越丰富,从简单的按键流水灯到复杂的光口网口,基本上可以说是满足了广大 FPGA 工程师的学习和项目开发。但是在实际项目开发的过程中往往会出现一些按键、LED 灯、数码管、拨码开关等基础器件不够用的情况,为此我们正点原子特地推出了 IO 扩展模块,这个模块旨在帮助大家丰富按键、LED 灯、数码管、拨码开关等基础器件,方便大家灵活开发实际项目。 本章包括以下几个部分: 30.1 简介 30.2 实验任务 30.3 硬件设计 30.4 软件设计 30.5 下载验证 30.1 简介 正点原子推出的 IO 扩展板包含了 8 个 LED、一个 x8 的拨码开关、四个八段数码管和一个 4x4 的矩阵 键盘。八颗LED可以使用FPGA单独控制也可以配合拨码开关去使用,当然拨码开关也可以用来控制其他外设。四个八段数码管同样可以使用 FPGA 单独控制,当开发板上的数码管不够用的时候就可以使用 IO 扩展板去代替。最后就是 4x4 的矩阵键盘了,共 16 个按键可以提供非常灵活的按键控制,当开发板上的按键不够用的时候就可以使用 IO 扩展板去提供一个额外的按键控制。 30.2 实验任务 本节实验任务是通过拨码开关控制 IO 扩展板上的 LED 灯亮灭,然后将矩阵键盘的按键编号显示在数码管上。 30.3 硬件设计 IO 扩展板模块的原理图如下所示: 在这里插入图片描述

图 7.5.13.1 IO扩展板硬件原理图 由上图可知,IO 扩展口模块的8颗LED灯是共阴极接法,其8个阳极全部引出,可以通过 FPGA(其 他单片机类芯片也可)对这八颗 LED 灯进行控制。拨码开关(Switch)也是共阴极接法,开关另一端全部上拉,当拨码开关断开时 SW0~SW7 全部是高电平,当拨码开关合上则 SW0~SW7 全部是低电平。我们可以使用拨码开关去控制一些其他外设,比如本节实验我们就可以使用拨码开关去控制颗 LED 灯。数码管大家就很熟悉了,IO 扩展模块的 4 个八段数码管的位选同样是共阴极接法,引出位选信号和段选信号可以使用 FPGA(其他单片机类芯片也可)对其进行控制。矩阵键盘是由 16 个按键组成的矩阵,分为四行四列, 其中四行全部是 3.3V 上拉,四列全部将端口引出,这 8 个端口(四行四列 8 个端口)全部可以连接到 FPGA上(其他单片机类芯片也可),可以通过 FPGA(其他单片机类芯片也可)对矩阵键盘进行行列扫描,判断出是哪一个按键被按下,扫描方法在下文会详细讲解。最后就是一排 20x2 的排针了,我们所有的端口都是连接到这个排针上的,大家在使用 IO 扩展板的时候可以将排针插到正点原子 FPGA 开发板的扩展口上去,这样每个端口就可以和 FPGA IO 引脚相连了。 IO 扩展板实物图如下图 所示。 在这里插入图片描述

图 7.5.13.2 实物图 本实验中,IO 扩展板管脚分配如下表所示。 表 30.3.1引脚分配表 sys_clk input U18 系统时钟,频率:50Mhz sys_rst_n input N16 系统复位,低电平有效 sel_t[0] output P19 数码管位选信号sel_t[0] sel_t[1] output T20 数码管位选信号sel_t[1] sel_t[2] output M20 数码管位选信号sel_t[2] sel_t[3] output K14 数码管位选信号sel_t[3] seg_led_t[0] output J14 数码管a段选信号seg_led_t[0] seg_led_t[1] output N18 数码管b段选信号seg_led_t[1] seg_led_t[2] output M19 数码管c段选信号seg_led_t[2] seg_led_t[3] output L16 数码管d段选信号seg_led_t[3] seg_led_t[4] output M15 数码管e段选信号seg_led_t[4] seg_led_t[5] output N20 数码管f段选信号seg_led_t[5] seg_led_t[6] output U20 数码管g段选信号seg_led_t[6] seg_led_t[7] output U19 数码管h段选信号seg_led_t[7] led[0] output N17 LED灯 led[1] output P18 LED灯 led[2] output V20 LED灯 led[3] output W20 LED灯 led[4] output R17 LED灯 led[5] output R16 LED灯 led[6] output W19 LED灯 led[7] output W18 LED灯 swi[0] input V17 拨码开关 swi[1] input V18 拨码开关 swi[2] input T17 拨码开关 swi[3] input R18 拨码开关 swi[4] input Y18 拨码开关 swi[5] input Y19 拨码开关 swi[6] input P15 拨码开关 swi[7] input P16 拨码开关 key_row[0] input T14 矩阵键盘行扫描 key_row[1] input U17 矩阵键盘行扫描 key_row[2] input Y16 矩阵键盘行扫描 key_row[3] input T15 矩阵键盘行扫描 key_col[0] output W16 矩阵键盘列扫描 key_col[1] output T16 矩阵键盘列扫描 key_col[2] output Y17 矩阵键盘列扫描 key_col[3] output V16 矩阵键盘列扫描 对应的XDC约束语句如下所示:

set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]

set_property -dict {PACKAGE_PIN J14 IOSTANDARD LVCMOS33} [get_ports seg_led_t[0]]
set_property -dict {PACKAGE_PIN N18 IOSTANDARD LVCMOS33} [get_ports seg_led_t[1]]
set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports seg_led_t[2]]
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS33} [get_ports seg_led_t[3]]
set_property -dict {PACKAGE_PIN M15 IOSTANDARD LVCMOS33} [get_ports seg_led_t[4]]
set_property -dict {PACKAGE_PIN N20 IOSTANDARD LVCMOS33} [get_ports seg_led_t[5]]
set_property -dict {PACKAGE_PIN U20 IOSTANDARD LVCMOS33} [get_ports seg_led_t[6]]
set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports seg_led_t[7]]

set_property -dict {PACKAGE_PIN P19 IOSTANDARD LVCMOS33} [get_ports sel_t[0]]
set_property -dict {PACKAGE_PIN T20 IOSTANDARD LVCMOS33} [get_ports sel_t[1]]
set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports sel_t[2]]
set_property -dict {PACKAGE_PIN K14 IOSTANDARD LVCMOS33} [get_ports sel_t[3]]

set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports key_row[0]]
set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports key_row[1]]
set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports key_row[2]]
set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports key_row[3]]

set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports key_col[0]]
set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports key_col[1]]
set_property -dict {PACKAGE_PIN Y17 IOSTANDARD LVCMOS33} [get_ports key_col[2]]
set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports key_col[3]]

set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports led[0]]
set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports led[1]]
set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33} [get_ports led[2]]
set_property -dict {PACKAGE_PIN W20 IOSTANDARD LVCMOS33} [get_ports led[3]]
set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports led[4]]
set_property -dict {PACKAGE_PIN R16 IOSTANDARD LVCMOS33} [get_ports led[5]]
set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports led[6]]
set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports led[7]]

set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports swi[0]]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports swi[1]]
set_property -dict {PACKAGE_PIN T17 IOSTANDARD LVCMOS33} [get_ports swi[2]]
set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports swi[3]]
set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports swi[4]]
set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports swi[5]]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports swi[6]]
set_property -dict {PACKAGE_PIN P16 IOSTANDARD LVCMOS33} [get_ports swi[7]]

30.4 程序设计 根据实验任务,我们画出程序框图,整个程序框架由三个子模块构成,第一个模块是矩阵键盘扫描模块,通过行列扫描检测按键的按下情况,并将按下的那个按键编号传递给数码管模块。数码管模块会把按键的编号显示在数码管上。拨码开关模块其实是和LED模块连在一起的,在代码中我们会直接把拨码开关的值赋给LED灯,因此当拨码开关断开swi端口被上拉,LED 灯点亮,反之LED灯熄灭。系统框图如下图所示: 在这里插入图片描述

图 7.5.13.1 程序框图 各模块端口及信号连接如下图所示: 在这里插入图片描述

图 7.5.13.2 RTL视图 由上图可知,FPGA 部分包括四个模块,顶层模块(top_matrix_keyboard)、矩阵键盘扫描模块(key_4x4)、数码管显示模块(seg_led)、拨码开关控制 led 灯模块(swi_led)。在顶层模块中完成对其它三个模块的例化,并实现各模块之间的信号传递。 1)顶层模块(top_matrix_keyboard):顶层模块主要是对其它三个子模块进行例化,实现子模块间的信号连接。 2)矩阵键盘扫描模块(key_4x4):矩阵键盘扫描模块主要是对IO扩展板上的矩阵键盘进行行列扫描, 定位出哪一个按键被按下并将其对应的编号传递给数码管显示模块。 3)数码管显示模块(seg_led):接收矩阵键盘扫描模块(key_4x4)传递出的按键编号值并将数据显示出来。 4)拨码开关模块(swi_led):主要检测拨码开关的开合状态,并将状态值赋给 led 灯控制 led 灯的亮灭。 顶层模块的代码如下:

1   module top_matrix_keyboard(
2       input         sys_clk    ,
3       input         sys_rst_n  ,
4       input   [3:0] key_row    ,
5       input   [7:0] swi        ,
6       output  [3:0] key_col    ,
7       output  [3:0] sel_t      ,
8       output  [7:0] seg_led_t  ,
9       output  [7:0] led
10  
11      );
12  
13  //wire define
14  wire [3:0]    key_value    ;
15  wire          key_flag     ;
16  
17  //*****************************************************
18  //**                    main code                      
19  //*****************************************************
20  
21  //矩阵键盘扫描模块
22  key_4x4    u_key_4x4(
23      .sys_clk    (sys_clk  ),
24      .sys_rst_n  (sys_rst_n),
25      .key_row    (key_row  ),
26      .key_col    (key_col  ),
27      .key_value  (key_value),
28      .key_flag   (key_flag )
29      );
30  
31  //数码管显示模块
32  seg_led    u_seg_led(
33      .clk       (sys_clk  ),
34      .rst_n     (sys_rst_n),
35      .key_value (key_value),
36      .key_flag  (key_flag ),
37      .sel_t     (sel_t    ),
38      .seg_led_t (seg_led_t)
39      );
40  
41  //拨码开关模块
42  swi_led     u_swi_led(
43      .clk     (sys_clk  ),
44      .rst_n   (sys_rst_n),
45      .swi     (swi      ),
46      .led     (led      )
47  );
48  endmodule

顶层模块主要就是例化三个子模块,在这里就不作过多介绍了,下面我们直接开始看矩阵键盘扫描模块,矩阵键盘扫描模块的代码如下:

1   module key_4x4(
2       input                sys_clk   ,   //50MHZ
3       input                sys_rst_n ,
4       input       [3:0]    key_row   ,   //行
5       output reg  [3:0]    key_col   ,   //列
6       output reg  [3:0]    key_value ,   //键值
7       output reg           key_flag
8   
9   );
10  
11  //reg define
12  reg [2:0] state       ;  //状态标志
13  reg [3:0] key_col_reg ;  //寄存扫描列值
14  reg [3:0] key_row_reg ;  //寄存扫描行值
15  reg [31:0]delay_cnt   ;
16  reg [3:0] key_reg     ;
17  reg       key_flag_row;  //消抖完成标志
18  
19  //*****************************************************
20  //**                    main code                      
21  //*****************************************************
22  
23  always @(posedge sys_clk or negedge sys_rst_n) begin 
24      if (!sys_rst_n) begin 
25          key_reg               
关注
打赏
1665308814
查看更多评论
0.0396s