Verilog数码管实验
- 格式:docx
- 大小:1.78 MB
- 文档页数:6
系统硬件综合设计实验报告# 系统硬件综合设计实验报告## 实验目的本实验的主要目的是综合运用课程中所学的硬件设计知识,设计一个具有一定功能的系统硬件。
通过实践,加深对硬件设计原理的理解,提高硬件设计能力。
## 实验原理在本实验中,我们将使用FPGA作为硬件平台,通过Verilog HDL语言进行设计。
FPGA可以灵活重构硬件电路,方便在实验过程中进行调试和修改。
在设计过程中,我们将使用数电模块以及FPGA内部资源实现所需的功能。
## 实验内容本次实验要求设计一个功能齐全的计算器。
计算器需要实现基本的加减乘除运算功能,并且能够显示运算结果。
具体功能要求如下:1. 输入:使用8位开关模拟输入两个8位二进制数。
2. 输出:输出两个输入数以及运算结果,并在数码管上显示。
3. 加法:实现两个八位二进制数的加法。
4. 减法:实现两个八位二进制数的减法。
5. 乘法:实现两个八位二进制数的乘法。
6. 除法:实现两个八位二进制数的除法。
## 实验过程与结果根据实验要求,我们首先设计了输入部分。
通过读取8个开关的状态,我们可以获得两个8位二进制数。
然后我们使用Verilog HDL语言编写了加法、减法、乘法和除法的模块。
这些模块使用了逻辑运算和算术运算来实现相应的功能。
最后,我们将输出结果显示在数码管上。
为了实现数码管的显示功能,我们使用了FPGA提供的数码管驱动模块。
在设计过程中,我们将运算结果转换成BCD 码,然后将BCD码输入到数码管驱动模块中进行显示。
经过调试和修改,我们成功实现了计算器的基本功能。
通过改变开关的状态,我们可以输入不同的二进制数,并获得正确的运算结果。
同时,结果也能够正确地显示在数码管上。
## 实验总结通过本次实验,我们深入学习了硬件设计的原理和方法,并且实践中提高了我们的设计能力。
本次实验的设计过程中,我们灵活运用了课程中所学的知识,并且通过调试和修改,解决了一些问题。
在实验中,我们也意识到硬件设计需要细致入微,每一个步骤都要认真对待。
哈尔滨理工大学软件学院实验报告课程 FPGA题目十六进制7段数码显示译码器设计班级集成12-2班专业集成电路设计与集成系统学生学号 12140202272014年10 月8日实验一十六进制7段数码显示译码器设计实验目的:1.熟悉硬件逻辑电路的一般设计和测试流程;2.嵌入式逻辑分析仪使用方法;实验内容及步骤:1.用Verilog HDL设计1位7段数码管的显示译码电路,能够显示0~f。
显示数字由SW3~SW0设定;2.使用嵌入式逻辑分析仪进行仿真;3.将实验程序下载到DE2运行。
实验程序:LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_Arith.ALL;USE IEEE.STD_LOGIC_Unsigned.ALL;ENTITY FREQ ISPORT(clk_lk: IN STD_LOGIC;SW: IN STD_LOGIC_VECTOR(3 DOWNTO 0);seg: out STD_LOGIC_VECTOR(6 DOWNTO 0));END ENTITY;ARCHITECTURE one OF FREQ ISSIGNAL seg_r: STD_LOGIC_VECTOR(7 DOWNTO 0); BEGINseg<=seg_r(6 DOWNTO 0);PROCESS(clk_lk)BEGINCASE SW ISWHEN X"0"=>seg_r<=X"c0";WHEN X"1"=>seg_r<=X"f9";WHEN X"2"=>seg_r<=X"a4";WHEN X"3"=>seg_r<=X"b0";WHEN X"4"=>seg_r<=X"99";WHEN X"5"=>seg_r<=X"92";WHEN X"6"=>seg_r<=X"82";WHEN X"7"=>seg_r<=X"f8";WHEN X"8"=>seg_r<=X"80";WHEN X"9"=>seg_r<=X"90";WHEN X"a"=>seg_r<=X"88";WHEN X"b"=>seg_r<=X"83";WHEN X"c"=>seg_r<=X"c6";WHEN X"d"=>seg_r<=X"a1";WHEN X"e"=>seg_r<=X"86";WHEN X"f"=>seg_r<=X"8e";END CASE;END PROCESS;END;实验结果:。
实验报告课程名称:Verilog数字系统设计实验实验项目:全加器与比较器的设计姓名:专业:计算机科学与技术班级:学号:计算机科学与技术学院实验教学中心实验项目名称:全加器与比较器的设计一、实验目的1.学习用Verilog HDL语言描述组合逻辑电路。
2.学会Quartus II利用仿真与下载调试的程序方法。
二、实验内容利用Verilog HDL语言设计四位全加器和比较器。
三、实验用设备仪器及材料硬件:计算机软件:Quartus II软件四、实验原理及接线1. 数值比较器用途是比较两个二进制数的大小。
一位数值比较器:比较输入的两个1位二进制数A、B的大小。
多位数值比较器:比较输入的两个位二进制数A、B的大小,比较时需从高位到低位逐位比较。
比较器功能框图:GSEB1B0下表是一位数值比较器的真值表。
表1-1 比较器真值表2.全加器:全加器是实现两个一位二进制数及低位来的进位数相加(即将三个二进制数相加),求得和数及向高位进位的逻辑电路。
所以全加器有三个输入端(Ai,Bi,Ci-1)和两个输出端Si,Ci+1。
真值表如下:五、实验程序代码及仿真1、比较器代码module bijiaoqi(a,b,l,g,e,ledcom);input[3:0] a,b;output l,g,e;output ledcom;reg l,g,e;always@(a,b)beging = a>b ? 1:0;l = a<b ? 1:0;e = a==b ? 1:0;endendmodule比较器结果仿真结果2、全加器代码module add(a,b,cin,cout,sum); input a,b,cin;output cout,sum;wire a,b,cin,cout,sum;wire w1,w2,w3,w4;and u1(w1,a,b);and u2(w2,a,cin);and u3(w3,b,cin);or #2 u4(cout,w1,w2,w3);xor f1(w4,a,b);xor #1 f2(sum,w4,cin);endmodule全加器结果仿真结果六、心得与体会通过本次实验,使我掌握了Verilog编程方法以及熟悉了如何使用QuartusII 软件。
大连理工大学城市学院FPGA实验报告实验内容:8位ALU系别班级:电子1004班学号:姓名:日期:2013.4.14一.设计概述:一种基于可编程逻辑器件FPGA和硬件描述语言的8位的ALU的设计方法。
该ALU采用层次设计方法,有寄存器模块、控制模块和显示模块组成,能实现8位无符号数的取值、加减和4种逻辑运算(与、或、异或、同或)。
该ALU在QuartusII软件环境下进行功能仿真,通过DE2验证。
二.设计功能:1、该处理器的数据宽度为8bit,可以实现算术加法、减法、逻辑与、逻辑或、逻辑非、逻辑与非、逻辑或非和逻辑异或等8种运算。
2、用选择端opcode [2:0] 选择8种运算,2个操作数分别是a_r [7:0]和b_r[7:0],运算结果是alu_out[7:0];并定义选择如下。
3、使用DE2板上的3个拨码开关设置当前ALU的运算功能,再由8个拨码开关给定数据A 和数据B,由一个按键key手动提供脉冲。
三.设计方案:本设计共有5个模块。
1)脉冲输出器(key手动脉冲),计数依次产生4个脉冲到各个部件,第一个脉冲启动信号。
2)寄存器A,第二个脉冲来时锁存数据A,并在数码管上显示。
3)寄存器B,第三个脉冲来时锁存数据B,并在数码管上显示。
4)8位ALU,第四个脉冲来时进行运算,并锁存结果alu_out。
5)结果显示器,将结果显示通过DE2上的数码管显示。
四.程序分析:主程序模块:module alu8(clk,clk_r,rst,a,b,alu_out,opcode,sw_ab,HEX1, HEX0, HEX7, HEX6, HEX5, HEX4);input clk,rst,clk_r;input [7:0] sw_ab;input [2:0] opcode;output [6:0] HEX1, HEX0, HEX7, HEX6, HEX5, HEX4;output [7:0] a;output [7:0] b;output [7:0] alu_out;rega U1(.clk(clk),.rst(rst),.sw_ab(sw_ab),.a_r(a),.clk_r(clk_r),.HEX7(HEX7),. HEX6(HEX6));regb U2(.clk(clk),.rst(rst),.sw_ab(sw_ab),.b_r(b),.clk_r(clk_r),.HEX5(HEX5),. HEX4(HEX4));alur U3(.clk(clk),.rst(rst),.a_r(a),.b_r(b),.alu_out(alu_out),.opcode(opcode)); digital U4(.clk_r(clk_r),.rst(rst),.alu_out(alu_out),.HEX1(HEX1),. HEX0(HEX0)); endmodule第一位数A模块:module rega (clk,clk_r,rst,sw_ab,a_r,HEX7,HEX6);input [7:0] sw_ab;input clk,clk_r,rst;output [7:0] a_r;reg [7:0] a_r;output reg[6:0] HEX7,HEX6;reg [3:0] cnt;always @(posedge clk or negedge rst)if(!rst) cnt<=1'd0;else if(cnt==5) cnt<=1'd0;else cnt<=cnt+1'd1;always @(posedge clk or negedge rst)if(!rst) a_r=0;else if(cnt==1) a_r=sw_ab;else a_r=a_r;parameter seg0=7'b1000000,seg1=7'b1111001,seg2=7'b0100100,seg3=7'b0110000,seg4=7'b0011001,seg5=7'b0010010 ,seg6=7'b0000010,seg7=7'b1111000,seg8=7'b0000000,seg9=7'b0010000,sega=7'b0001000,segb=7'b0000011 ,segc=7'b1000110,segd=7'b0100001,sege=7'b0000110,segf=7'b0001110;always @(posedge clk_r)case(a_r[3:0])4'h0: HEX6[6:0]=seg0;4'h1: HEX6[6:0]=seg1;4'h2: HEX6[6:0]=seg2;4'h3: HEX6[6:0]=seg3;4'h4: HEX6[6:0]=seg4;4'h5: HEX6[6:0]=seg5;4'h6: HEX6[6:0]=seg6;4'h7: HEX6[6:0]=seg7;4'h8: HEX6[6:0]=seg8;4'h9: HEX6[6:0]=seg9;4'ha: HEX6[6:0]=sega;4'hb: HEX6[6:0]=segb;4'hc: HEX6[6:0]=segc;4'hd: HEX6[6:0]=segd;4'he: HEX6[6:0]=sege;4'hf: HEX6[6:0]=segf;default:HEX6[6:0]=seg0;endcasealways @(posedge clk_r)case(a_r[7:4])4'h0: HEX7[6:0]=seg0;4'h1: HEX7[6:0]=seg1;4'h2: HEX7[6:0]=seg2;4'h3: HEX7[6:0]=seg3;4'h4: HEX7[6:0]=seg4;4'h5: HEX7[6:0]=seg5;4'h6: HEX7[6:0]=seg6;4'h7: HEX7[6:0]=seg7;4'h8: HEX7[6:0]=seg8;4'h9: HEX7[6:0]=seg9;4'ha: HEX7[6:0]=sega;4'hb: HEX7[6:0]=segb;4'hc: HEX7[6:0]=segc;4'hd: HEX7[6:0]=segd;4'he: HEX7[6:0]=sege;4'hf: HEX7[6:0]=segf;default:HEX7[6:0]=seg0;endcaseendmodule第二位数B模块:module regb (clk,clk_r,rst,sw_ab,b_r,HEX5,HEX4); input [7:0] sw_ab;input clk,clk_r,rst;output [7:0] b_r;reg [7:0] b_r;output reg[6:0] HEX5,HEX4;reg [3:0] cnt;always @(posedge clk or negedge rst)if(!rst) cnt<=1'd0;else if(cnt==5) cnt<=1'd0;else cnt<=cnt+1'd1;always @(posedge clk or negedge rst)if(!rst) b_r=0;else if(cnt==2) b_r=sw_ab;else b_r=b_r;parameter seg0=7'b1000000,seg1=7'b1111001,seg2=7'b0100100,seg3=7'b0110000,seg4=7'b0011001,seg5=7'b0010010,seg6=7'b0000010 ,seg7=7'b1111000,seg8=7'b0000000,seg9=7'b0010000,sega=7'b0001000,segb=7'b0000011 ,segc=7'b1000110,segd=7'b0100001,sege=7'b0000110,segf=7'b0001110;always @(posedge clk_r)case(b_r[3:0])4'h0: HEX4[6:0]=seg0;4'h1: HEX4[6:0]=seg1;4'h2: HEX4[6:0]=seg2;4'h3: HEX4[6:0]=seg3;4'h4: HEX4[6:0]=seg4;4'h5: HEX4[6:0]=seg5;4'h6: HEX4[6:0]=seg6;4'h7: HEX4[6:0]=seg7;4'h8: HEX4[6:0]=seg8;4'h9: HEX4[6:0]=seg9;4'ha: HEX4[6:0]=sega;4'hb: HEX4[6:0]=segb;4'hc: HEX4[6:0]=segc;4'hd: HEX4[6:0]=segd;4'he: HEX4[6:0]=sege;4'hf: HEX4[6:0]=segf;default:HEX4[6:0]=seg0;endcasealways @(posedge clk_r)case(b_r[7:4])4'h0: HEX5[6:0]=seg0;4'h1: HEX5[6:0]=seg1;4'h2: HEX5[6:0]=seg2;4'h3: HEX5[6:0]=seg3;4'h4: HEX5[6:0]=seg4;4'h5: HEX5[6:0]=seg5;4'h6: HEX5[6:0]=seg6;4'h7: HEX5[6:0]=seg7;4'h8: HEX5[6:0]=seg8;4'h9: HEX5[6:0]=seg9;4'ha: HEX5[6:0]=sega;4'hb: HEX5[6:0]=segb;4'hc: HEX5[6:0]=segc;4'hd: HEX5[6:0]=segd;4'he: HEX5[6:0]=sege;4'hf: HEX5[6:0]=segf;default:HEX5[6:0]=seg0;endcaseendmodule运算模块:module alur(clk,rst,alu_out,a_r,b_r,opcode,zero);output [7:0] alu_out;output zero;input [7:0] a_r,b_r;input [2:0] opcode;input clk,rst;reg [7:0] alu_out;reg [3:0] cnt;parameterquA=3'b000,quB=3'b001,ADD=3'b010,DEC=3'b011,ANDD=3'b100,XORR=3'b101,XOR=3'b110, NXOP=3'b111;assign zero=!a_r;always @(posedge clk or negedge rst)if(!rst) cnt<=1'd0;else if(cnt==5) cnt<=1'd0;else cnt<=cnt+1'd1;always @(posedge clk or negedge rst)if(!rst) alu_out=0;else if(cnt==3) begincasex(opcode)quA: alu_out<=a_r;quB: alu_out<=b_r;ADD: alu_out<=a_r+b_r;DEC: alu_out<=a_r-b_r;ANDD: alu_out<=a_r&b_r;XORR: alu_out<=a_r|b_r;XOR: alu_out<=a_r^b_r;NXOP: alu_out<=a_r^~b_r;default: alu_out<=8'bxxxx_xxxx;endcaseendelse alu_out=0;endmodule结果显示模块:module digital(clk_r,rst,alu_out,HEX1,HEX0);input [7:0] alu_out;input clk_r,rst;output reg[6:0] HEX1,HEX0;parameter seg0=7'b1000000,seg1=7'b1111001,seg2=7'b0100100,seg3=7'b0110000,seg4=7'b0011001,seg5=7'b0010010,seg6=7'b0000010 ,seg7=7'b1111000,seg8=7'b0000000,seg9=7'b0010000,sega=7'b0001000,segb=7'b0000011 ,segc=7'b1000110,segd=7'b0100001,sege=7'b0000110,segf=7'b0001110;always @(posedge clk_r)case(alu_out[3:0])4'h0: HEX0[6:0]=seg0;4'h1: HEX0[6:0]=seg1;4'h2: HEX0[6:0]=seg2;4'h3: HEX0[6:0]=seg3;4'h4: HEX0[6:0]=seg4;4'h5: HEX0[6:0]=seg5;4'h6: HEX0[6:0]=seg6;4'h7: HEX0[6:0]=seg7;4'h8: HEX0[6:0]=seg8;4'h9: HEX0[6:0]=seg9;4'ha: HEX0[6:0]=sega;4'hb: HEX0[6:0]=segb;4'hc: HEX0[6:0]=segc;4'hd: HEX0[6:0]=segd;4'he: HEX0[6:0]=sege;4'hf: HEX0[6:0]=segf;default: HEX0[6:0]=seg0;endcasealways @(posedge clk_r)case(alu_out[7:4])4'h0: HEX1[6:0]=seg0;4'h1: HEX1[6:0]=seg1;4'h2: HEX1[6:0]=seg2;4'h3: HEX1[6:0]=seg3;4'h4: HEX1[6:0]=seg4;4'h5: HEX1[6:0]=seg5;4'h6: HEX1[6:0]=seg6;4'h7: HEX1[6:0]=seg7;4'h8: HEX1[6:0]=seg8;4'h9: HEX1[6:0]=seg9;4'ha: HEX1[6:0]=sega;4'hb: HEX1[6:0]=segb;4'hc: HEX1[6:0]=segc;4'hd: HEX1[6:0]=segd;4'he: HEX1[6:0]=sege;4'hf: HEX1[6:0]=segf; default: HEX1[6:0]=seg0; endcaseendmodule五.仿真实现:整体图:波形图:六.硬件实现:1.引脚图:2.分析结果说明:开关0~2是算法选择,具体算法类型见设计功能第2项开关10~17数字输入,用8位二进制数表示两个十六进制数,每四位表示一位按键0是锁存及运算,当开关10~17输入一个数A时,按下按键0,数据就是锁存,再输入数就是数B,而当数据B也锁存后,再次按下按键0,就会显示运算结果按键1是复位键七.总结:通过这次FPGA实验课让我明白了真正的编程不像是那些C语言小程序那么简单,为了这次实验算是绞尽脑汁,最后为了读懂程序,还去专门找了Verilog语言辅导书,不管过程再怎么复杂曲折,总算是顺利的完成了实验任务,到了现在回顾为期6周的学习过程,也有一些时候是因为上课不认真,为后来的程序设计增加了难度,也有一些原因是因为自己本身能力不足导致设计接连失败,不得不说,也有一部分原因是因为学习实验室的器件不足,限制了实验设计的范围,也使实验难度增加。
数字频率计的设计实验报告实验名称:数字频率计的设计实验日期:2021年7月1日实验目的:设计并实现一个基于计数器的数字频率计,使用计数器测量输入信号的频率,并将结果显示在数码管上。
实验器材:FPGA开发板、数字频率计模块、计数器模块、数码管模块。
实验原理:1. 计数器模块设计一个计数器模块,用于计数示波器输入脉冲信号的时间。
计数器的计数时间可以根据需要进行调整。
2. 数字频率计模块设计一个数字频率计模块,用于将计数器的计数时间转换为输入信号的频率。
通过计算计数器的计数值来计算频率,并将结果显示在数码管上。
3. 数码管模块设计一个数码管模块,用于将数字频率计模块计算出的频率值转换为可以在数码管上显示的数码。
实验步骤:1. 搭建实验电路将FPGA开发板连接到计数器模块、数字频率计模块和数码管模块。
2. 编写Verilog代码根据上述原理,编写计数器模块、数字频率计模块和数码管模块的Verilog代码。
3. 编译代码并下载到FPGA开发板使用Xilinx Vivado软件将Verilog代码编译成比特流文件,并将比特流文件下载到FPGA开发板中。
4. 测试实验将示波器的输出信号连接到数字频率计的输入端,并将数字频率计连接到数码管。
通过计算数字频率计的输出,验证数字频率计的测量准确性。
实验结果:经过测试,数字频率计的测量准确度在实验误差范围内。
输入不同频率的信号时,数码管能够正确显示频率值。
实验总结:通过本次实验,成功设计并实现了一个基于计数器的数字频率计。
该实验不仅巩固了计数器、数码管等模块的设计知识,也提高了学生的Verilog编程能力。
在实验中,学生还学习了如何使用FPGA开发板进行数字电路实验,以及测试和验证数字电路的方法和技巧。
文章标题:深入探究Vivado中七段数码管代码及仿真在数字电路设计中,七段数码管是一种常见的数字显示装置,广泛应用于计时器、计数器、仪表等设备中。
Vivado是Xilinx公司推出的一款集成化开发环境软件,用于FPGA设计和开发。
本文将深入探讨在Vivado中编写七段数码管的代码以及进行仿真的方法,以便读者能够更深入地理解数字电路设计和Vivado软件的应用。
一、七段数码管的基本原理要理解在Vivado中编写七段数码管的代码,首先需要了解七段数码管的基本原理。
七段数码管由7根发光二极管组成,分别对应数码管的a、b、c、d、e、f、g片段,可以显示0-9以及一些字母。
在数字电路设计中,需要通过操纵七段数码管的每一个片段,来显示需要的数字或字符。
编写七段数码管的代码,实质上是利用FPGA来控制这7个片段的亮灭。
二、Vivado中七段数码管的代码编写在Vivado中,可以使用Verilog或VHDL等硬件描述语言来编写数字电路设计的代码。
对于七段数码管的代码编写,以Verilog为例,可以按照以下步骤进行:1. 定义输入信号2. 分配七个片段对应的输出信号3. 使用组合逻辑进行数字与片段的对应4. 使用时序逻辑进行信号的控制和时序处理以下是一个简单的七段数码管代码示例:```verilogmodule seven_segment(input [3:0] sw,output reg [6:0] seg);always @(*)begincase (sw)4'b0000: seg = 7'b1000000; // 数字0 4'b0001: seg = 7'b1111001; // 数字1 4'b0010: seg = 7'b0100100; // 数字2 // 其他数字的对应关系default: seg = 7'b1111111; // 默认不显示 endcaseendendmodule```三、Vivado中七段数码管的仿真方法在编写七段数码管的代码之后,需要对其进行仿真以验证设计的正确性。
v e r i l o g乒乓球大作业(仿真成功)-标准化文件发布号:(9456-EUATWK-MWUB-WUNN-INNUL-DDQTY-KII一任务描述1 设计要求左、右双方各持一按键作为“球拍”,实验板上一行8只发光二极管为乒乓球台,其中那只发光的发光二极管代表乒乓球所在位置。
设计如图1所示的乒乓球游戏实物图的模拟控制器。
发球方最后一位LED 点亮,按下键表示发球,亮的灯依次向对方移动,当到达对方最后一位时0.5s 内对方必须按下按键表示接球,接球后LED灯向对方移动,否则输球。
接球时,LED没有亮到最后一位时就按下接球按键为犯规。
输球或者犯规,对方加1分,率先加到11分者游戏胜出这一局。
2设计思路考虑到游戏的复杂度,采用状态机来实现这些模式转换。
用到8个状态,如下所示:状态功能S2球从甲方向乙方右移,若此时乙方接球就给甲方加一分,并将球权给甲方S3开始判断乙方是否在0.5S内接球S4乙方发球S5球从乙方向甲方左移,若此时甲方接球就给乙方加一分,并将球权给乙方S7用于接球后判断发球程序还加入了蜂鸣、用数码管显示分数和发球权等功能。
二结构框图1 状态转移图002 程序流程图3 系统模块三系统程序modulepingpangok(state,clk2hz,rst,k_a,k_b,led8s,led7s1,led7s2,led7s3,led7s4,led7s5,speaker );//clk2hz指一个2Hz的时钟输入, rst异步复位, k_a和k_b是比赛双方按键, speaker是蜂鸣器//led8s是一排8个发光二极管代表球场, led7s1~4是4个显示分数的数码管, led7s5是显示发球权的数码管input clk2hz,rst,k_a,k_b;output [7:0] led8s;output [6:0] led7s1,led7s2,led7s3,led7s4,led7s5;output speaker;output [2:0] state;reg [7:0] led8s;reg [6:0] led7s1,led7s2,led7s3,led7s4,led7s5;reg [3:0] score_a,score_b;reg [2:0] state;reg speaker;parameter s0=3'b000,//复位状态,也是判断发球权的状态;s1=3'b001,//甲方发球;s2=3'b010,//球从甲方向乙方右移,若此时乙方接球就给甲方加一分,并将球权给甲方;s3=3'b011,//开始判断乙方是否在0.5S内接球;s4=3'b100,//乙方发球;s5=3'b101,//球从乙方向甲方左移,若此时甲方接球就给乙方加一分,并将球权给乙方;s6=3'b110;//开始判断甲方是否在0.5S内接球;s7=3'b111;//用于判断接球后发球;//----------------游戏逻辑控制核心----------------------------------------------------------------------------always @(posedge clk2hz) begincase(state)s7: beginif(k_a)state<=s1; //甲发球;else if(k_b)state<=s4;//乙发球;else if(speaker)speaker=1'b0;elsespeaker=1'b0;ends0: beginled7s5<=7'b0111111;//第五个数码管显示数字0,表示发球权可以开始判断了;led8s<=7'b00000000;score_a<=0;score_b<=0;//给甲乙双方的分数复位;if(k_a)beginspeaker<=1'b1;//因为按键k_a要持续按着保持高电位'1',蜂鸣器鸣叫是提示可以松手了;state<=s7;endelse if(k_b)beginspeaker<=1'b1;state<=s7;endelsestate<=s0;ends1: beginled7s5<=7'b0000110;//第五个数码管显示数字1,表示发球权现在是甲方的;if(led8s==8'b00000000)led8s<=8'b10000000;//点亮的灯出现在最右边,即甲方发球;state<=s2;if(speaker)speaker<=1'b0;//将刚才鸣叫的蜂鸣器关闭;ends2: beginif(led8s==8'b00000010)beginled8s<=led8s>>1;state<=s3;//进入判断乙方接球的状态;endelsebeginled8s<=led8s>>1;state<=s7;endif(k_b)beginscore_a<=score_a+1;speaker<=1'b1;//若在此期间乙方抢先按键,就判断乙方输,给甲方加1分,并让蜂鸣器鸣叫;state<=s7;led8s<=8'b00000000;endends3: beginif(k_b)beginstate<=s7;//乙方接球成功,并进入乙方发球的s7状态;led8s<=8'b00000000;endelsebeginscore_a<=score_a+1;speaker<=1'b1;state<=s7;//乙方接球不成功,则甲方加一分,并进入甲方发球的s7状态,蜂鸣器鸣叫;led8s<=8'b00000000;endends4: beginled7s5<=7'b1011011;//第五个数码管显示数字2,表示发球权现在是乙方的;if(led8s==8'b00000000)led8s<=8'b00000001;//点亮的灯出现在最左边,即乙方发球;state<=s5;if(speaker)speaker<=1'b0;//将刚才鸣叫的蜂鸣器关闭;ends5: beginif(led8s==8'b01000000)beginled8s<=led8s<<1;state<=s6;//进入判断甲方接球的状态;endelsebeginled8s<=led8s<<1;state<=s7;endif(k_a)beginscore_b<=score_b+1;speaker<=1'b1;//若在此期间甲方抢先按键,就判断甲方输,给乙方加1分,并让蜂鸣器鸣叫;state<=s7;led8s<=8'b00000000;endends6: beginif(k_a)beginstate<=s7;//甲方接球成功,并进入甲方发球的s7状态;led8s<=8'b00000000;endelsebeginscore_b<=score_b+1;speaker<=1'b1;state<=s7;//甲方接球不成功,则乙方加一分,并进入乙方发球的s7状态,蜂鸣器鸣叫;led8s<=8'b00000000;endenddefault: state<=s0;endcase//----------甲乙双方的分数各用2个数码管显示-----------------------------------------------------------------if(score_a==11 & score_b==11)beginscore_a<=0;score_b<=0;//如果任一方得11分,一局结束,计分清零;endcase(score_a)8'b0000: beginled7s1<=7'b0111111;led7s2<=7'b0111111;//数码管显示0分;end8'b0001: beginled7s1<=7'b0111111;led7s2<=7'b0000110;//数码管显示1分;end8'b0010: beginled7s1<=7'b0111111;led7s2<=7'b1011011;//数码管显示2分;end8'b0011: beginled7s1<=7'b0111111;led7s2<=7'b1001111;//数码管显示3分;end8'b0100: beginled7s1<=7'b0111111;led7s2<=7'b1100110;//数码管显示4分;end8'b0101: beginled7s1<=7'b0111111;led7s2<=7'b1101101;//数码管显示5分;end8'b0110: beginled7s1<=7'b0111111;led7s2<=7'b1111101;//数码管显示6分;end8'b0111: beginled7s1<=7'b0111111;led7s2<=7'b0000111;//数码管显示7分;end8'b1000: beginled7s1<=7'b0111111;led7s2<=7'b1111111;//数码管显示8分;end8'b1001: beginled7s1<=7'b0111111;led7s2<=7'b1101111;//数码管显示9分;end8'b1010: beginled7s1<=7'b0000110;led7s2<=7'b0111111;//数码管显示10分;end8'b1011: beginled7s1<=7'b0000110;led7s2<=7'b0000110;//数码管显示11分;enddefault: beginled7s1<=7'b0111111;led7s2<=7'b0111111;//数码管显示0分;endendcasecase(score_b)8'b0000: beginled7s3<=7'b0111111;led7s4<=7'b0111111;//数码管显示0分;end8'b0001: beginled7s3<=7'b0111111;led7s4<=7'b0000110;//数码管显示1分;end8'b0010: beginled7s3<=7'b0111111;led7s4<=7'b1011011;//数码管显示2分;end8'b0011: beginled7s3<=7'b0111111;led7s4<=7'b1001111;//数码管显示3分;end8'b0100: beginled7s3<=7'b0111111;led7s4<=7'b1100110;//数码管显示4分;end8'b0101: beginled7s3<=7'b0111111;led7s4<=7'b1101101;//数码管显示5分;end8'b0110: beginled7s3<=7'b0111111;led7s4<=7'b1111101;//数码管显示6分;end8'b0111: beginled7s3<=7'b0111111;led7s4<=7'b0000111;//数码管显示7分;end8'b1000: beginled7s3<=7'b0111111;led7s4<=7'b1111111;//数码管显示8分;end8'b1001: beginled7s3<=7'b0111111;led7s4<=7'b1101111;//数码管显示9分;end8'b1010: beginled7s3<=7'b0000110;led7s4<=7'b0111111;//数码管显示10分;end8'b1011: beginled7s3<=7'b0000110;led7s4<=7'b0000110;//数码管显示11分;enddefault: beginled7s3<=7'b0111111;led7s4<=7'b0111111;//数码管显示0分;endendcaseend endmodule四仿真结果功能仿真是最基本的仿真验证,它只能仿真设计中的逻辑功能。
西南科技大学实验报告课程名称:基于FPGA的现代数字系统设计实验名称:基于HDL十进制计数、显示系统设计姓名:学号:班级:通信1301指导教师:刘桂华西南科技大学信息工程学院制基于HDL十进制计数、显示系统设计一、实验目的1、掌握基于语言的ISE 设计全流程;2、熟悉、应用VerilogHDL描述数字电路;3、掌握基于Verilog的组合和时序逻辑电路的设计方法;4、掌握chipscope 片内逻辑分析仪的使用与调试方法。
二、实验原理1、实验内容:设计具有异步复位、同步使能的十进制计数器,其计数结果可以通过七段数码管、发光二极管等进行显示。
2、模块端口信号说明:输入信号:Clk_50m ---系统采样时钟clk -------待计数的时钟clr ---------异步清零信号,当clr=0,输出复位为0,当clr=1,正常计数ena---------使能控制信号,当ena=1,电路正常累加计数,否则电路不工作输出信号:q[6:0]---------驱动数码管,显示计数值的个位cout -----------1bit 数据,显示计数值向十位的进位COM-----------共阳级数码管,公共端(接地,参考开发板原理图3、以自顶向下的设计思路进行模块划分:整个系统主要设计的模块是:十进制计数模块和数码管驱动模块,由于实验板的按键为实现硬件防抖,则需要将按键输入的时钟clk,先通过消抖模块消抖后,再输出至后续使用。
1)十进制计数器模块设计输入: CLK -------待计数的时钟CLR ---------异步清零信号,当CLR =0,输出复位为0,当CLR =1,正常计数。
EN---------使能控制信号,当EN=1,电路正常累加计数,否则电路不工作输出:SUM[3:0]---------- 计数值的个位。
即,在CLK 上升沿检测到SUM=9 时,SUM 将被置0,开始新一轮的计数。
tc ------------计数值的十位进位,即:只有在时钟CLK 上升沿检测到SUM=9 时,TC将被置1,其余情况下TC=0;在设计中可以使用always,if-else-if语句实现,设计中注意不要在两个以上的always 模块中对同一个变量进行赋值,否则会产生多重赋值源(multi-source)的问题。
实验四 4 位计数器设计1.实验目的学习quartusii 和modelsim的使用方法;学习原理图和veriloghdl混合输入设计方法;掌握4 位计数器设计的设计及仿真方法。
2.实验原理根据下面FPGA内部电路,设计4 位计数器,并在在kx3c10F+开发板上实现该电路,并作仿真。
设计其中的计数器模块CNT4B和数码管译码驱动模块DECL7S的verilogHDL代码,并作出整个系统仿真。
4位计数器模块代码module CNT4B(out, CLK, RST); Please refer to theLK(CLK),.RST(RST),.out(SYNTHESIZED_WIRE_0));segled b2v_inst1(.a(SYNTHESIZED_WIRE_0),.out1(Q));endmodule效果图:3.实验设备kx3c10F+开发板,电脑。
4.实验步骤编译编译结果如下图所示:编译解释:在这个报告中,我们可以看到如下信息:Total logic elements 11/5136(<1%): 该芯片中共有5136个LE资源,其中的11个在这个工程的这次编译中得到了使用。
Total combinational functions 11/5136(<1%): 该芯片的5136个LE资源中,其中11个用于实现组合逻辑。
Dedicated logic registers 4/5136(0%): 该芯片的5136个LE资源中,其中4个用于实现寄存器,即时序逻辑。
从上述信息中,可以得到组合逻辑与时序逻辑的使用比例——11/4= :1。
综合出来的电路图电路图解释:从以上电路图可以看出本电路图主要由计数器(CNT4B)和七段数码管显示程序(segled)组成。
从CNT4B的CLK端输入CLK信号,RST为低电平复位信号,本实验是四位二进制计数器可以计数16个,每个CLK上升沿计数一次,其中七段数码管是通过输入的四位二进制数来选择相应的断码进行输出显示。
7段数码显示译码器设计1、实验目的熟悉ISE系列软件的设计流程和基本工具使用,学习7段数码显示译码器设计,学习VHDL的CASE语句应用。
2、实验内容7段数码是纯组合电路,通常的小规模专用IC,如74或4000系列的器件只能作十进制BCD码译码,然而数字系统中的数据处理和运算都是二进制的,所以输出表达都是十六进制的,为了满足十六进制数的译码显示,最方便的方法就是利用译码程序在FPGA/CPLD中实现。
本实验中,7段译码器的数码管采用共阴数码管,而且不考虑小数点的发光管。
其输出信号LED7S的7位分别接数码管的7个段,高电平有效。
例如,当LED7S输出为“1101101”时,数码管的7个段:g、f、e、d、c、b、a分别接1、1、0、1、1、0、1;接有高电平的段发亮,于是数码管显示“5”。
3、实验器材Spartan 3E开发板。
4、实验说明实验中所需要的源文件在本报告附录中。
5、实验步骤步骤1:创建ISE工程(1)启动桌面上的ISE9.1图标,在Project Navigator中选择File→New Project。
(2)在弹出的对话框(见图1)中,设置工程名为ymq7s,工程存放路径为E:\work\,顶层模块类型选择HDL,并单击Next按钮。
图1 ISE工程属性对话框(3)出现图2所示对话框,目标器件选择spartan3E,具体设计如下图。
图2 ISE工程属性对话框(4)一直点击Next,直到出现图3(即是刚才所设定的),最后点击Finish。
图3 工程设计总表出现图4,这就是所建立的工程,现在我们需要在里面完成我们的设计。
图4 ISE工程属性对话框步骤2:创建新的VHDL设计文件(1)在ISE用户界面中,选择Project→New Source。
(2)在弹出的对话框(见图5)中,选择VHDL Module作为源程序类型,设置文件名为ymq7s,并单击“下一步”按钮。
图5 VHDL的New Source Wizard(3)点击Next,直到出现图6,直到Finish。
实验四数码管的动态显示实验班级通信1102 姓名谢剑辉学号20110803223 指导老师袁文澹一、实验目的熟悉掌握数码管动态显示的基本方法;根据已知电路和设计要求在实验板上实现数码管动态显示。
根据已知电路和设计要求在PROTEUS平台仿真实现控制系统。
二、实验内容1、在STC89C52实验平台的4位数码管上实现动态显示0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容。
2、思考:如何实现当4位数码管显示的内容中有“1”时,蜂鸣器蜂鸣。
三、实验原理实验要求“4位数码管上实现动态显示0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容”。
动态扫描可以实现要求。
简单地说,动态扫描就是选通一位,送一位数据。
原理图中的P10~P13是位选信号,即选择哪个数码管显示数字;P00~P07是段码,即要显示的数字。
可以通过依次选通一位7段数码管并通过P0端口送出显示数据。
由于人眼的视觉残留原理,如果这种依次唯一选通每一位7段数码管的动作在0.1s内完成,就会造成多位数码管同时点亮显示各自数字的假象。
本实验使用中断,实现每2s更新一次数字。
四、实验方法与步骤设计思路和方法:1、根据电路图,分析数码管动态显示的设计思路,使用中断实现每2秒更新一次数字的设计思路,以及实现当4位数码管显示的内容中有“1”时,蜂鸣器蜂鸣的设计思路。
(1)数码管动态显示的原理如“实验原理”里所述,不赘述;(2)使用中断实现每2s更新一次数字的设计思路:本次实验使用Timer0中断,由于其定时时间最大为65536us,不能实现2s的长延时,那么可以使用多次中断来实现,并且在中断到来时,不断地死循环显示数字,即根据动态显示原理“选通一位,来一位数据”。
由于最大的数字为9,则(x%10),(x+1)%10,(x+2)%10,(x+3)%10分别是千位,百位,十位,个位上的数字。
2位BCD码加法器一、实验内容:利用V erilog HDL语言,编写一个2为BCD码加法器程序,并在DE2板是实现功能的运用。
A0、A1,B0、B1分别是2个输入数字,S0-S2为输出,经过BCD加法器的运算,能实现BCD码加法功能。
设计思路:A0、B0分别是A、B的低位,相加的值T0=A0+B0,若T0>10,则Z0赋值为10,同时进位C0=1,和值低位S0=T0-Z0;同理,高位A1、B1,T1=A1+B1+C0,若T1>10,则Z1=10,进位C1=1,和值高位S1=T1-Z1;S2=C1。
二、实验源程序:1)BCD加法器module BCDadder(A0,A1,B0,B1,S0,S1,S2,clear); //定义输入模块input [3:0]A0; //考虑到A0、B0、A1、B1的值可能input [3:0]A1; 超过十进制数8,顾定义长度为4位;input [3:0]B0;input [3:0]B1;input clear;output S0;output S1;output S2;reg [3:0]S0;reg [3:0]S1;reg [3:0]S2;reg [4:0]C0;reg [4:0]C1;reg [4:0]T0; //低位和值可能超过16,所以定义T0、T1长reg [4:0]T1; 度为5;reg [4:0]Z0;reg [4:0]Z1;always @(posedge clear) //以每一次复位上升沿到来开始计算和值;beginT0=A0+B0; //低位相加和值赋T0;if(T0>9)beginZ0=10; //如果低位相加有进位,则赋值Z0=10;C0=1; //如果T0>9,则有进位,此时C0=1;endelsebeginZ0=0;C0=0;endbeginT1=A1+B1+C0; //高位为A1加B1再加进位C0,赋值给T1;if(T1>9)beginZ1=10;C1=1;endelsebeginZ1=0;C1=0;endendbeginS0=T0-Z0; //和值S0到S1赋值;S1=T1-Z1;S2=C1;endendendmodule2)输入数A0、A1、B0、B1显示module indisplay(A0,A1,B0,B1,displayA0,displayA1,displayB0,displayB1); input [3:0]A0;input [3:0]A1;input [3:0]B0;input [3:0]B1;output [6:0]displayA0;output [6:0]displayA1; //定义7段数码管的输出;output [6:0]displayB0;output [6:0]displayB1;reg [6:0]displayA0;reg [6:0]displayA1; //定义其类型为寄存器类型;reg [6:0]displayB0;reg [6:0]displayB1;always@(A0 or A1 or B0 or B1) //当输入A、B中任何一位变化,即执行输入显示程序;begincase(A0) //输入A0显示4'd0:displayA0=7'b1000000;4'd1:displayA0=7'b1111001;4'd2:displayA0=7'b0100100;4'd3:displayA0=7'b0110000;4'd4:displayA0=7'b0011001;4'd5:displayA0=7'b0010010;4'd6:displayA0=7'b0000010;4'd7:displayA0=7'b1011000;4'd8:displayA0=7'b0000000;4'd9:displayA0=7'b0010000;default: displayA0=7'b1000000; //默认时,数码管显示数字“0”;endcasecase(A1) //输入A1显示4'd0:displayA1=7'b1000000;4'd1:displayA1=7'b1111001;4'd2:displayA1=7'b0100100;4'd3:displayA1=7'b0110000;4'd4:displayA1=7'b0011001;4'd5:displayA1=7'b0010010;4'd6:displayA1=7'b0000010;4'd7:displayA1=7'b1011000;4'd8:displayA1=7'b0000000;4'd9:displayA1=7'b0010000;default:displayA1=7'b1000000; //默认时,数码管显示数字“0”;endcasecase(B0) //输入B0显示4'd0:displayB0=7'b1000000;4'd1:displayB0=7'b1111001;4'd2:displayB0=7'b0100100;4'd3:displayB0=7'b0110000;4'd4:displayB0=7'b0011001;4'd5:displayB0=7'b0010010;4'd6:displayB0=7'b0000010;4'd7:displayB0=7'b1011000;4'd9:displayB0=7'b0010000;default:displayB0=7'b1000000; //默认时,数码管显示数字“0”;endcasecase(B1) //输入B1显示4'd0:displayB1=7'b1000000;4'd1:displayB1=7'b1111001;4'd2:displayB1=7'b0100100;4'd3:displayB1=7'b0110000;4'd4:displayB1=7'b0011001;4'd5:displayB1=7'b0010010;4'd6:displayB1=7'b0000010;4'd7:displayB1=7'b1011000;4'd8:displayB1=7'b0000000;4'd9:displayB1=7'b0010000;default:displayB1=7'b1000000; //默认时,数码管显示数字“0”;endcaseendendmodule3)输出显示module display(S0,S1,S2,display1,display2,display3);input[3:0] S0;input[3:0] S1;input[3:0] S2;output[6:0] display1;output[6:0] display2;output[6:0] display3;reg[6:0] display1;reg[6:0] display2;reg[6:0] display3;always @(S0 or S1 or S2) //当和值S中的任何一位变化,就开始执行显示程序;begincase(S0) //和值第一位S0显示;4'd0:display1=7'b1000000;4'd1:display1=7'b1111001;4'd2:display1=7'b0100100;4'd3:display1=7'b0110000;4'd4:display1=7'b0011001;4'd5:display1=7'b0010010;4'd6:display1=7'b0000010;4'd7:display1=7'b1011000;4'd8:display1=7'b0000000; //默认时,数码管显示数字“0”;default: display1=7'b1000000; //默认时,数码管显示数字“0”;endcasecase(S1) //和值第二位S1显示;4'd0:display2=7'b1000000;4'd1:display2=7'b1111001;4'd2:display2=7'b0100100;4'd3:display2=7'b0110000;4'd4:display2=7'b0011001;4'd5:display2=7'b0010010;4'd6:display2=7'b0000010;4'd7:display2=7'b1011000;4'd8:display2=7'b0000000;4'd9:display2=7'b0010000;default:display2=7'b1000000; //默认时,数码管显示数字“0”;endcasecase(S2) //和值第三位S2显示;4'd0:display3=7'b1000000;4'd1:display3=7'b1111001;4'd2:display3=7'b0100100;4'd3:display3=7'b0110000;4'd4:display3=7'b0011001;4'd5:display3=7'b0010010;4'd6:display3=7'b0000010;4'd7:display3=7'b1011000;4'd8:display3=7'b0000000;4'd9:display3=7'b0010000;default:display3=7'b1000000; //默认时,数码管显示数字“0”;endcaseendendmodule4)模块连接三、实验仿真与实现1)BCD加法器仿真输入A为24,B为48,当clear复位后,和值S为72,与理论一致,故BCD加法器正常;输入A为06,B为14,在clear的上升沿来到是计算和值,display得出相应值,从仿真结果可以看出程序正常实现BCD码加法器功能。
一顶层模块:module iic_top(clk,rst_n,sw1,sw2,scl,sda,sm_cs1_n,sm_cs2_n,sm_db);input clk; // 50MHzinput rst_n; //复位信号,低有效input sw1,sw2; //按键1、2,(1按下执行写入操作,2按下执行读操作) output scl; // 24C02的时钟端口inout sda; // 24C02的数据端口output sm_cs1_n,sm_cs2_n; //数码管片选信号,低有效output[6:0] sm_db; //7段数码管(不包括小数点)wire[7:0] dis_data; //在数码管上显示的16进制数iic_com iic_com(.clk(clk),.rst_n(rst_n),.sw1(sw1),.sw2(sw2),.scl(scl),.sda(sda),.dis_data(dis_data));led_seg7 led_seg7(.clk(clk),.rst_n(rst_n),.dis_data(dis_data),.sm_cs1_n(sm_cs1_n),.sm_cs2_n(sm_cs2_n),.sm_db(sm_db));endmodule二IIC时序模块:module iic_com(clk,rst_n,sw1,sw2,scl,sda,dis_data);input clk; // 50MHzinput rst_n; //复位信号,低有效input sw1,sw2; //按键1、2,(1按下执行写入操作,2按下执行读操作)output scl; // 24C02的时钟端口inout sda; // 24C02的数据端口output[7:0] dis_data; //数码管显示的数据//--------------------------------------------//按键检测reg sw1_r,sw2_r; //键值锁存寄存器,每20ms检测一次键值reg[19:0] cnt_20ms; //20ms计数寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) cnt_20ms <= 20'd0;else cnt_20ms <= cnt_20ms+1'b1; //不断计数always @ (posedge clk or negedge rst_n)if(!rst_n) beginsw1_r <= 1'b1; //键值寄存器复位,没有键盘按下时键值都为1sw2_r <= 1'b1;endelse if(cnt_20ms == 20'hfffff) beginsw1_r <= sw1; //按键1值锁存sw2_r <= sw2; //按键2值锁存end//---------------------------------------------//分频部分reg[2:0] cnt; // cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间reg[8:0] cnt_delay; //500循环计数,产生iic所需要的时钟reg scl_r; //时钟脉冲寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) cnt_delay <= 9'd0;else if(cnt_delay == 9'd499) cnt_delay <= 9'd0; //计数到10us为scl的周期,即100KHzelse cnt_delay <= cnt_delay+1'b1; //时钟计数always @ (posedge clk or negedge rst_n) beginif(!rst_n) cnt <= 3'd5;else begincase (cnt_delay)9'd124: cnt <= 3'd1; //cnt=1:scl高电平中间,用于数据采样9'd249: cnt <= 3'd2; //cnt=2:scl下降沿9'd374: cnt <= 3'd3; //cnt=3:scl低电平中间,用于数据变化9'd499: cnt <= 3'd0; //cnt=0:scl上升沿default: cnt <= 3'd5;endcaseendend`define SCL_POS (cnt==3'd0) //cnt=0:scl上升沿`define SCL_HIG (cnt==3'd1) //cnt=1:scl高电平中间,用于数据采样`define SCL_NEG (cnt==3'd2) //cnt=2:scl下降沿`define SCL_LOW (cnt==3'd3) //cnt=3:scl低电平中间,用于数据变化always @ (posedge clk or negedge rst_n)if(!rst_n) scl_r <= 1'b0;else if(cnt==3'd0) scl_r <= 1'b1; //scl信号上升沿else if(cnt==3'd2) scl_r <= 1'b0; //scl信号下降沿assign scl = scl_r; //产生iic所需要的时钟//---------------------------------------------//需要写入24C02的地址和数据`define DEVICE_READ 8'b1010_0001 //被寻址器件地址(读操作)`define DEVICE_WRITE 8'b1010_0000 //被寻址器件地址(写操作)`define WRITE_DATA 8'b1101_0001 //写入EEPROM的数据`define BYTE_ADDR 8'b0000_0011 //写入/读出EEPROM的地址寄存器reg[7:0] db_r; //在IIC上传送的数据寄存器reg[7:0] read_data; //读出EEPROM的数据寄存器//---------------------------------------------//读、写时序parameter IDLE = 4'd0;parameter START1 = 4'd1;parameter ADD1 = 4'd2;parameter ACK1 = 4'd3;parameter ADD2 = 4'd4;parameter ACK2 = 4'd5;parameter START2 = 4'd6;parameter ADD3 = 4'd7;parameter ACK3 = 4'd8;parameter DATA = 4'd9;parameter ACK4 = 4'd10;parameter STOP1 = 4'd11;parameter STOP2 = 4'd12;reg[3:0] cstate; //状态寄存器reg sda_r; //输出数据寄存器reg sda_link; //输出数据sda信号inout方向控制位reg[3:0] num; //always @ (posedge clk or negedge rst_n) beginif(!rst_n) begincstate <= IDLE;sda_r <= 1'b1;sda_link <= 1'b0;num <= 4'd0;read_data <= 8'b0000_0000;endelsecase (cstate)IDLE: beginsda_link <= 1'b1; //数据线sda为outputsda_r <= 1'b1;if(!sw1_r || !sw2_r) begin //SW1,SW2键有一个被按下db_r <= `DEVICE_WRITE; //送器件地址(写操作)cstate <= START1;endelse cstate <= IDLE; //没有任何键被按下endSTART1: beginif(`SCL_HIG) begin //scl为高电平期间sda_link <= 1'b1; //数据线sda为outputsda_r <= 1'b0; //拉低数据线sda,产生起始位信号cstate <= ADD1;num <= 4'd0; //num计数清零endelse cstate <= START1; //等待scl高电平中间位置到来endADD1: beginif(`SCL_LOW) beginif(num == 4'd8) beginnum <= 4'd0; //num计数清零sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态(input)cstate <= ACK1;endelse begincstate <= ADD1;num <= num+1'b1;case (num)4'd0: sda_r <= db_r[7];4'd1: sda_r <= db_r[6];4'd2: sda_r <= db_r[5];4'd3: sda_r <= db_r[4];4'd4: sda_r <= db_r[3];4'd5: sda_r <= db_r[2];4'd6: sda_r <= db_r[1];4'd7: sda_r <= db_r[0];default: ;endcase// sda_r <= db_r[4'd7-num]; //送器件地址,从高位开始endend// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelse cstate <= ADD1;endACK1: beginif(/*!sda*/`SCL_NEG) begin //注:24C01/02/04/08/16器件可以不考虑应答位cstate <= ADD2; //从机响应信号db_r <= `BYTE_ADDR; // 1地址endelse cstate <= ACK1; //等待从机响应endADD2: beginif(`SCL_LOW) beginif(num==4'd8) beginnum <= 4'd0; //num计数清零sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态(input)cstate <= ACK2;endelse beginsda_link <= 1'b1; //sda作为outputnum <= num+1'b1;case (num)4'd0: sda_r <= db_r[7];4'd1: sda_r <= db_r[6];4'd2: sda_r <= db_r[5];4'd3: sda_r <= db_r[4];4'd4: sda_r <= db_r[3];4'd5: sda_r <= db_r[2];4'd6: sda_r <= db_r[1];4'd7: sda_r <= db_r[0];default: ;endcase// sda_r <= db_r[4'd7-num]; //送EEPROM地址(高bit开始)cstate <= ADD2;endend// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelse cstate <= ADD2;endACK2: beginif(/*!sda*/`SCL_NEG) begin //从机响应信号if(!sw1_r) begincstate <= DATA; //写操作db_r <= `WRITE_DATA; //写入的数据endelse if(!sw2_r) begindb_r <= `DEVICE_READ; //送器件地址(读操作),特定地址读需要执行该步骤以下操作cstate <= START2; //读操作endendelse cstate <= ACK2; //等待从机响应endSTART2: begin //读操作起始位if(`SCL_LOW) beginsda_link <= 1'b1; //sda作为outputsda_r <= 1'b1; //拉高数据线sdacstate <= START2;endelse if(`SCL_HIG) begin//scl为高电平中间sda_r <= 1'b0; //拉低数据线sda,产生起始位信号cstate <= ADD3;endelse cstate <= START2;endADD3: begin //送读操作地址if(`SCL_LOW) beginif(num==4'd8) beginnum <= 4'd0; //num计数清零sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态(input)cstate <= ACK3;endelse beginnum <= num+1'b1;case (num)4'd0: sda_r <= db_r[7];4'd1: sda_r <= db_r[6];4'd2: sda_r <= db_r[5];4'd3: sda_r <= db_r[4];4'd4: sda_r <= db_r[3];4'd5: sda_r <= db_r[2];4'd6: sda_r <= db_r[1];4'd7: sda_r <= db_r[0];default: ;endcase// sda_r <= db_r[4'd7-num]; //送EEPROM地址(高bit开始)cstate <= ADD3;endend// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //器件地址左移1bitelse cstate <= ADD3;endACK3: beginif(/*!sda*/`SCL_NEG) begincstate <= DATA; //从机响应信号sda_link <= 1'b0;endelse cstate <= ACK3; //等待从机响应endDATA: beginif(!sw2_r) begin //读操作if(num<=4'd7) begincstate <= DATA;if(`SCL_HIG) beginnum <= num+1'b1;case (num)4'd0: read_data[7] <= sda;4'd1: read_data[6] <= sda;4'd2: read_data[5] <= sda;4'd3: read_data[4] <= sda;4'd4: read_data[3] <= sda;4'd5: read_data[2] <= sda;4'd6: read_data[1] <= sda;4'd7: read_data[0] <= sda;default: ;endcase// read_data[4'd7-num] <= sda; //读数据(高bit开始)end// else if(`SCL_NEG) read_data <= {read_data[6:0],read_data[7]}; //数据循环右移endelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0; //num计数清零cstate <= ACK4;endelse cstate <= DATA;endelse if(!sw1_r) begin //写操作sda_link <= 1'b1;if(num<=4'd7) begincstate <= DATA;if(`SCL_LOW) beginsda_link <= 1'b1; //数据线sda作为outputnum <= num+1'b1;case (num)4'd0: sda_r <= db_r[7];4'd1: sda_r <= db_r[6];4'd2: sda_r <= db_r[5];4'd3: sda_r <= db_r[4];4'd4: sda_r <= db_r[3];4'd5: sda_r <= db_r[2];4'd6: sda_r <= db_r[1];4'd7: sda_r <= db_r[0];default: ;endcase// sda_r <= db_r[4'd7-num]; //写入数据(高bit开始)end// else if(`SCL_POS) db_r <= {db_r[6:0],1'b0}; //写入数据左移1bitendelse if((`SCL_LOW) && (num==4'd8)) beginnum <= 4'd0;sda_r <= 1'b1;sda_link <= 1'b0; //sda置为高阻态cstate <= ACK4;endelse cstate <= DATA;endendACK4: beginif(/*!sda*/`SCL_NEG) begin// sda_r <= 1'b1;cstate <= STOP1;endelse cstate <= ACK4;endSTOP1: beginif(`SCL_LOW) beginsda_link <= 1'b1;sda_r <= 1'b0;cstate <= STOP1;endelse if(`SCL_HIG) beginsda_r <= 1'b1; //scl为高时,sda产生上升沿(结束信号)cstate <= STOP2;endelse cstate <= STOP1;endSTOP2: beginif(`SCL_LOW) sda_r <= 1'b1;else if(cnt_20ms==20'hffff0) cstate <= IDLE;else cstate <= STOP2;enddefault: cstate <= IDLE;endcaseendassign sda = sda_link ? sda_r:1'bz; assign dis_data = read_data;//--------------------------------------------- endmodule三数码管显示模块:module led_seg7(clk,rst_n,dis_data,sm_cs1_n,sm_cs2_n,sm_db);input clk; // 50MHzinput rst_n; // 复位信号,低有效input[7:0] dis_data; //显示数据output sm_cs1_n,sm_cs2_n; //数码管片选信号,低有效output[6:0] sm_db; //7段数码管(不包括小数点)reg[7:0] cnt;always @ (posedge clk or negedge rst_n)if(!rst_n) cnt <= 8'd0;else cnt <= cnt+1'b1;//------------------------------------------------------------------------------- /* 共阴极:不带小数点;0, 1, 2, 3, 4, 5, 6, 7,db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h;8, 9, a, b, c, d, e, f , 灭db 7fh,6fh,77h,7ch,39h,5eh,79h,71h,00h*/ parameterseg0 = 7'h3f,seg1 = 7'h06,seg2 = 7'h5b,seg3 = 7'h4f,seg4 = 7'h66,seg5 = 7'h6d,seg6 = 7'h7d,seg7 = 7'h07,seg8 = 7'h7f,seg9 = 7'h6f,sega = 7'h77,segb = 7'h7c,segc = 7'h39,segd = 7'h5e,sege = 7'h79,segf = 7'h71;reg[6:0] sm_dbr; //7段数码管(不包括小数点)wire[3:0] num; //显示数据assign num = cnt[7] ? dis_data[7:4] : dis_data[3:0]; assign sm_cs1_n = cnt[7]; //数码管1常开assign sm_cs2_n = ~cnt[7]; //数码管2常开always @ (posedge clk)case (num) //NUM值显示在两个数码管上4'h0: sm_dbr <= seg0;4'h1: sm_dbr <= seg1;4'h2: sm_dbr <= seg2;4'h3: sm_dbr <= seg3;4'h4: sm_dbr <= seg4;4'h5: sm_dbr <= seg5;4'h6: sm_dbr <= seg6;4'h7: sm_dbr <= seg7;4'h8: sm_dbr <= seg8;4'h9: sm_dbr <= seg9;4'ha: sm_dbr <= sega;4'hb: sm_dbr <= segb;4'hc: sm_dbr <= segc;4'hd: sm_dbr <= segd;4'he: sm_dbr <= sege;4'hf: sm_dbr <= segf;default: ;endcaseassign sm_db = sm_dbr;endmodule。
Basys3实验指导手册1. 引言Basys3是一款基于Xilinx Artix-7 FPGA的开辟板,它提供了丰富的硬件资源和接口,适合于学习和开辟数字电路和嵌入式系统。
本实验指导手册旨在匡助初学者快速上手Basys3开辟板,并通过一系列实验匡助他们熟悉FPGA开辟流程和基本的数字电路设计。
2. 实验准备2.1 Basys3开辟板2.2 Vivado设计套件2.3 计算机2.4 USB A to micro-B线缆3. 实验一:LED控制3.1 实验目的通过编写Verilog代码,控制Basys3开辟板上的LED灯实现不同的闪烁模式。
3.2 实验步骤3.2.1 创建新工程3.2.2 添加约束文件3.2.3 编写Verilog代码3.2.4 综合、实现和生成比特流文件3.2.5 下载比特流文件到Basys3开辟板3.3 实验结果实验结果应包括不同频率和模式下的LED闪烁效果。
4. 实验二:七段数码管显示4.1 实验目的通过编写Verilog代码,控制Basys3开辟板上的七段数码管显示不同的数字。
4.2 实验步骤4.2.1 创建新工程4.2.2 添加约束文件4.2.3 编写Verilog代码4.2.4 综合、实现和生成比特流文件4.2.5 下载比特流文件到Basys3开辟板4.3 实验结果实验结果应包括数码管显示不同数字的效果。
5. 实验三:按键输入和输出5.1 实验目的通过编写Verilog代码,实现Basys3开辟板上按键输入和LED输出的控制。
5.2 实验步骤5.2.1 创建新工程5.2.2 添加约束文件5.2.3 编写Verilog代码5.2.4 综合、实现和生成比特流文件5.2.5 下载比特流文件到Basys3开辟板5.3 实验结果实验结果应包括按下不同按键时,LED灯的亮灭效果。
6. 实验四:PWM信号发生器6.1 实验目的通过编写Verilog代码,实现Basys3开辟板上的PWM信号发生器。
一、8位数字显示的简易频率计设计要求:①能够测试10Hz~10MHz方波信号;②电路输入的基准时钟为1Hz,要求测量值以8421BCD码形式输出;③系统有复位键;④采用分层次分模块的方法,用Verilog HDL进行设计。
⑤写出测试仿真程序1.设计原理频率计的原理即测量给定信号每秒钟脉冲个数,则系统时钟宽度应为2s,通过分频模块将基准时钟进行二分频实现;当系统时钟高电平时计数模块开始计数,低电平时清零;之后将结果存入锁存模块使其稳定显示。
2.设计方案该频率计由分频模块,计数模块,锁存模块和顶层模块构成,其中:1)分频模块(FC_div):由于基准时钟(clk_d)频率为1Hz,高电平宽度为0.5s,因此通过一个二分频模块得到一个频率为0.5Hz,高电平宽度为1s的时钟(clk_out),并作为计频器的系统时钟。
2)计数模块(FC_counter):频率计核心模块,在接入的系统时钟(clk_c)处于高电平时对输入信号(freq_in)的上升沿进行计数,从而测得输入信号的频率。
由于要把测量值以8421BCD码输出,且量程上限为10MHz。
因此程序内采用8个4位寄存器分别从低到高地按位存储测量值,最后再按位排列输出一个32位的BCD 码序列(CT)。
3)锁存模块(FC_latch):将计数模块输出的结果存储以稳定显示。
4)顶层模块(FC_top):将各模块连接实现计频器。
3.程序代码1)分频模块module FC_div(clk_d,rst_d,clk_out);input clk_d,rst_d;output clk_out;reg clk_out;always@(posedge clk_d or negedge rst_d)beginif(rst_d==0)clk_out<=0;elseclk_out<=~clk_out;endendmodule2)计数模块module FC_counter(clk_c,freq_in,CT);input clk_c;input freq_in;output [31:0] CT;reg [31:0] CT;reg [3:0] C0,C1,C2,C3,C4,C5,C6,C7;always@(posedge freq_in)beginif(!clk_c)beginC0<=0;C1<=0;C2<=0;C3<=0;C4<=0;C5<=0;C6<=0;C7<=0;endelsebeginif(C0!=4'b1001)C0<=C0+1;elsebeginC0<=0;if(C1!=4'b1001)C1<=C1+1;elsebeginC1<=0;if(C2!=4'b1001)C2<=C2+1;elsebeginC2<=0;if(C3!=4'b1001)C3<=C3+1;elsebeginC3<=0;if(C4!=4'b1001)C4<=C4+1;elsebeginC4<=0;if(C5!=4'b1001)C5<=C5+1;elsebeginC5<=0;if(C6!=4'b1001)C6<=C6+1;elsebeginC6<=0;if(C7!=4'b1001)C7<=C7+1;elseC7<=0;endendendendendendendendassign CT={C7,C6,C5,C4,C3,C2,C1,C0};endendmodule3)锁存模块module FC_latch(freq,Cl,Rl);input freq;input [31:0] Cl;output [31:0] Rl;reg [31:0] Rl;always@(negedge freq)Rl<=Cl;Endmodule4)顶层模块module FC_top(clk,rst,Freq_in,Nt);input clk,rst;input Freq_in;output [31:0] Nt;wire c0;wire [31:0] w0;FC_div d(.clk_d(clk),.rst_d(rst),.clk_out(c0));FC_counter c(.clk_c(c0),.freq_in(Freq_in),.CT(w0));FC_latch l(.freq(Freq_in),.Cl(w0),.Rl(Nt));Endmodule5)测试程序`timescale 100ns/1ns;module FC_top_test;reg clk,rst;reg Freq_in;wire [31:0] Nt;initialbeginclk=0;rst=0;Freq_in=0;#4999 rst=1;#500000$stop();endalways #50000 clk=~clk;always #5 Freq_in=~Freq_in;FC_top t(.clk(clk),.rst(rst),.Freq_in(Freq_in),.Nt(Nt));Endmodule4.仿真测试如测试程序所示,取时间单位为100ns,精度为1ns,为方便起见,定义此基准时钟为1Hz,则待测信号频率为10kHz。
实验四数码管实验
一、实验目的:
1.进一步熟悉Modelsim和ISE仿真工具;
2.掌握7段数码管显示译码器;
3.掌握7段数码管数码管动态输出显示的方法。
二、实验内容:
1.实现按动开关键,在数码管上显示相应的十六进制数0~F。
(参考给定的已有
工程文件Prep-IO)
2.实现开发板上的数码管动态显示0~F。
三、实验要求:
要求首先使用Modelsim软件进行功能仿真,然后使用ISE软件综合,并下载到开发板进行电路功能测试。
四、实验步骤:
1.采用VerilogHDL语言编程实现输入4位BCD码,输出是8位数码管显示码。
程序代码如下:
module Seg7BCD(out, in);
output [7:0] out;
input [3:0] in;
reg [7:0] out;
always@(in)
begin
case(in)
4'h0: out = 8'b00000011;
4'h1: out = 8'b10011111;
4'h2: out = 8'b00100101;
4'h3: out = 8'b00001101;
4'h4: out = 8'b10011001;
4'h5: out = 8'b01001001;
4'h6: out = 8'b01000001;
4'h7: out = 8'b00011111;
4'h8: out = 8'b00000001;
4'h9: out = 8'b00001001;
4'hA: out = 8'b00010001;
4'hB: out = 8'b11000001;
4'hC: out = 8'b01100011;
4'hD: out = 8'b10000101;
4'hE: out = 8'b01100001;
4'hF: out = 8'b01110001;
default: out = 8'hFE;
endcase
end
endmodule
2.用Modelsim进行功能仿真。
测试代码:
module Seg7BCD_tb;
reg [3:0] in;
wire [7:0] out;
Seg7BCD bcd(.in(in),.out(out));
initial
begin
in = 4'h0;
#20 in = 4'h1;
#20 in = 4'h2;
#20 in = 4'h3;
#20 in = 4'h4;
#20 in = 4'h5;
#20 in = 4'h6;
#20 in = 4'h7;
#20 in = 4'h8;
#20 in = 4'h9;
#20 in = 4'hA;
#20 in = 4'hB;
#20 in = 4'hC;
#20 in = 4'hD;
#20 in = 4'hE;
#20 in = 4'hF;
end
endmodule
仿真结果:
3.分别设计4位BCD码自动生成模块和BCD码的译码模块。
4位BCD码生成模块:
module BCDCode( input clk,
input rst,
output reg [3:0] BCDCode
);
always @ (posedge clk)
if (rst) BCDCode = 0;
else BCDCode = BCDCode + 1; endmodule
BCD码的译码模块:
module Seg7BCD(out, in);
output [7:0] out;
input [3:0] in;
reg [7:0] out;
always@(in)
begin
case(in)
4'h0: out = 8'b00000011;
4'h1: out = 8'b10011111;
4'h2: out = 8'b00100101;
4'h3: out = 8'b00001101;
4'h4: out = 8'b10011001;
4'h5: out = 8'b01001001;
4'h6: out = 8'b01000001;
4'h7: out = 8'b00011111;
4'h8: out = 8'b00000001;
4'h9: out = 8'b00001001;
4'hA: out = 8'b00010001;
4'hB: out = 8'b11000001;
4'hC: out = 8'b01100011;
4'hD: out = 8'b10000101;
4'hE: out = 8'b01100001;
4'hF: out = 8'b01110001;
default: out = 8'hFE;
endcase
end
endmodule
4.在顶层文件将2个电路模块实例化,并进行相应的连线。
5.用ISE综合并将电路下载到开发板进行电路功能测试。
五、实验思考
本次实验相对上次实验要难一点,在实验开始一直做不出来,最后仔细看了老师给的例子,照着例子修修改改终于做出来了结果,不过第一次出来的结果有一点瑕疵,就是数码管的小数点是亮的状态,最后把译码模块中控制数码管的小数点的码改为1就好了。
难点是要设计一个时钟分频电路、4位BCD码生成模块和4位BCD码到数码管显示码的译码模块,其中时钟分频电路和4位BCD码生成模块的第一次编写,所以遇到的问题比较多,在克服了这个难题后,这次实验就顺利完成了。