赞
踩
目录
本实验通过扫描4*4矩阵键盘的值,在数码管上显示对应按钮的编号数据。矩阵键盘及数码管电路如下所示。
完整的顶层模块原理图如图所示:
创建项目、创建Verilog文件、写代码、进行波形仿真、画出电路图、设置管脚和三态、烧录文件
在讲实验过程之前,先讲讲相关的原理,不知道原理的话就很难去写代码。
矩阵按键模块是先按行选取到某一行,然后再选列,跟矩阵选择某一个点的原理是一样的,如果按下这个按键的时候,此时两边的开关是接通的,这时候就会返回到一个矩阵按键回馈的信息,我们只需要去读取到这个信息,然后再根据行列的相关位置,把这个信息转换为相对于的数字返回即可。
Verilog代码(读取到矩阵按键按下的位置,输出相对于的数字):
- module keyarraycontrol(clk,rst,row,col,keydata);
- input clk;
- input rst;
- input [3:0] row;
- output reg[3:0] col;
- output reg[3:0] keydata;
- reg keyint;
-
- reg [19:0] cnt;
- //分频获得键盘扫描频率
- always @ (posedge clk, negedge rst)
- if (!rst)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- //将计数的最高位赋给key_clk
- wire key_clk = cnt[19]; // (2^20/50M = 21)ms
- //设定扫描状态判断参数
- parameter NO_KEY_PRESSED = 6'b000_001; // 如果没有按键按下的时候
- parameter SCAN_COL0 = 6'b000_010; // 按下第一行按键
- parameter SCAN_COL1 = 6'b000_100; // 按下第二行按键
- parameter SCAN_COL2 = 6'b001_000; // 按下第三行按键
- parameter SCAN_COL3 = 6'b010_000; // 按下第四行按键
- parameter KEY_PRESSED = 6'b100_000; // 有按键按下状态
-
- reg [5:0] current_state, next_state; // 当前状态,,,下一个状态
-
- always @ (posedge key_clk, negedge rst)
- if (!rst)
- current_state <= NO_KEY_PRESSED;
- else
- current_state <= next_state;
-
- //
- always @ *
- case (current_state)
- NO_KEY_PRESSED : //
- if (row != 4'hF)
- next_state = SCAN_COL0;
- else
- next_state = NO_KEY_PRESSED;
- SCAN_COL0 : //
- if (row != 4'hF)
- next_state = KEY_PRESSED;
- else
- next_state = SCAN_COL1;
- SCAN_COL1 : //
- if (row != 4'hF)
- next_state = KEY_PRESSED;
- else
- next_state = SCAN_COL2;
- SCAN_COL2 : //
- if (row != 4'hF)
- next_state = KEY_PRESSED;
- else
- next_state = SCAN_COL3;
- SCAN_COL3 : //
- if (row != 4'hF)
- next_state = KEY_PRESSED;
- else
- next_state = NO_KEY_PRESSED;
- KEY_PRESSED : //
- if (row != 4'hF)
- next_state = KEY_PRESSED;
- else
- next_state = NO_KEY_PRESSED;
- endcase
- reg [3:0] col_val, row_val; //
-
-
- always @ (posedge key_clk, negedge rst)
- if (!rst)
- begin
- col<= 4'h0;
- keyint<=0;
- end
- else
- case (next_state)
- NO_KEY_PRESSED : //
- begin
- col <= 4'h0;
- keyint <= 0; //
- end
- SCAN_COL0 : //
- col <= 4'b1110;
- SCAN_COL1 :
- col <= 4'b1101;
- SCAN_COL2 : //
- col <= 4'b1011;
- SCAN_COL3 : //
- col <= 4'b0111;
- KEY_PRESSED : //
- begin
- col_val<= col; // 得到列的值
- row_val<= row; // 得到行的值
- keyint <= 1; //
- end
- endcase
-
- always @ (posedge key_clk, negedge rst)
- if (!rst)
- keydata <= 16'h0000;
- else
- if (keyint)
- case ({col_val, row_val})
- 8'b1110_1110 : keydata <= 8'd0;
- 8'b1110_1101 : keydata <= 8'd4;
- 8'b1110_1011 : keydata <= 8'd8;
- 8'b1110_0111 : keydata <= 8'd12;
-
- 8'b1101_1110 : keydata <= 8'd1;
- 8'b1101_1101 : keydata <= 8'd5;
- 8'b1101_1011 : keydata <= 8'd9;
- 8'b1101_0111 : keydata <= 8'd13;
-
- 8'b1011_1110 : keydata <= 8'd2;
- 8'b1011_1101 : keydata <= 8'd6;
- 8'b1011_1011 : keydata <= 8'd10;
- 8'b1011_0111 : keydata <= 8'd14;
-
- 8'b0111_1110 : keydata <= 8'd3;
- 8'b0111_1101 : keydata <= 8'd7;
- 8'b0111_1011 : keydata <= 8'd11;
- 8'b0111_0111 : keydata <= 8'd15;
- default: keydata <= keydata;
- endcase
- else
- keydata <= keydata;
- endmodule
数码管分为共阴和共阳两种,通过选择器的高低电平去判断选取到的位数,所以数码管的读取是先选择位,然后再去显示亮的灯。下图所示,下面的74HC573芯片是用于选位处理的(这个芯片必须接地或者接上低电平才可以正常工作),由于上面的U1也是同一个芯片,所以这里先进行选位的时候要先把上面的那个芯片锁住,然后下面的芯片工作,这里我们不难看出这是一个共阴的数码管,每一个数码管的选位都是连接到阴极处的(接地),所以选位的时候只需要去进行连接到地,那就可以实现通电。选完位之后,就开始选段,所以这时候要锁住下面的芯片,让上面的工作,这个数码管的选段是根据某一个段通入高电平才会亮,其每一段对应的电平位置是 hgfedcba,比如通入8个电平: 0000 0110,那么就会显示数字1,因为只有b和c段亮了。
数码管生成器模拟软件:数码管 代码 生成器 (treee.com.cn)
Verilog代码(获取到相对于的数字,然后在数码管静态显示出来):
-
- module seg(clk, data, sel_lock, seg_lock, gpio);
- input clk;
- input[3:0] data;
- output reg sel_lock;
- output reg seg_lock;
- output [7:0] gpio;
-
- reg [7:0] gpio;
- reg [3:0] disp_dat;
- reg cnt;
- reg [12:0] cnt2;
-
- always@(posedge clk)
- //cnt2 = cnt2 + 1;
- //if (cnt <1000)
- begin
- cnt = cnt + 1;
- cnt2 = cnt2 + 1;
- if (cnt)
- begin
- sel_lock = 1'b1;
- seg_lock = 1'b0;
- gpio = 8'h00;
- #20 sel_lock = 1'b0;
- seg_lock = 1'b1;
- end
- else
- begin
- sel_lock = 1'b0;
- seg_lock = 1'b1;
-
- disp_dat = data;
- case(disp_dat)
-
- 4'h0:gpio=8'h3f; //0 0011 1111
- 4'h1:gpio=8'h06; //1 0000 0110
- 4'h2:gpio=8'h5b; //2
- 4'h3:gpio=8'h4f; //3
- 4'h4:gpio=8'h66; //4
- 4'h5:gpio=8'h6d; //5
- 4'h6:gpio=8'h7d; //6
- 4'h7:gpio=8'h07; //7
- 4'h8:gpio=8'h7f; //8
- 4'h9:gpio=8'h6f; //9
- 4'ha:gpio=8'h77; //a
- 4'hb:gpio=8'h7c; //b
- 4'hc:gpio=8'h39; //c
- 4'hd:gpio=8'h5e; //d
- 4'he:gpio=8'h79; //e
- 4'hf:gpio=8'h71; //f
-
-
- endcase
-
- #20 sel_lock = 1'b1;
- seg_lock = 1'b0;
- end
- end
- endmodule
- module divclk(inclk,outclk);
- input inclk;
- output outclk;
- reg outclk;
- reg [16:0] cnt;
- initial
- begin
- cnt=0;
- outclk=0;
- end
-
- always @(posedge inclk)
- begin
- cnt=cnt+1;
- if (cnt==0)
- outclk = outclk+1;
- end
- endmodule
写好了Verilog代码,就进行分析错误,分析无误后,我们就对这些代码生成子模块文件。然后就创建block文件开始连接电路图,电路图以及管脚配置如下:
弄好了之后就是最后一步操作了,把没用到的管脚设置三态,然后烧录文件。
点击Assignment, Device
然后点击这里,设置管脚。
选择第一个就行了,就是把多余的管脚设置三态。
然后就是编译运行文件,运行无误。
点击此处,烧录文件。
这里我们会看到,下面有一个芯片,这个也就是我们写好了的sof文件,然后就是通过你的电脑接口去连接到开发板,如果你看到上面有一个No Hardware的时候,你点击旁边的按钮进行接口设置,设置为USB接口即可(USB线连接了你的开发板就会自动显示出来的)。最后点击start就可以进行烧录了。
以上就是本期的全部内容了,我们下一次见!
分享一张壁纸:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。