EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )

目录

1、实验目的

2、实验仪器设备

3、实验原理

4、实验要求

5、实验步骤

6、实验报告

7、实验过程

(1)矩阵按键原理

(2)音符发音原理

(3)电路连接

(4)文件烧录 


1、实验目的

  1. 了解蜂鸣器的工作原理;
  2. 掌握4*4矩阵键盘的编程方法。
  3. 学会用于Verilog语言进行程序设计。

2、实验仪器设备

  1. PC机一台
  2. FPGA实验开发系统一套。

3、实验原理

本实验根据蜂鸣器工作频率不同,从而发出不同的音符的声音。故本实验是将主时钟进行分频,使其分别产生 7 种不同分频因子。通过4*4键盘选择不同的频率输出驱动蜂鸣器。

音调

低/Hz

中/Hz

高/Hz

D0

262

523

1046

RE

294

578

1175

MI

330

698

1397

FA

349

698

1397

SO

392

784

1568

LA

440

880

1760

SI

494

988

1967

4、实验要求

  1. 预习教材中的相关内容。
  2. 阅读并熟悉本次实验的内容。
  3. 完成实验内容。

5、实验步骤

  1. 启动 Quartus II 建立一个空白工程,选择的器件为 Altera 公司的 Cyclone 系列的 EP2C8Q240C8 芯片,命名为 keyarray.qpf;
  2. 新建一个 Schematic File 文件,命名为 keyarray.bdf;
  3. 分别新建两个 Verilog HDL File 文件,分别命名为 keyarraycontrol.v,note.v。输入程序代码并保存,然后进行综合编译。若在编译过程中发现错误,则找出错误并更正错误,直至编译成功为止。
  4. 从设计文件创建模块(FileàCreat UpdateàCreat Symbol Files for Current File),keyarraycontrol.v 生成名为 keyarraycontrol.bsf;note.v 生成名为 note.bsf;
  5. 在 keyarray.bdf 文件中,在空白处双击鼠标左键,添加锁相环模块(altpll)其配置参数为输入 50MHz,输出 10MHz。在 Symbol 对话框左上角的 libraries 中,分别将 Project 下的 keyarraycontrol、note 模块放在图形文件 keyarray.bdf 中,加入输入、输出引脚,双击每个引脚,进行引脚命名,并锁定管脚,将未使用的引脚设置为三态输入(一定要设置,否则可能会损坏芯片);

EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第1张图片

完整的顶层模块原理图如图所示

EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第2张图片

        6. 将 keyarray.bdf 设置为顶层实体。对该工程文件进行全程编译处理,若在编译过程中出现             错误,则找出错误并更正,直至编译通过为止;

        7. 将 USB-Blaster 下载电缆的两端分别连接到 PC 机的 USB 接口和 EDA 实验箱上的 JTAG               下载口上,打开电源,执行下载命令,把程序下载到 FPGA 器件中,此时,即可在 EDA 实              验箱上通过按下相应的按键使蜂鸣器发出对应的音符声响。

6、实验报告

  1. 总结Verilog设计多路选择器使用的最基本与核心的语法知识。
  2. 对仿真的结果进行分析。
  3. 讨论自己在设计过程中遇到的问题、解决的过程以及收获体会。

7、实验过程

基本流程为创建项目、创建Verilog文件、写代码、进行波形仿真、画出电路图、设置管脚和三态、烧录文件。这里我就不去做演示了,下面主要去讲原理。

(1)矩阵按键原理

EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第3张图片
矩阵按键模块是先按行选取到某一行,然后再选列,跟矩阵选择某一个点的原理是一样的,如果按下这个按键的时候,此时两边的开关是接通的,这时候就会返回到一个矩阵按键回馈的信息,我们只需要去读取到这个信息,然后再根据行列的相关位置,把这个信息转换为相对于的数字返回即可。

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

(2)音符发音原理

以下是不同音符发音的频率:

音调

低/Hz

中/Hz

高/Hz

D0

262

523

1046

RE

294

578

1175

MI

330

698

1397

FA

349

698

1397

SO

392

784

1568

LA

440

880

1760

SI

494

988

1967

前面我们创建了一个获取矩阵按键返回值的代码,这里我们需要去创建一个verilog文件来去对返回值进行分频操作,代码如下:

module note(clk, divcnt, out);
	input clk;
	input[3:0] divcnt;
	output out;
	
	reg out;
	reg[15:0] cnt_0, cnt_4, cnt_8, cnt_12, cnt_1, cnt_5, cnt_9;
	
	always@(posedge clk)
		begin
			if (divcnt == 8'd0)//do√
				begin
					if (cnt_0 == 4780)
						begin
							out = out + 1;
							cnt_0 = 0;
						end
					else
						begin
							cnt_0 = cnt_0 + 1;
						end
				end
			else if (divcnt == 8'd4)//re√
				begin
					if (cnt_4 == 4255)
						begin
							out = out + 1;
							cnt_4 = 0;
						end
					else
						begin
							cnt_4 = cnt_4 + 1;
						end
				end
			else if (divcnt == 8'd8)//mi√
				begin
					if (cnt_8 == 3794)
						begin
							out = out + 1;
							cnt_8 = 0;
						end
					else
						begin
							cnt_8 = cnt_8 + 1;
						end
				end
			else if (divcnt == 8'd12)//fa√
				begin
					if (cnt_12 == 3579)
						begin
							out = out + 1;
							cnt_12 = 0;
						end
					else
						begin
							cnt_12 = cnt_12 + 1;
						end
				end
			else if (divcnt == 8'd1)//so√
				begin
					if (cnt_1 == 3189)
						begin
							out = out + 1;
							cnt_1 = 0;
						end
					else
						begin
							cnt_1 = cnt_1 + 1;
						end
				end
			else if (divcnt == 8'd5)//la√
				begin
					if (cnt_5 == 2841)
						begin
							out = out + 1;
							cnt_5 = 0;
						end
					else
						begin
							cnt_5 = cnt_5 + 1;
						end
				end
			else if (divcnt == 8'd9)//si√
				begin
					if (cnt_9 == 2542)
						begin
							out = out + 1;
							cnt_9 = 0;
						end
					else
						begin
							cnt_9 = cnt_9 + 1;
						end
				end
		end
endmodule

(3)电路连接

写好了Verilog代码,就进行分析错误,分析无误后,我们就对这些代码生成子模块文件。然后就创建block文件开始连接电路图,电路图以及管脚配置如下:

EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第4张图片

(4)文件烧录 

弄好了之后就是最后一步操作了,把没用到的管脚设置三态,然后烧录文件。

点击Assignment, Device

EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第5张图片

然后点击这里,设置管脚。 

EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第6张图片  选择第一个就行了,就是把多余的管脚设置三态。

EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第7张图片

点击此处,烧录文件。 EDA实验-----4*4矩阵键盘模拟音符测试(Quartus II )_第8张图片

 这里我们会看到,下面有一个芯片,这个也就是我们写好了的sof文件,然后就是通过你的电脑接口去连接到开发板,如果你看到上面有一个No Hardware的时候,你点击旁边的按钮进行接口设置,设置为USB接口即可(USB线连接了你的开发板就会自动显示出来的)。最后点击start就可以进行烧录了。 
 

以上就是本期的全部内容了,我们下次见!

分享一张壁纸:

你可能感兴趣的:(EDA实验,计算机外设,fpga开发,EDA实验,quartus,硬件)