深入浅出玩转FPGA代码
- 格式:docx
- 大小:45.85 KB
- 文档页数:53
fpga计数代码FPGA(Field-Programmable Gate Array)是一种可编程逻辑设备,可以通过编写程序来定义其功能。
在FPGA中实现计数功能是一项常见的任务,可以通过组合逻辑或时序逻辑来实现。
以下是一个使用组合逻辑实现的简单计数器的参考代码:```verilogmodule Counter(input clock,input reset,output reg [3:0] count);always @(posedge clock or posedge reset)beginif (reset)count <= 4'b0000;elsecount <= count + 1;endendmodule```这是一个4位二进制计数器,每当输入时钟(clock)上升沿到来时,计数器会增加1。
同时,当复位信号(reset)为高电平时,计数器会被重置为0。
在这个例子中,我们使用了Verilog HDL来描述计数器的行为。
Verilog是一种硬件描述语言,常用于FPGA和ASIC (Application-Specific Integrated Circuit)设计。
计数器的`module`声明定义了一个Verilog模块,它有三个输入参数(时钟、复位信号和一个4位的计数器)和一个输出参数(4位计数器)。
`always @(posedge clock or posedge reset)`语句定义了一个`always`块,它描述了计数器如何根据时钟和复位信号的变化来进行操作。
当时钟上升沿或者复位信号上升沿到来时,`always`块的内容会被执行。
在这个例子中,`if (reset)`条件语句检查复位信号的状态。
如果复位信号为高电平,计数器被重置为0。
否则,计数器会增加1,通过`count <= count + 1`语句来实现。
以上是一个简单的计数器的Verilog代码示例。
第三章入门基础3.1 例程代码详解请下载例程:/cH6DGJ9jGU66i 访问密码 0711该工程共包括三个文件:led.qpf、led.qsf和led.v,三个文件都可以用GVIM或者记事本打开。
led.qpf:工程项目文件。
说明了生成此工程的Quartus II版本;指定顶层模块名。
led.qsf:工程配置文件。
工程中包括管脚定义、signaltap定义等。
熟练后,在此配置管脚非常方便。
led.v:工程的源代码。
该工程实现如下功能:每隔一秒,两个led灯变化一次,亮1秒,灭1秒。
我们详细讲解一下代码。
module led(clk ,rst_n ,led);上面代码定义了模块名led,该模块的内容从module开始,到endmodule为止。
该模块有三个输入输出信号,分别是clk、rst_n和led,是输入还是输出,分别是多少位宽(即多少根线)还未定义。
对于外界来说,看到的就是这三个信号,只需将这三个信号连接起来,就能使用这个模块的功能,至于内部是如何实现的、内部定义了什么信号,外界不关心。
input clk ;input rst_n ;output[1:0] led ;上面代码定义了信号的输入和输出,以及该信号的位宽。
例如,定义了clk和rst_n是输入的信号,并且每个位宽都是1位的,即只有一根线。
定义了led是输出信号,并且是2位的,即led信号有两根线。
输入信号即这个信号的激励,是由外部输入进来的;输出信号则是本模块根据功能,产生的信号。
reg [ 1:0] led ;reg [25:0] time_1s_cnt ;上面代码定义了led和time_1s_cnt的信号类型,声明他们是reg型的,并且表明led是2位宽,time_1s_cnt是26位宽(即有26根线)。
在设计代码中,一般只用到reg型和wire型。
reg型不一定就表示是寄存器。
到底是用reg型还是wire型,请记住一个原则:本module代码中,如果是在always 里产生的信号,都是用reg型,其他包括assign赋值、例化模块输出的信号都是用wire型。
fpga实现pid算法的代码摘要:1.FPGA简介2.PID算法简介3.FPGA实现PID算法的方法4.代码实例5.总结与展望正文:随着科技的不断发展,数字电路技术得到了广泛的应用。
在众多数字电路应用领域,FPGA(现场可编程门阵列)作为一种高度集成的硬件平台,用户可以按照需求现场编程,实现各种数字信号处理算法。
本文将介绍如何利用FPGA实现PID算法,以完成对连续信号的调控。
一、FPGA简介FPGA(Field-Programmable Gate Array),现场可编程门阵列,是一种集成电路,其内部包含大量的硬件资源,如逻辑门、存储器、乘法器等。
用户可以根据需求,通过编程软件对FPGA进行编程,实现各种数字信号处理算法。
FPGA具有以下优点:1.并行处理能力强:FPGA内部拥有大量的硬件资源,可以同时执行多个任务,提高处理速度。
2.实时性:FPGA可以直接在硬件层面实现算法,响应速度快,实时性好。
3.可重构性:FPGA可以根据需求重新编程,实现不同的功能。
4.灵活性:FPGA支持多种编程语言,如VHDL、Verilog等,方便用户进行编程。
二、PID算法简介PID(Proportional Integral Derivative,比例-积分-微分)算法是一种广泛应用于工业控制领域的调节算法。
它通过计算系统误差与期望值的比例、积分和微分,来调节系统的输出,使系统达到稳定状态。
PID算法数学模型如下:U(t) = K_p * e(t) + K_i * ∫e(t)dt + K_d * de(t)/dt其中,U(t)为控制器的输出,e(t)为系统误差,K_p、K_i、K_d分别为比例、积分、微分控制器的系数。
三、FPGA实现PID算法的方法在FPGA上实现PID算法,主要分为以下几个步骤:1.参数配置:根据实际应用需求,设置PID算法的参数,如比例系数K_p、积分时间常数K_i、微分时间常数K_d等。
FPGA之旅---例化⼀、信号端⼝采⽤名称关联语法结构:.PortName(port_expr)//PortName是顶层的名称,port_expr是底层端⼝//port_expr可以是⼀下任何类型1.标识符2.位选择,如.C(d[0]),C端⼝连接到d信号的第0位3.部分选择,例.bus(din[5:4])例:module yumen(C,A,B).C(T3)//⼆、各分层模块之编写底层编写:正常书写后,最后⽤assign语句将输出定义 例: output [3:0] key_value; 原来的按键输出按键值的次数,那么次数是reg型,always @(posedge clk or negedge rst) if(!rst) ci<=5'b0; else if(dawn_flagr!=4'b0) ci<=ci+1'b1; //此时ci是按键输出值,是reg型,此时需要换⼀下输出值,重新定义输出数组,⽤assign 赋值语句将ci赋值给输出 //即 assign key_value=ci;三、顶层模块的编写1.所有中间变量必须重新声明,否则会默认为⼀位的2.注意在对在同⼀条线上的变量命名的时候使⽤同⼀名字3.模块例化后在连线语法:module_name1 U1//模块名字空格加U?( .clk(clk),//注意,⽤逗号,外边是顶层外部信号,括号内是底层模块信号名字 .rst(rst), .top_in_signal(U1_in_signal),//顶层输⼊信号进⼊U1模块 .... .U1_signal_output(U2_in),//U1输出连到U2输⼊,此信号需要声明⼀下,否则会默认是⼀位的 ....);//括号内⽤逗号隔开,最后⼀个不加逗号,module_name2 U2//( .clk(clk),//注意,⽤逗号,外边是底层外部信号,括号内是顶层模块信号名字 .rst(rst), .U2_in(U1_output), ... .Top_out_signal(U1_out_signal),//不是很确定,有待验证 ...);//⽤分号。
fpga计数代码FPGA 计数器是基于 FPGA 实现的计数器,主要用于对电路中的事件进行计数。
通过 FPGA 的可编程性,可以通过更改代码来实现计数器的不同规格和特性。
下面是FPGA计数代码的一些相关参考内容:一、计数器的工作原理FPGA 计数器是由一组寄存器组成的计数器。
它的工作原理就是通过不断地累加计数器中的数字来实现事件的计数。
当计数器达到设定的上限时,它会向下复位并重新开始计数。
二、FPGA 计数器的实现FPGA 计数器可以通过 VHDL 或 Verilog HDL 等编程语言来实现。
以下是 VHDL 代码示例:```library IEEE;use IEEE.STD_LOGIC_1164.ALL;entity cnt_4_bit isPort ( clk : in STD_LOGIC;rst : in STD_LOGIC;en : in STD_LOGIC;q : out STD_LOGIC_VECTOR (3 downto 0));end cnt_4_bit;architecture Behavioral of cnt_4_bit issignal cnt : STD_LOGIC_VECTOR (3 downto 0) := "0000"; beginprocess(clk, rst)beginif rst = '1' thencnt <= "0000";elsif rising_edge(clk) thenif en = '1' thencnt <= cnt + 1;end if;end if;end process;q <= cnt;end Behavioral;```在上面的代码中,四位计数器被定义为一个VHDL实体。
在计数器的行为结构中,产生了一个进程,该进程在时钟上升沿增加计数器的值。
特权同学倾情奉献9G海量FPGA学习资料
本人最恨恶淘宝上那些卖资料的JS了,本来就是网络上免费搜集来的资料,居然还冠冕堂皇的拿来生财。
为此,本人特别将手上所有的资料共享给广大的FPGA爱好者们。
百度网盘下载地址:
/s/1o62lMYY
《深入浅出玩转FPGA》视频教程:35课时
特权同学精心录制的35课时深入浅出FPGA入门、进阶课程。
可配套北航出版社2010年6月上市的《深入浅出玩转FPGA》一书学习。
整部视频先是阐述FPGA的基本概念和学习方法,接着通过相应的开发套件BJ-EPM和SF-EP1C进行实践学习。
是初学者迈入
《特权和你一起学NIOS2》视频教程:20课时
特权同学的又一力作,SOPC的设计与底层逻辑设计不同,这部教程完全以另一种方式带领初学者领悟基于FPGA的嵌入式系统设计,同时也希望借助本教程能使大家熟悉在EDS 软件平台上实现NIOS2的编程和开发。
与本视频完全配套同步的图书《爱上FPGA开发——
Altera官方专题视频教程:38课时
特权fpga技术公开课
Altera官方资料(各类手册和应用笔记)(略)
百度网盘下载地址:
/s/1o62lMYY。
fpga的编程方法FPGA(Field-Programmable Gate Array)是一种可编程的逻辑器件,能够根据用户的需求进行编程,实现各种不同的功能。
FPGA的编程方法有多种,包括硬件描述语言和图形化编程工具。
本文将介绍几种常用的FPGA编程方法,并对其特点和应用进行详细阐述。
一、硬件描述语言(HDL)硬件描述语言是一种用于描述数字电路的语言,常用的HDL有VHDL (VHSIC Hardware Description Language)和Verilog。
这种编程方法将硬件电路抽象为逻辑门、寄存器等基本元素,并通过编写代码来描述它们之间的连接关系和功能。
HDL具有描述精确、灵活性强的特点,适用于复杂的电路设计和开发。
使用HDL进行FPGA编程的过程大致包括以下几个步骤:1. 设计电路结构:根据需求和功能设计电路的逻辑结构,包括各个模块的功能和连接关系。
2. 编写HDL代码:使用VHDL或Verilog编写描述电路结构和功能的代码,包括模块实例化、信号赋值、时序控制等。
3. 综合与布局:将HDL代码综合为门级网表,然后进行布局布线,生成可配置的FPGA逻辑电路。
4. 下载与调试:将生成的逻辑电路下载到FPGA芯片中,并进行功能验证和调试。
二、图形化编程工具除了使用HDL进行编程,FPGA的编程方法还包括使用图形化编程工具,如LabVIEW FPGA和Xilinx System Generator等。
这些工具提供了可视化的界面,用户只需通过拖拽和连接图形元件,即可完成对FPGA的编程。
图形化编程工具的使用过程相对简单,适合初学者或对硬件电路编程不熟悉的人。
用户只需选择所需的功能模块,将其拖入工作区域,并通过连接线将各个模块连接起来。
然后,通过配置模块的参数和时序,即可生成对应的FPGA逻辑电路。
三、特殊领域的FPGA编程方法除了传统的HDL和图形化编程工具,还有一些特殊领域的FPGA编程方法。
fpga串并转换代码摘要:1.FPGA 简介2.串并转换的概念3.FPGA 实现串并转换的方法4.串并转换代码实例5.总结正文:一、FPGA 简介FPGA(现场可编程门阵列)是一种集成电路,用户可以通过编程配置其内部的逻辑门和连线,从而实现特定的功能。
FPGA 具有高度的灵活性和可重构性,广泛应用于数字信号处理、通信、图像处理等领域。
二、串并转换的概念串并转换,顾名思义,是指将串行数据转换为并行数据,或者将并行数据转换为串行数据。
这种转换在数据传输和处理过程中具有重要意义,可以有效地提高数据传输的效率和降低硬件复杂度。
三、FPGA 实现串并转换的方法在FPGA 中实现串并转换,通常采用以下两种方法:1.使用查找表(LUT):通过编程配置查找表,将输入的串行数据转换为对应的并行数据。
2.使用串行到并行转换器(S/P 转换器):这是一种硬件电路,通过移位寄存器和逻辑门实现串行数据到并行数据的转换。
四、串并转换代码实例下面以查找表方法为例,给出一个简单的FPGA 串并转换代码实例。
假设输入串行数据为3 位,需要转换为8 位并行数据。
首先,我们需要配置一个3 位到8 位的查找表。
在Verilog 中,可以这样编写:```verilogmodule s_to_p_conv(input wire clk, input wire rst_n, input wire [2:0] s_in, output reg [7:0] p_out){reg [7:0] lut [7:0];integer i;always @(posedge clk or negedge rst_n)beginif (!rst_n)for (i = 0; i < 8; i = i + 1)lut[i] <= 8"b0;elsefor (i = 0; i < 8; i = i + 1)lut[i] <= s_in[i];endassign p_out = lut[s_in[2:0]];endmodule```在上述代码中,我们定义了一个名为s_to_p_conv 的模块,输入信号包括时钟信号clk、复位信号rst_n、输入串行数据s_in,输出并行数据p_out。
FPGA简易四位密码锁的代码一、概述在现代社会中,密码锁被广泛应用于各种场合,如家庭、商业和工业等。
密码锁的使用方便、安全性高,受到了人们的青睐。
FPGA (Field Programmable Gate Array)作为一种灵活可编程的硬件设备,可以用来实现各种数字逻辑电路,包括密码锁。
本文将介绍如何使用FPGA实现一个简易的四位密码锁,并提供相应的代码。
二、硬件设计1. 需要的硬件- FPGA开发板- 数字键盘- LED数码管2. 硬件连接- 将数字键盘通过连接线连接到FPGA开发板上的GPIO端口,用于输入密码;- 将LED数码管通过连接线连接到FPGA开发板上的GPIO端口,用于显示密码输入状态。
三、软件设计1. Verilog代码设计```verilog// 模块声明module password_lock (input wire clk, // 时钟信号input wire rst, // 复位信号input wire [3:0] key_in, // 数字键盘输入output reg [3:0] led_out // LED数码管输出);// 代码实现reg [3:0] password = 4'b1101; // 设定密码为1101always (posedge clk or posedge rst) beginif (rst) beginled_out <= 4'b1111; // 置LED数码管输出为1111end else beginif (key_in == password) beginled_out <= 4'b0000; // 如果输入密码正确,则LED数码管输出为0000end else beginled_out <= 4'b1111; // 如果输入密码错误,则LED数码管输出为1111endendendendmodule```2. 实现原理说明- 模块声明中指定了模块的输入和输出端口;- 代码实现中首先设定了一个四位的密码,然后在时钟信号的作用下判断输入的密码是否与设定的密码相匹配,如果匹配则将LED数码管输出为0000,表示密码正确;否则输出为1111,表示密码错误。
1、按键消抖实验1.module anjianxiaodou(clk,rst_n,sw1_n,sw2_n,sw3_n,led_d1,led_d2,led_d3);2.3.input clk; //主时钟信号,50MHZ4.input rst_n; //复位信号,低电平有效5.input sw1_n,sw2_n,sw3_n; //3个独立按键,低表示按下6.output led_d1,led_d2,led_d3; //发光二极管,分别由按键控制7.8.//----------------------------------------------------------9.10.reg[2:0] key_rst; //按键复位,低电平有效11.12.always @(posedge clk or negedge rst_n)13.if (!rst_n) key_rst <= 3'b111;14.else key_rst <= {sw3_n,sw2_n,sw1_n};15.16.reg[2:0] key_rst_r; //每个时钟周期的上升沿将key_rst信号所存到key_rst_r中17.18.always @(posedge clk or negedge rst_n)19.if(!rst_n) key_rst_r <= 3'b111;20.else key_rst_r <= key_rst; //key_rst_r为key_rst延迟一个时钟周期21.22.wire[2:0] key_an = key_rst_r & (~key_rst); //当寄存器key_rst由1变为0时,key_an的值为高并维持一个时钟周期,实际上时获取key_rst的下降沿23.24.//-------------------------------------------------------------25.26.reg[19:0] cnt; //计数寄存器2^20约等于10^627.28.always @ (posedge clk or negedge rst_n) //该always进程用来判断是抖动还是真的有按键按下,若真的按键按下,则计数会达到20‘hfffff29.if(!rst_n) cnt <= 20'd0; //异步复位30.else if (key_an) cnt <= 20'd0;//key_an为1可能是因为抖动产生,此处若是抖动,时间必定小于20ms,则计数清零,下面不锁存按键的值31.else cnt <= cnt + 1'b1;//(10^6)*20ns = 20ms,若是人为按下按键,按下持续时间必定大于20ms。
第二课module led_test(a,b,key_in,led_out);input a;//输入端口Ainput b;//输入端口Binput key_in;//按键输入,实现输入输入通道的选择output led_out;//led 控制端口//当key_in == 0 :led_out = aassign led_out = (key_in == 0)? a : b;Endmodule第三课3——8译码器module my3_8(a,b,c,out);input a;//杈撳叆绔彛Ainput b;//杈撳叆绔彛Binput c;//杈撳叆绔彛Coutput [7:0]out;//杈撳嚭绔彛reg [7:0]out;always@(a,b,c)begincase({a,b,c})3'b000:out = 8'b0000_0001;3'b001:out = 8'b0000_0010;3'b010:out = 8'b0000_0100;3'b011:out = 8'b0000_1000;3'b100:out = 8'b0001_0000;3'b101:out = 8'b0010_0000;3'b110:out = 8'b0100_0000;3'b111:out = 8'b1000_0000;endcaseendendmodule第四课计数器module counter(Clk50M,Rst_n,led);input Clk50M;//系统时钟,50Minput Rst_n;//全局复位,低电平复位output reg led;//led输出reg [24:0]cnt;//定义计数器寄存器//计数器计数进程always@(posedge Clk50M or negedge Rst_n)if(Rst_n == 1'b0)cnt <= 25'd0;//else if(cnt == 25'd24_999_999)else if(cnt == 25'd24_999)cnt <= 25'd0;elsecnt <= cnt + 1'b1;//led输出控制进程always@(posedge Clk50M or negedge Rst_n)if(Rst_n == 1'b0)led <= 1'b1;//else if(cnt == 25'd24_999_999)else if(cnt == 25'd24_999)led <= ~led;elseled <= led;endmodule第五课计数器——IP核module counter_top(cin,clk,cout,q);input cin;input clk;output cout;output [7:0]q;wire cout0;counter counter0(.cin(cin),.clock(clk),.cout(cout0),.q(q[3:0]));counter counter1(.cin(cout0),.clock(clk),.cout(cout),.q(q[7:4]));endmoduleTestbench(仿真)`timescale 1ns/1ns`define clock_period 20module counter_tb;reg cin;//进位输入reg clk;//计数基准时钟wire cout;//进位输出wire [3:0] q;counter counter0(.cin(cin),.clock(clk),.cout(cout),.q(q));initial clk = 1;always #(`clock_period/2)clk = ~clk;initial beginrepeat(20)begincin = 0;#(`clock_period*5)cin = 1;#(`clock_period)cin = 0;end#(`clock_period*200);$stop;endEndmoduletop_ip`timescale 1ns/1ns`define clock_period 20module counter_top_tb;reg cin;//进位输入reg clk;//计数基准时钟wire cout;//进位输出wire [7:0] q;counter_top counter0(.cin(cin),.clk(clk),.cout(cout),.q(q));initial clk = 1;always #(`clock_period/2)clk = ~clk;initial beginrepeat(300)begincin = 0;#(`clock_period*5)cin = 1;#(`clock_period)cin = 0;end#(`clock_period*200);$stop;endEndmodule第六课BCD计数器module BCD_Counter(Clk, Cin, Rst_n, Cout, q);input Clk;//计数基准时钟input Cin;//计数器进位输入input Rst_n;//系统复位output Cout;//计数进位输出output [3:0]q;//计数值输出reg [3:0]cnt;//定义计数器寄存器//执行计数过程always@(posedge Clk or negedge Rst_n)if(Rst_n == 1'b0)cnt <= 4'd0;else if(Cin == 1'b1)beginif(cnt == 4'd9)cnt <= 4'd0;elsecnt <= cnt + 1'b1;endelsecnt <= cnt;//产生进位输出信号assign Cout = (Cin == 1'b1 && cnt == 4'd9);assign q = cnt;EndmoduleCounter_Topmodule BCD_Counter_top(Clk, Cin, Rst_n, Cout, q);input Clk;//计数基准时钟input Cin;//计数器进位输入input Rst_n;//系统复位output Cout;//计数进位输出output [11:0]q;//计数值输出wire Cout0,Cout1;wire [3:0]q0,q1,q2;assign q = {q2,q1,q0};BCD_Counter BCD_Counter0(.Clk(Clk),.Cin(Cin),.Rst_n(Rst_n),.Cout(Cout0),.q(q0));BCD_Counter BCD_Counter1(.Clk(Clk),.Cin(Cout0),.Rst_n(Rst_n),.Cout(Cout1),.q(q1));BCD_Counter BCD_Counter2(.Clk(Clk),.Cin(Cout1),.Rst_n(Rst_n),.Cout(Cout),.q(q2));endmodule仿真`timescale 1ns/1ns`define clock_period 20module BCD_Counter_tb;reg Clk;reg Cin;reg Rst_n;wire Cout;wire [3:0]q;BCD_Counter BCD_Counter0(.Clk(Clk),.Cin(Cin),.Rst_n(Rst_n),.Cout(Cout),.q(q));initial Clk = 1'b1;always#(`clock_period/2) Clk = ~Clk;initial beginRst_n = 1'b0;Cin = 1'b0;#(`clock_period*200);Rst_n = 1'b1;#(`clock_period*20);repeat(30)beginCin = 1'b1;#`clock_period;Cin = 1'b0;#(`clock_period*5);end#(`clock_period*20);$stop;endEndmoduleTop_仿真`timescale 1ns/1ns`define clock_period 20module BCD_Counter_top_tb;reg Clk;reg Cin;reg Rst_n;wire Cout;wire [11:0]q;BCD_Counter_top BCD_Counter_top0(.Clk(Clk),.Cin(Cin),.Rst_n(Rst_n),.Cout(Cout),.q(q));initial Clk = 1'b1;always#(`clock_period/2) Clk = ~Clk;initial beginRst_n = 1'b0;Cin = 1'b0;#(`clock_period*200);Rst_n = 1'b1;#(`clock_period*20);Cin = 1'b1;#(`clock_period*5000);$stop;endendmodule第七课阻塞与非阻塞`timescale 1ns/1ns`define tp 1module block_nonblock(Clk,Rst_n,a,b,c,out);input Clk;input Rst_n;input a,b,c;output reg [1:0]out;//out = a + b + c;//d = a+b;//out = d + c;reg [1:0] d;always@(posedge Clk or negedge Rst_n)if(!Rst_n)out <= 2'b0;else beginout <= a + b + c;endendmodule仿真`timescale 1ns/1ns`define clock_period 20module block_nonblock_tb;reg Clock;reg Rst_n;reg a,b,c;wire [1:0]out;block_nonblock block_nonblock0(Clock,Rst_n,a,b,c,out);initial Clock = 1;always#(`clock_period/2) Clock = ~Clock;initial beginRst_n = 1'b0;a = 0;b = 0;c = 0;#(`clock_period*200 + 1);Rst_n = 1'b1;#(`clock_period*200);a = 0 ;b = 0 ;c = 0;#(`clock_period*200);a = 0 ;b = 0 ;c = 1;#(`clock_period*200);a = 0 ;b = 1 ;c = 0;#(`clock_period*200);a = 0 ;b = 1 ;c = 1;#(`clock_period*200);a = 1 ;b = 0 ;c = 0;#(`clock_period*200);a = 1 ;b = 0 ;c = 1;#(`clock_period*200);a = 1 ;b = 1 ;c = 0;#(`clock_period*200);a = 1 ;b = 1 ;c = 1;#(`clock_period*200);#(`clock_period*200);$stop;endEndmodule第八课状态机module Hello(Clk,Rst_n,data,led);input Clk;//50Minput Rst_n;//低电平复位input [7:0]data;output reg led;localparamCHECK_H= 5'b0_0001,CHECK_e = 5'b0_0010,CHECK_la= 5'b0_0100,CHECK_lb= 5'b0_1000,CHECK_o= 5'b1_0000;reg[4:0]state;always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginled <= 1'b1;state <= CHECK_H;endelse begincase(state)CHECK_H:if(data == "H")state <= CHECK_e;elsestate <= CHECK_H;CHECK_e:if(data == "e")state <= CHECK_la;elsestate <= CHECK_H;CHECK_la:if(data == "l")state <= CHECK_lb;elsestate <= CHECK_H;CHECK_lb:if(data == "l")state <= CHECK_o;elsestate <= CHECK_H;CHECK_o:beginstate <= CHECK_H;if(data == "o")led <= ~led;elseled <= led;enddefault:state <= CHECK_H;endcaseendendmodule仿真`timescale 1ns/1ns`define clock_period 20module Hello_tb;reg Clk;reg Rst_n;reg [7:0]ASCII;wire led;Hello Hello0(.Clk(Clk),.Rst_n(Rst_n),.data(ASCII),.led(led));initial Clk = 1;always#(`clock_period/2)Clk = ~Clk;initial beginRst_n = 0;ASCII = 0;#(`clock_period*200); Rst_n = 1;#(`clock_period*200 + 1); forever beginASCII = "I";#(`clock_period);ASCII = "A";#(`clock_period);ASCII = "M";#(`clock_period);ASCII = "X";#(`clock_period);ASCII = "i";#(`clock_period);ASCII = "a";#(`clock_period);ASCII = "o";#(`clock_period);ASCII = "M";#(`clock_period);ASCII = "e";#(`clock_period);ASCII = "i";#(`clock_period);ASCII = "g";#(`clock_period);ASCII = "e";#(`clock_period);ASCII = "H";#(`clock_period);ASCII = "E";#(`clock_period);ASCII = "M";#(`clock_period);ASCII = "l";#(`clock_period);ASCII = "H";#(`clock_period);ASCII = "E";#(`clock_period);ASCII = "L";#(`clock_period);ASCII = "L";#(`clock_period);ASCII = "O";#(`clock_period);ASCII = "H";#(`clock_period);ASCII = "e";#(`clock_period);ASCII = "l";#(`clock_period);ASCII = "l";#(`clock_period);ASCII = "o";#(`clock_period);ASCII = "l";endendEndmodule第九课按键消抖module key_filter(Clk,Rst_n,key_in,key_flag,key_state);input Clk;input Rst_n;input key_in;output reg key_flag;output reg key_state;localparamIDEL = 4'b0001,FILTER0 = 4'b0010,DOWN = 4'b0100,FILTER1 = 4'b1000;reg [19:0]cnt;reg en_cnt; //浣胯兘璁℃暟瀵勫瓨鍣?//瀵瑰閮ㄨ緭鍏ョ殑寮傛淇″彿杩涜鍚屾澶勭悊reg key_in_sa,key_in_sb;always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginkey_in_sa <= 1'b0;key_in_sb <= 1'b0;endelse beginkey_in_sa <= key_in;key_in_sb <= key_in_sa;endreg key_tmpa,key_tmpb;wire pedge,nedge;reg cnt_full;//璁℃暟婊℃爣蹇椾俊鍙?//浣跨敤D瑙﹀彂鍣ㄥ瓨鍌ㄤ袱涓浉閭绘椂閽熶笂鍗囨部鏃跺閮ㄨ緭鍏ヤ俊鍙凤紙宸茬粡鍚屾鍒扮郴缁熸椂閽熷煙涓級鐨勭數骞崇姸鎬?always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginkey_tmpa <= 1'b0;key_tmpb <= 1'b0;endelse beginkey_tmpa <= key_in_sb;key_tmpb <= key_tmpa;end//浜х敓璺冲彉娌夸俊鍙?assign nedge = !key_tmpa & key_tmpb;assign pedge = key_tmpa & (!key_tmpb);always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginen_cnt <= 1'b0;state <= IDEL;key_flag <= 1'b0;key_state <= 1'b1;endelse beginIDEL :beginkey_flag <= 1'b0;if(nedge)beginstate <= FILTER0;en_cnt <= 1'b1;endelsestate <= IDEL;endFILTER0:if(cnt_full)beginkey_flag <= 1'b1;key_state <= 1'b0;en_cnt <= 1'b0;state <= DOWN;endelse if(pedge)beginstate <= IDEL;en_cnt <= 1'b0;endelsestate <= FILTER0;DOWN:beginkey_flag <= 1'b0;if(pedge)beginstate <= FILTER1;en_cnt <= 1'b1;endelsestate <= DOWN;endFILTER1:if(cnt_full)beginkey_flag <= 1'b1;key_state <= 1'b1;en_cnt <= 1'b0;state <= IDEL;endelse if(nedge)beginen_cnt <= 1'b0;state <= DOWN;endelsestate <= FILTER1;default:beginstate <= IDEL;en_cnt <= 1'b0;key_flag <= 1'b0;key_state <= 1'b1;endendcaseendalways@(posedge Clk or negedge Rst_n)if(!Rst_n)cnt <= 20'd0;else if(en_cnt)cnt <= cnt + 1'b1;elsecnt <= 20'd0;always@(posedge Clk or negedge Rst_n)if(!Rst_n)cnt_full <= 1'b0;else if(cnt == 999_999)cnt_full <= 1'b1;elsecnt_full <= 1'b0;endmodule第十课数码管动态扫描module HXE8(Clk,Rst_n,En,disp_data,sel,seg);input Clk;//50Minput Rst_n;input En;//数码管显示使能,1使能,0关闭input [31:0]disp_data;output [7:0] sel;//数码管位选(选择当前要显示的数码管)output reg [6:0] seg;//数码管段选(当前要显示的内容)reg [14:0]divider_cnt;//25000-1reg clk_1K;reg [7:0]sel_r;reg [3:0]data_tmp;//数据缓存//分频计数器计数模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)divider_cnt <= 15'd0;else if(!En)divider_cnt <= 15'd0;else if(divider_cnt == 24999)divider_cnt <= 15'd0;elsedivider_cnt <= divider_cnt + 1'b1;//1K扫描时钟生成模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)clk_1K <= 1'b0;else if(divider_cnt == 24999)clk_1K <= ~clk_1K;elseclk_1K <= clk_1K;//8位循环移位寄存器always@(posedge clk_1K or negedge Rst_n)if(!Rst_n)sel_r <= 8'b0000_0001;else if(sel_r == 8'b1000_0000)sel_r <= 8'b0000_0001;elsesel_r <= sel_r << 1;always@(*)case(sel_r)8'b0000_0001:data_tmp = disp_data[3:0];8'b0000_0010:data_tmp = disp_data[7:4];8'b0000_0100:data_tmp = disp_data[11:8];8'b0000_1000:data_tmp = disp_data[15:12];8'b0001_0000:data_tmp = disp_data[19:16];8'b0010_0000:data_tmp = disp_data[23:20];8'b0100_0000:data_tmp = disp_data[27:24];8'b1000_0000:data_tmp = disp_data[31:28];default:data_tmp = 4'b0000;endcasealways@(*)case(data_tmp)4'h0:seg = 7'b1000000;4'h1:seg = 7'b1111001;4'h2:seg = 7'b0100100;4'h3:seg = 7'b0110000;4'h4:seg = 7'b0011001;4'h5:seg = 7'b0010010;4'h6:seg = 7'b0000010;4'h7:seg = 7'b1111000;4'h8:seg = 7'b0000000;4'h9:seg = 7'b0010000;4'ha:seg = 7'b0001000;4'hb:seg = 7'b0000011;4'hc:seg = 7'b1000110;4'hd:seg = 7'b0100001;4'he:seg = 7'b0000110;4'hf:seg = 7'b0001110;endcaseassign sel = (En)?sel_r:8'b0000_0000;endmoduleTOPmodule HXE_top(Clk,Rst_n,sel,seg);input Clk;//50Minput Rst_n;output [7:0] sel;//数码管位选(选择当前要显示的数码管)output [6:0] seg;//数码管段选(当前要显示的内容)wire[31:0]disp_data;hex_data hex_data(.probe(),.source(disp_data));HXE8 HXE8(.Clk(Clk),.Rst_n(Rst_n),.En(1'b1),.disp_data(disp_data),.sel(sel),.seg(seg));endmodule第十一课uart发数据module uart_byte_tx(Clk,Rst_n,data_byte,send_en,baud_set,Rs232_Tx,Tx_Done,uart_state);input Clk;input Rst_n;input [7:0]data_byte;input send_en;input [2:0]baud_set;output reg Rs232_Tx;output reg Tx_Done;output reg uart_state;reg bps_clk;//波特率时钟reg [15:0]div_cnt;//分频计数器reg [15:0]bps_DR;//分频计数最大值reg [3:0]bps_cnt;//波特率时钟计数器reg [7:0]r_data_byte;localparam START_BIT = 1'b0; localparam STOP_BIT = 1'b1;always@(posedge Clk or negedge Rst_n) if(!Rst_n)uart_state <= 1'b0;else if(send_en)uart_state <= 1'b1;else if(bps_cnt == 4'd11)uart_state <= 1'b0;elseuart_state <= uart_state;always@(posedge Clk or negedge Rst_n) if(!Rst_n)r_data_byte <= 8'd0;else if(send_en)r_data_byte <= data_byte;elser_data_byte <= r_data_byte;always@(posedge Clk or negedge Rst_n) if(!Rst_n)bps_DR <= 16'd5207;else begincase(baud_set)0:bps_DR <= 16'd5207;1:bps_DR <= 16'd2603;2:bps_DR <= 16'd1301;3:bps_DR <= 16'd867;4:bps_DR <= 16'd433;default:bps_DR <= 16'd5207;endcaseend//counteralways@(posedge Clk or negedge Rst_n) if(!Rst_n)div_cnt <= 16'd0;else if(uart_state)beginif(div_cnt == bps_DR)div_cnt <= 16'd0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 16'd0;// bps_clk genalways@(posedge Clk or negedge Rst_n) if(!Rst_n)bps_clk <= 1'b0;else if(div_cnt == 16'd1)bps_clk <= 1'b1;elsebps_clk <= 1'b0;//bps counteralways@(posedge Clk or negedge Rst_n) if(!Rst_n)bps_cnt <= 4'd0;else if(bps_cnt == 4'd11)bps_cnt <= 4'd0;else if(bps_clk)bps_cnt <= bps_cnt + 1'b1;elsebps_cnt <= bps_cnt;always@(posedge Clk or negedge Rst_n) if(!Rst_n)Tx_Done <= 1'b0;else if(bps_cnt == 4'd11)Tx_Done <= 1'b1;elseTx_Done <= 1'b0;always@(posedge Clk or negedge Rst_n)if(!Rst_n)Rs232_Tx <= 1'b1;else begincase(bps_cnt)0:Rs232_Tx <= 1'b1;1:Rs232_Tx <= START_BIT;2:Rs232_Tx <= r_data_byte[0];3:Rs232_Tx <= r_data_byte[1];4:Rs232_Tx <= r_data_byte[2];5:Rs232_Tx <= r_data_byte[3];6:Rs232_Tx <= r_data_byte[4];7:Rs232_Tx <= r_data_byte[5];8:Rs232_Tx <= r_data_byte[6];9:Rs232_Tx <= r_data_byte[7];10:Rs232_Tx <= STOP_BIT;default:Rs232_Tx <= 1'b1;endcaseendEndmoduleTOPmodule uart_tx_top(Clk,Rst_n,Rs232_Tx,key_in0,led);input Clk;input Rst_n;input key_in0;output Rs232_Tx;output led;wire send_en;wire [7:0]data_byte;wire key_flag0;wire key_state0;assign send_en = key_flag0 & !key_state0;uart_byte_tx uart_byte_tx(.Clk(Clk),.Rst_n(Rst_n),.data_byte(data_byte),.send_en(send_en),.baud_set(3'd0),.Rs232_Tx(Rs232_Tx),.Tx_Done(),.uart_state(led));key_filter key_filter0(.Clk(Clk),.Rst_n(Rst_n),.key_in(key_in0),.key_flag(key_flag0),.key_state(key_state0) );issp issp(.probe(),.source(data_byte));endmodule第十二课uart收数据module uart_byte_rx(Clk,Rst_n,baud_set,Rs232_Rx,data_byte,Rx_Done);input Clk;input Rst_n;input [2:0]baud_set;input Rs232_Rx;output reg [7:0]data_byte;output reg Rx_Done;reg s0_Rs232_Rx,s1_Rs232_Rx;//同步寄存器reg tmp0_Rs232_Rx,tmp1_Rs232_Rx;//数据寄存器reg [15:0]bps_DR;//分频计数器计数最大值reg [15:0]div_cnt;//分频计数器reg bps_clk;//reg [7:0]bps_cnt;reg uart_state;reg [2:0] r_data_byte [7:0];reg [7:0] tmp_data_byte;reg [2:0] START_BIT,STOP_BIT;wire nedege;//同步寄存器,消除亚稳态always@(posedge Clk or negedge Rst_n)if(!Rst_n)begins0_Rs232_Rx <= 1'b0;s1_Rs232_Rx <= 1'b0;endelse begins0_Rs232_Rx <= Rs232_Rx;s1_Rs232_Rx <= s0_Rs232_Rx;end//数据寄存器always@(posedge Clk or negedge Rst_n)if(!Rst_n)begintmp0_Rs232_Rx <= 1'b0;tmp1_Rs232_Rx <= 1'b0;endelse begintmp0_Rs232_Rx <= s1_Rs232_Rx;tmp1_Rs232_Rx <= tmp0_Rs232_Rx;endassign nedege = !tmp0_Rs232_Rx & tmp1_Rs232_Rx; always@(posedge Clk or negedge Rst_n)if(!Rst_n)bps_DR <= 16'd324;else begincase(baud_set)0:bps_DR <= 16'd324;1:bps_DR <= 16'd162;2:bps_DR <= 16'd80;3:bps_DR <= 16'd53;4:bps_DR <= 16'd26;default:bps_DR <= 16'd324;endcaseend//counteralways@(posedge Clk or negedge Rst_n)if(!Rst_n)div_cnt <= 16'd0;else if(uart_state)beginif(div_cnt == bps_DR)div_cnt <= 16'd0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 16'd0;// bps_clk genalways@(posedge Clk or negedge Rst_n)if(!Rst_n)bps_clk <= 1'b0;else if(div_cnt == 16'd1)bps_clk <= 1'b1;elsebps_clk <= 1'b0;//bps counteralways@(posedge Clk or negedge Rst_n)if(!Rst_n)bps_cnt <= 8'd0;else if(bps_cnt == 8'd159 | (bps_cnt == 8'd12 && (START_BIT > 2))) bps_cnt <= 8'd0;else if(bps_clk)bps_cnt <= bps_cnt + 1'b1;elsebps_cnt <= bps_cnt;always@(posedge Clk or negedge Rst_n)if(!Rst_n)Rx_Done <= 1'b0;else if(bps_cnt == 8'd159)Rx_Done <= 1'b1;elseRx_Done <= 1'b0;//always@(posedge Clk or negedge Rst_n) //if(!Rst_n)//data_byte <= 8'd0;//else if(bps_cnt == 8'd159)//data_byte <= tmp_data_byte;//else//data_byte <= data_byte;always@(posedge Clk or negedge Rst_n)if(!Rst_n)data_byte <= 8'd0;else if(bps_cnt == 8'd159)begindata_byte[0] <= r_data_byte[0][2];data_byte[1] <= r_data_byte[1][2];data_byte[2] <= r_data_byte[2][2];data_byte[3] <= r_data_byte[3][2];data_byte[4] <= r_data_byte[4][2];data_byte[5] <= r_data_byte[5][2];data_byte[6] <= r_data_byte[6][2];data_byte[7] <= r_data_byte[7][2];endalways@(posedge Clk or negedge Rst_n)if(!Rst_n)beginSTART_BIT = 3'd0;r_data_byte[0] <= 3'd0;r_data_byte[1] <= 3'd0;r_data_byte[2] <= 3'd0;r_data_byte[3] <= 3'd0;r_data_byte[4] <= 3'd0;r_data_byte[5] <= 3'd0;r_data_byte[6] <= 3'd0;r_data_byte[7] <= 3'd0;STOP_BIT = 3'd0;endelse if(bps_clk)begincase(bps_cnt)0:beginSTART_BIT = 3'd0;r_data_byte[0] <= 3'd0;r_data_byte[1] <= 3'd0;r_data_byte[2] <= 3'd0;r_data_byte[3] <= 3'd0;r_data_byte[4] <= 3'd0;r_data_byte[5] <= 3'd0;r_data_byte[6] <= 3'd0;r_data_byte[7] <= 3'd0;STOP_BIT = 3'd0;end6,7,8,9,10,11:START_BIT <= START_BIT + s1_Rs232_Rx;22,23,24,25,26,27:r_data_byte[0] <= r_data_byte[0] + s1_Rs232_Rx;38,39,40,41,42,43:r_data_byte[1] <= r_data_byte[1] + s1_Rs232_Rx;54,55,56,57,58,59:r_data_byte[2] <= r_data_byte[2] + s1_Rs232_Rx;70,71,72,73,74,75:r_data_byte[3] <= r_data_byte[3] + s1_Rs232_Rx;86,87,88,89,90,91:r_data_byte[4] <= r_data_byte[4] + s1_Rs232_Rx;102,103,104,105,106,107:r_data_byte[5] <= r_data_byte[5] + s1_Rs232_Rx;118,119,120,121,122,123:r_data_byte[6] <= r_data_byte[6] + s1_Rs232_Rx;134,135,136,137,138,139:r_data_byte[7] <= r_data_byte[7] + s1_Rs232_Rx;150,151,152,153,154,155:STOP_BIT <= STOP_BIT + s1_Rs232_Rx;default:beginSTART_BIT = START_BIT;r_data_byte[0] <= r_data_byte[0];r_data_byte[1] <= r_data_byte[1];r_data_byte[2] <= r_data_byte[2];r_data_byte[3] <= r_data_byte[3];r_data_byte[4] <= r_data_byte[4];r_data_byte[5] <= r_data_byte[5];r_data_byte[6] <= r_data_byte[6];r_data_byte[7] <= r_data_byte[7];STOP_BIT = STOP_BIT;endendcaseendalways@(posedge Clk or negedge Rst_n)if(!Rst_n)uart_state <= 1'b0;else if(nedege)uart_state <= 1'b1;else if(Rx_Done || (bps_cnt == 8'd12 && (START_BIT > 2))) uart_state <= 1'b0;elseuart_state <= uart_state;EndmoduleTOPmodule uart_rx_top(Clk,Rst_n,Rs232_Rx);input Clk;input Rst_n;input Rs232_Rx;reg [7:0]data_rx_r;wire [7:0]data_rx;wire Rx_Done;uart_byte_rx uart_byte_rx(.Clk(Clk),.Rst_n(Rst_n),.baud_set(3'd0),.Rs232_Rx(Rs232_Rx),.data_byte(data_rx),.Rx_Done(Rx_Done));issp issp(.probe(data_rx_r),.source());always@(posedge Clk or negedge Rst_n)if(!Rst_n)data_rx_r <= 8'd0;else if(Rx_Done)data_rx_r <= data_rx;elsedata_rx_r <= data_rx_r;Endmodule第十三课DPROMmodule CTRL(Clk,Rst_n,Key_flag,Key_state,Rx_Done,Tx_Done,rdaddress,wraddress,wren,Send_en);input Clk;input Rst_n;input Key_flag;input Key_state;input Rx_Done;input Tx_Done;output reg[7:0]rdaddress;output reg[7:0]wraddress;output wren;output reg Send_en;assign wren = Rx_Done;reg do_send;//reg r0_send_done,r1_send_done;always@(posedge Clk or negedge Rst_n) if(!Rst_n)wraddress <= 8'd0;else if(Rx_Done)wraddress <= wraddress + 1'b1;elsewraddress <= wraddress;always@(posedge Clk or negedge Rst_n)if(!Rst_n)do_send <= 1'd0;else if(Key_flag && !Key_state)do_send <= ~do_send;always@(posedge Clk or negedge Rst_n)if(!Rst_n)rdaddress <= 8'd0;else if(do_send && Tx_Done)rdaddress <= rdaddress + 8'd1;elserdaddress <= rdaddress;always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginr0_send_done <= 1'b0;r1_send_done <= 1'b0;endelse beginr0_send_done <= (do_send && Tx_Done);r1_send_done <= r0_send_done;endalways@(posedge Clk or negedge Rst_n)if(!Rst_n)Send_en <= 1'b0;else if(Key_flag && !Key_state)Send_en <= 1'b1;else if(r1_send_done)Send_en <= 1'b1;elseSend_en <= 1'b0;endmodule ——————————————————————————————module UART_DPRAM(Clk,Rst_n,Key_in,Rs232_Rx,Rs232_Tx);input Clk;input Rst_n;input Key_in;input Rs232_Rx;output Rs232_Tx;wire Key_flag;wire Key_state;wire Rx_Done;wire Tx_Done;wire Send_en;wire [7:0]rdaddress,wraddress;wire wren;wire [7:0]rx_data,tx_data;uart_byte_tx uart_byte_tx(.Clk(Clk),.Rst_n(Rst_n),.data_byte(tx_data),.send_en(Send_en),.baud_set(3'd0),.Rs232_Tx(Rs232_Tx),.Tx_Done(Tx_Done),.uart_state());uart_byte_rx uart_byte_rx(.Clk(Clk),.Rst_n(Rst_n),.baud_set(3'd0),.Rs232_Rx(Rs232_Rx),.data_byte(rx_data),.Rx_Done(Rx_Done) );key_filter key_filter(.Clk(Clk),.Rst_n(Rst_n),.key_in(Key_in),.key_flag(Key_flag),.key_state(Key_state) );dpram dpram0(.clock(Clk),.data(rx_data),.rdaddress(rdaddress),.wraddress(wraddress),.wren(wren),.q(tx_data));CTRL CTRL(.Clk(Clk),.Rst_n(Rst_n),.Key_flag(Key_flag),.Key_state(Key_state),.Rx_Done(Rx_Done),.Tx_Done(Tx_Done),.rdaddress(rdaddress),.wraddress(wraddress),.wren(wren),.Send_en(Send_en));endmodule第十四课ROMmodule ROM_top(Clk,Rst_n,q);input Clk;input Rst_n;output [7:0]q;reg [7:0]addr;rom rom(.address(addr),.clock(Clk),.q(q));always@(posedge Clk or negedge Rst_n) if(!Rst_n)addr <= 8'd0;elseaddr <= addr + 1'b1;endmodule仿真`timescale 1ns/1ns`define clk_period 20module rom_tb;reg [7:0]addr;reg clk;wire [7:0]q;rom rom(.address(addr),.clock(clk),.q(q));initial clk = 1;always #(`clk_period/2) clk = ~clk;integer i;initial beginaddr = 0;#21;for(i=0;i<2550;i=i+1)begin#`clk_period;addr = addr + 1;end#(`clk_period * 50);$stop;endendmodule第十五课fifo第十六课pll第十七课tlc5620module TCL5620_TOP(Clk,Rst_n,TLC5620_CLK,TLC5620_DATA,TLC5620_LOAD,TLC5620_LDAC);input Clk;input Rst_n;output TLC5620_CLK;output TLC5620_DATA;output TLC5620_LOAD;output TLC5620_LDAC;wire [10:0]CtrlWord;CtrlWordSource CtrlWordSource( .probe(),.source(CtrlWord));TLC5620_CTRL TLC5620_CTRL0(.Clk(Clk),.Rst_n(Rst_n),.UpdateReq(1'b1),.CtrlWord(CtrlWord),.UpdateDone(),.TLC5620_CLK(TLC5620_CLK),.TLC5620_DATA(TLC5620_DATA),.TLC5620_LOAD(TLC5620_LOAD),.TLC5620_LDAC(TLC5620_LDAC));endmodule ————————————————————————————//Vo(DAC A|B|C|D)= REF * CODE/256 *(1 + RNG bit value)module TLC5620_CTRL(Clk,Rst_n,UpdateReq,CtrlWord,UpdateDone,TLC5620_CLK,TLC5620_DATA,TLC5620_LOAD,TLC5620_LDAC);input Clk;input Rst_n;input UpdateReq;//更新输出电压请求input [10:0]CtrlWord;//ADDR[1:0];RNG bit;CODE[7:0]output reg UpdateDone;//更新输出电压完成标志信号output reg TLC5620_CLK;//TLC5620接口时钟信号output reg TLC5620_DATA;//TLC5620数据输入信号output reg TLC5620_LOAD;//output reg TLC5620_LDAC;reg [9:0] Cnt;//线性序列机计数器//线性序列机计数器计数进程always@(posedge Clk or negedge Rst_n)if(!Rst_n)Cnt <= 10'd0;else if(UpdateReq == 1 | (Cnt != 10'd0))begin if(Cnt == 10'd820)Cnt <= 10'd0;elseCnt <= Cnt + 10'd1;endelseCnt <= 10'd0;//线性序列机控制进程always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginTLC5620_CLK <= 1'b0;TLC5620_DATA <= 1'b0;TLC5620_LOAD <= 1'b0;TLC5620_LDAC <= 1'b0;UpdateDone <= 1'b0;endelse begincase(Cnt)0:beginTLC5620_CLK <= 1'b0;TLC5620_DATA <= 1'b0;TLC5620_LOAD <= 1'b1;TLC5620_LDAC <= 1'b0;UpdateDone <= 1'b0;end10:beginTLC5620_CLK <= 1'b1;TLC5620_DATA <= CtrlWord[10];end40: TLC5620_CLK <= 1'b0;70:begin。
代码LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY FREQUENCY ISPORT ( CLK : IN STD_LOGIC;A : IN STD_LOGIC_VECTOR(4 DOWNTO 0);--设置A的初值FOUT : OUT STD_LOGIC );END;ARCHITECTURE one OF FREQUENCY ISSIGNAL FULL : STD_LOGIC;BEGINP_REG: PROCESS(CLK)V ARIABLE CNT1 : STD_LOGIC_VECTOR(4 DOWNTO 0);BEGINIF CLK'EVENT AND CLK = '1' THENIF CNT1 = "11111" THENCNT1 := A; --当CNT1计数计满时,输入数据D被同步预置给计数器CNT1FULL <= '1'; --同时使溢出标志信号FULL输出为高电平ELSE CNT1 := CNT1 + 1; --否则继续作加1计数FULL <= '0'; --且输出溢出标志信号FULL为低电平END IF;END IF;END PROCESS P_REGP_DIV: PROCESS(FULL)V ARIABLE CNT2 : STD_LOGIC;BEGINIF FULL'EVENT AND FULL = '1' THENCNT2 := NOT CNT2; --如果溢出标志信号FULL为高电平,D触发器输出取反IF CNT2 = '1' THEN FOUT <= '1';ELSE FOUT <= '0';END IF;END IF;END PROCESS P_DIVEND;代码LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_ARITH.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY BUTTON ISPORT ( d : IN STD_LOGIC_VECTOR(2 DOWNTO 0) a,b,c : OUT STD_LOGIC ) END; ARCHITECTURE ONE OF BUTTON ISBEGINPROCESS( d )BEGINCASE d ISWHEN "000" => NULL;WHEN OTHERS => a <= d(0);--dltb <= d(1);--sqrc <= d(2);--sinEND CASE;END PROCESS;END;三角波信号产生模块代码library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity delta isport ( clk : in std_logicclr : in std_logic;q : out std_logic_vector(7 downto 0) )end delta;architecture one of delta isbeginprocess( clk,clr)variable num : std_logic_vector(7 downto 0);variable ff : std_logic;beginif clr = '0' thennum := "00000000";else if clk'event and clk = '1' then--时钟信号有上升沿时有效if ff = '0' thenif num = "11111000" thenff :='1';elsenum := num + 8;end if;--以上,ff=0时,上升,直至num加到11111000时,使ff=1elseif num = "00000111" thennum := "00000000";ff := '0';elsenum := num -8;--以上,ff=1时,下降,直至num减到00000111时,使ff=0 end if;end if;end if;end if;q <= num;--每一次脉冲,将num的值给q以输出end processend;四.方波信号产生模块代码library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity aquare isport ( clk : in std_logicclr : in std_logic;q : out std_logic_vector(7 downto 0) )end aquare;architecture one of aquare issignal ff:bit;beginp1:process( clk,clr)variable num : std_logic_vector(5 downto 0);beginif clr = '0' thenff <= '0';else if clk'event and clk = '1' then--当时钟脉冲有一个上升沿 if num < 31 thennum := num+1;elsenum := "000000";ff <= not ff;--num每次加1,加32次ff取反1次end if;end if;end if;end process p1;p2: process( clk,ff)beginif clk'event and clk = '1' thenif ff = '1' thenq <= "11111111";--ff=1时输出高电平elseq <= "00000000";--ff=0时输出低电平end if;end if;end process p2;end;五.正弦波信号产生模块代码library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity sin isport ( clk : in std_logic --正弦信号的相位clr : in std_logic;d : out std_logic_vector(7 downto 0) ) --正弦函数值endarchitecture one of sin is--结构体开始Beginprocess( clk,clr)variable num : std_logic_vector(5 downto 0);Beginif clr = '0' thend <= "00000000";else if clk'event and clk = '1' thenif num = "111111" thennum := "000000";--每加到111111时清零elsenum := num+1;end if;end if;end if;case num is --四个输入,共有16总相位可能360/64=5.625when "000000" => d <= CONV_STD_LOGIC_VECTOR(128,8); --每5.625取一个点when "000001" => d <= CONV_STD_LOGIC_VECTOR(141,8); --共64个点when "000010" => d <= CONV_STD_LOGIC_VECTOR(153,8);when "000011" => d <= CONV_STD_LOGIC_VECTOR(165,8);when "000100" => d <= CONV_STD_LOGIC_VECTOR(177,8);when "000101" => d <= CONV_STD_LOGIC_VECTOR(188,8);when "000110" => d <= CONV_STD_LOGIC_VECTOR(199,8);when "000111" => d <= CONV_STD_LOGIC_VECTOR(209,8);when "001000" => d <= CONV_STD_LOGIC_VECTOR(218,8);when "001001" => d <= CONV_STD_LOGIC_VECTOR(227,8);when "001010" => d <= CONV_STD_LOGIC_VECTOR(234,8);when "001011" => d <= CONV_STD_LOGIC_VECTOR(240,8);when "001100" => d <= CONV_STD_LOGIC_VECTOR(246,8);when "001101" => d <= CONV_STD_LOGIC_VECTOR(250,8);when "001110" => d <= CONV_STD_LOGIC_VECTOR(253,8);when "001111" => d <= CONV_STD_LOGIC_VECTOR(254,8); when "010000" => d <= CONV_STD_LOGIC_VECTOR(255,8); when "010001" => d <= CONV_STD_LOGIC_VECTOR(254,8); when "010010" => d <= CONV_STD_LOGIC_VECTOR(253,8); when "010011" => d <= CONV_STD_LOGIC_VECTOR(250,8); when "010100" => d <= CONV_STD_LOGIC_VECTOR(246,8); when "010101" => d <= CONV_STD_LOGIC_VECTOR(240,8); when "010110" => d <= CONV_STD_LOGIC_VECTOR(234,8); when "010111" => d <= CONV_STD_LOGIC_VECTOR(227,8); when "011000" => d <= CONV_STD_LOGIC_VECTOR(218,8); when "011001" => d <= CONV_STD_LOGIC_VECTOR(209,8); when "011010" => d <= CONV_STD_LOGIC_VECTOR(199,8); when "011011" => d <= CONV_STD_LOGIC_VECTOR(188,8); when "011100" => d <= CONV_STD_LOGIC_VECTOR(177,8); when "011101" => d <= CONV_STD_LOGIC_VECTOR(165,8); when "011110" => d <= CONV_STD_LOGIC_VECTOR(153,8); when "011111" => d <= CONV_STD_LOGIC_VECTOR(141,8); when "100000" => d <= CONV_STD_LOGIC_VECTOR(128,8); when "100001" => d <= CONV_STD_LOGIC_VECTOR(115,8); when "100010" => d <= CONV_STD_LOGIC_VECTOR(103,8); when "100011" => d <= CONV_STD_LOGIC_VECTOR(91,8); when "100100" => d <= CONV_STD_LOGIC_VECTOR(79,8); when "100101" => d <= CONV_STD_LOGIC_VECTOR(68,8); when "100110" => d <= CONV_STD_LOGIC_VECTOR(57,8); when "100111" => d <= CONV_STD_LOGIC_VECTOR(47,8); when "101000" => d <= CONV_STD_LOGIC_VECTOR(38,8); when "101001" => d <= CONV_STD_LOGIC_VECTOR(29,8);六.波形选择器代码library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity changer isport ( dlt,sqr,sin : in std_logicdltd,sqrd,sind : in std_logic_vector(7 downto 0);q : out std_logic_vector(7 downto 0) )end changer;architecture one of changer isBeginprocess( dlt,dltd,sqr,sqrd,sin,sind)variable temp : std_logic_vector(2 downto 0);-- variable a,b : std_logic_vector(9 downto 0);-- variable c,d,e : std_logic_vector(9 downto 0);Begintemp :=dlt&sqr&sin;case temp iswhen "100" => q <= dltd;--a00输出三角波when "010" => q <= sqrd;--0b0输出方波when "001" => q <= sind;--00c输出正弦波when others => null;end case;end processend;。
读特权同学《深入浅出玩转FPGA》有感看了特权同学的这本书,感悟颇多,最终使我重新确立了目标。
只是思路有些杂乱,我得慢慢道来: 初识特权同学实在END网站上,因为他的FPGA助学活动,在得到他的35集FPGA教学视频后,得知他已经和北京航空航天大学出版社合作出板了《深入浅出玩转FPGA》一书。
对于国内格式呆板、内容互抄的教科书,我是一直没有任何兴趣的,但是对于这样一个搞过FPGA项目的工程师写出的经验之谈,而且是以随笔的形式写出的书,我是没有任何理由放过的。
也许我最需要的不是一份说教的知识,而是一个可以在我最困难的时候让陪我聊天、给我动力的‘人’,而这个‘人’就隐藏在这本书点点滴滴、洋洋洒洒的文字之间,等着我去感悟。
由于我个人是习惯在当当网买书的,于是当下就去当当网搜索了一下,果然有这本书,售价是31.9元,但由于最近经济的原因我始终没有点下购买的按钮,于是自己买到这本书的计划便搁浅了。
也就是昨天我和一帮兄弟们去吉大的时候,偶然在兄弟那边看到了这本书,于是很爱不释手,当时便决定从兄弟手中‘横刀夺爱’了。
呵呵,于是,这本书便随我来到了理工,被我带到了实验室。
对于这样一本不同于现代呆板教材的书,我是很欣赏的,于是我开始用心去读这本书,去尽量感悟这本书的精髓,破开表面的知识去追求作者要给我们表达的深层次的意义。
很有幸的,我最后的结论是我没有选错书,在这本书中我感悟了很多,虽然我只读了第一个晚上,但这本书给我带来的感悟要比其他书籍在几周甚至几个月给我带来的感悟远远多得多...我感悟了很多,依靠串行触发是解决不了的,于是,我得用并行触发的方式来表达我的思路,首先得解释一下什么是并行触发:并行是指可以在同一时间进行响应,而没有顺序的问题。
于是,在这部分,我拿并行的概念套用一下,下面的这些感悟没有刻意的进行先后排序,既没有重要程度的高低和内容高低的划分,因为我认为:每一点思考都可以带来进步。
下面我就开始慢慢道来:1:它纠正了我对FPGA的认识 说实话,我的兄弟在去年寒假就给我买好了FPGA开发板,我们分配的任务是我在理工主要攻FPGA方向,很惭愧的是当我用原来单片机的方式去学习FPGA时遇到了很大的障碍,这段学习的路进展很缓慢,于是不知不觉已经推迟到了今年暑假。
EX1`timescale 1ns / 1psmodule johnson(clk,rst_n,led);input clk; //主时钟,25MHzinput rst_n; //低电平复位output led; // LED接口//------------------------------------reg[24:0] delay; //延时计数器always @ (posedge clk or negedge rst_n)if(!rst_n) delay <= 25'd0;else delay <= delay+1'b1; //不断计数,周期为1.34sassign led = delay[24]; //1.34s LED闪烁一次endmoduleEX2////`timescale 1ns / 1psmodule seg7(clk,rst_n,ds_stcp,ds_shcp,ds_data);input clk; //25M输入时钟信号input rst_n; //复位信号输入,低有效output ds_stcp; //74HC595的并行时钟输入,上升沿将当前串行输入数据并行输出output ds_shcp; //74HC595的串行时钟输入,上升沿锁存当前串行输入数据output ds_data; //74HC595的串行数据输入//-------------------------------------------------//参数定义//数码管显示0~F 对应段选输出parameter SEG_NUM0 = 8'h3f,//c0,SEG_NUM1 = 8'h06,//f9,SEG_NUM2 = 8'h5b,//a4,SEG_NUM3 = 8'h4f,//b0,SEG_NUM4 = 8'h66,//99,SEG_NUM5 = 8'h6d,//92,SEG_NUM6 = 8'h7d,//82,SEG_NUM7 = 8'h07,//F8,SEG_NUM8 = 8'h7f,//80,SEG_NUM9 = 8'h6f,//90,SEG_NUMA = 8'h77,//88,SEG_NUMB = 8'h7c,//83,SEG_NUMC = 8'h39,//c6,SEG_NUMD = 8'h5e,//a1,SEG_NUME = 8'h79,//86,SEG_NUMF = 8'h71;//8e;//数码管位选0~3 对应输出parameter SEG_WE0 = 4'b1110,SEG_WE1 = 4'b1101,SEG_WE2 = 4'b1011,SEG_WE3 = 4'b0111;//-------------------------------------------------//递增数据产生单元reg[24:0] cnt_1s; //1s计数器,0-24999999reg[15:0] dis_data; //数码管显示数据,16位//1s定时计数always @(posedge clk or negedge rst_n)if(!rst_n) cnt_1s <= 25'd0;else if(cnt_1s == 25'd24_999_999) cnt_1s <= 25'd0;else cnt_1s <= cnt_1s+1'b1;wire done_1s = (cnt_1s == 25'd24_999_999); //1s定时到标志位,高有效一个时钟周期//显示数据每秒递增always @(posedge clk or negedge rst_n)if(!rst_n) dis_data <= 16'd0;else if(done_1s) dis_data <= dis_data+1'b1;//-------------------------------------------------//分时显示数据控制单元reg[7:0] seg_num; //当前显示数据reg[7:0] seg_duan; //7段数码管段选信号(包括小数点为8段)reg[3:0] seg_wei; //7段数码管位选信号reg[7:0] cnt_4; //分时计数器//分时计数器always @(posedge clk or negedge rst_n)if(!rst_n) cnt_4 <= 8'd0;else cnt_4 <= cnt_4+1'b1;//显示数据always @(posedge clk or negedge rst_n)if(!rst_n) seg_num <= 8'h00;elsecase(cnt_4[7:6])2'b00: seg_num <= dis_data[3:0];2'b01: seg_num <= dis_data[7:4];2'b10: seg_num <= dis_data[11:8];2'b11: seg_num <= dis_data[15:12];default: seg_num <= 8'h00;endcase//段选数据译码always @(posedge clk or negedge rst_n)if(!rst_n) seg_duan <= 8'h00;elsecase(seg_num)4'h0: seg_duan <= SEG_NUM0;4'h1: seg_duan <= SEG_NUM1;4'h2: seg_duan <= SEG_NUM2;4'h3: seg_duan <= SEG_NUM3;4'h4: seg_duan <= SEG_NUM4;4'h5: seg_duan <= SEG_NUM5;4'h6: seg_duan <= SEG_NUM6;4'h7: seg_duan <= SEG_NUM7;4'h8: seg_duan <= SEG_NUM8;4'h9: seg_duan <= SEG_NUM9;4'ha: seg_duan <= SEG_NUMA;4'hb: seg_duan <= SEG_NUMB;4'hc: seg_duan <= SEG_NUMC;4'hd: seg_duan <= SEG_NUMD;4'he: seg_duan <= SEG_NUME;4'hf: seg_duan <= SEG_NUMF;default: ;endcase//位选译码always @(cnt_4[7:6])case(cnt_4[7:6])2'b00: seg_wei <= SEG_WE0;2'b01: seg_wei <= SEG_WE1;2'b10: seg_wei <= SEG_WE2;2'b11: seg_wei <= SEG_WE3;default: seg_wei <= 4'b1111;endcase//-------------------------------------------------//74HC95驱动译码reg ds_stcpr; //74HC595的并行时钟输入,上升沿将当前串行输入数据并行输出reg ds_shcpr; //74HC595的串行时钟输入,上升沿锁存当前串行输入数据reg ds_datar; //74HC595的串行数据输入//串行移位时钟产生always @(posedge clk or negedge rst_n)if(!rst_n) ds_shcpr <= 1'b0;else if((cnt_4 > 8'h02 && cnt_4 <= 8'h22) || (cnt_4 > 8'h42 && cnt_4 <= 8'h62) || (cnt_4 > 8'h82 && cnt_4 <= 8'ha2) || (cnt_4 > 8'hc2 && cnt_4 <= 8'he2)) ds_shcpr <= ~ds_shcpr;//串行移位数据产生always @(posedge clk or negedge rst_n)if(!rst_n) ds_datar <= 1'b0;elsecase(cnt_4)8'h02,8'h42,8'h82,8'hc2: ds_datar <= seg_duan[7];8'h04,8'h44,8'h84,8'hc4: ds_datar <= seg_duan[6];8'h06,8'h46,8'h86,8'hc6: ds_datar <= seg_duan[5];8'h08,8'h48,8'h88,8'hc8: ds_datar <= seg_duan[4];8'h0a,8'h4a,8'h8a,8'hca: ds_datar <= seg_duan[3];8'h0c,8'h4c,8'h8c,8'hcc: ds_datar <= seg_duan[2];8'h0e,8'h4e,8'h8e,8'hce: ds_datar <= seg_duan[1];8'h10,8'h50,8'h90,8'hd0: ds_datar <= seg_duan[0];8'h1a,8'h5a,8'h9a,8'hda: ds_datar <= seg_wei[0];8'h1c,8'h5c,8'h9c,8'hdc: ds_datar <= seg_wei[1];8'h1e,8'h5e,8'h9e,8'hde: ds_datar <= seg_wei[2];8'h20,8'h60,8'ha0,8'he0: ds_datar <= seg_wei[3];default: ;endcase//并行移位时钟产生always @(posedge clk or negedge rst_n)if(!rst_n) ds_stcpr <= 1'b0;else if((cnt_4 == 8'h02) || (cnt_4 == 8'h42) || (cnt_4 == 8'h82) || (cnt_4 == 8'hc2)) ds_stcpr <= 1'b0;else if((cnt_4 == 8'h23) || (cnt_4 == 8'h63) || (cnt_4 == 8'ha3) || (cnt_4 == 8'he3)) ds_stcpr <= 1'b1;wire ds_stcp = ds_stcpr;wire ds_shcp = ds_shcpr;wire ds_data = ds_datar;endmoduleEX4`timescale 1ns / 1psmodule datagene(clk,rst_n,wrf_din,wrf_wrreq);input clk; //FPAG输入时钟信号25MHzinput rst_n; //FPGA输入复位信号//wrFIFO输入控制接口output[7:0] wrf_din; //数据写入缓存FIFO输入数据总线output wrf_wrreq; //数据写入缓存FIFO数据输入请求,高有效//------------------------------------------//每1s写入16个8bit数据到fifo中reg[24:0] cntwr; //写sdram定时计数器always @(posedge clk or negedge rst_n)if(!rst_n) cntwr <= 25'd0;else cntwr <= cntwr+1'b1;assign wrf_wrreq = (cntwr >= 25'h1fffff0) && (cntwr <= 25'h1ffffff); //FIFO写有效信号//------------------------------------------//写fifo请求信号产生,即wrfifo的写入有效信号reg[7:0] wrf_dinr; //wrfifo的写入数据always @(posedge clk or negedge rst_n)if(!rst_n) wrf_dinr <= 8'd0;else if((cntwr >= 25'h1fffff0) && (cntwr <= 25'h1ffffff))wrf_dinr <= wrf_dinr+1'b1; //写入数据递增assign wrf_din = wrf_dinr;endmodule`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////// // Company :// Engineer : 特权franchises3// Create Date : 2009.05.04// Design Name :// Module Name : uart_ctrl// Project Name : uartfifo// Target Device: Cyclone EP1C3T144C8// Tool versions: Quartus II 8.1// Description : 串口数据发送控制模块//// Revision : V1.0// Additional Comments :////////////////////////////////////////////////////////////////////////////////// module uart_ctrl(clk,rst_n,tx_data,tx_start,fifo232_rdreq,rs232_tx);input clk; // 25MHz主时钟input rst_n; //低电平复位信号input[7:0] tx_data; //待发送数据input tx_start; //串口发送数据启动标志位,高有效output fifo232_rdreq; //FIFO读请求信号,高有效output rs232_tx; //RS232发送数据信号//----------------------------------------------------------------//串口发送底层模块和串口波特率选择模块接口wire clk_bps; //发送数据标志位,高有效wire bps_start; //波特率时钟计数器启动信号,高有效//----------------------------------------------------------------//例化串口数据发送底层模块uart_tx uut_tx(.clk(clk),.rst_n(rst_n),.tx_data(tx_data),.tx_start(tx_start),.clk_bps(clk_bps),.rs232_tx(rs232_tx),.bps_start(bps_start),.fifo232_rdreq(fifo232_rdreq));//例化串口数据发送波特率控制模块uart_speed_select uut_ss(.clk(clk),.rst_n(rst_n),.bps_start(bps_start),.clk_bps(clk_bps));Endmodule`timescale 1ns / 1psmodule uart_speed_select(clk,rst_n,bps_start,clk_bps);input clk; // 25MHz时钟input rst_n; //低电平复位信号input bps_start; //波特率时钟计数器启动信号,高有效output clk_bps; //发送数据标志位,高有效/*`define bps9600 5207/2 //波特率为9600bps`define bps19200 2603/2 //波特率为19200bps `define bps38400 1301/2 //波特率为38400bps `define bps57600 867/2 //波特率为57600bps `define bps115200 433/2 //波特率为115200bps`define bps9600_2 2603/2`define bps19200_2 1301/2`define bps38400_2 650/2`define bps57600_2 433/2`define bps115200_2 216/2*///以下波特率分频计数值可参照上面的参数进行更改`define BPS_PARA 2604 //波特率为9600时的分频计数值`define BPS_PARA_2 1302 //波特率为9600时的分频计数值的一半,用于数据采样//----------------------------------------------------------//----------------------------------------------------------reg[12:0] cnt; //分频计数器reg clk_bps_r; //波特率数据改变标志位reg[2:0] uart_ctrl; // uart波特率选择寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) cnt <= 13'd0;else if(cnt == `BPS_PARA) cnt <= 13'd0; //波特率计数溢出后清零else if(bps_start) cnt <= cnt+1'b1; //波特率时钟计数启动else cnt <= 13'd0; //波特率计数停止always @ (posedge clk or negedge rst_n)if(!rst_n) clk_bps_r <= 1'b0;else if(cnt == `BPS_PARA_2) clk_bps_r <= 1'b1; // clk_bps_r高电平作为发送数据的数据改变点else clk_bps_r <= 1'b0;assign clk_bps = clk_bps_r;endmodule`timescale 1ns / 1psmodule uart_tx(clk,rst_n,tx_data,tx_start,clk_bps,rs232_tx,bps_start,fifo232_rdreq);input clk; // 25MHz主时钟input rst_n; //低电平复位信号input[7:0] tx_data; //待发送数据input tx_start; //串口发送数据启动标志位,高有效input clk_bps; //发送数据标志位,高有效output rs232_tx; // RS232发送数据信号output bps_start; //波特率时钟计数器启动信号,高有效output fifo232_rdreq; //FIFO读请求信号,高有效//---------------------------------------------------------reg tx_en; //发送数据使能信号,高有效reg[3:0] num;always @ (posedge clk or negedge rst_n)if(!rst_n) tx_en <= 1'b0;else if(num==4'd11) tx_en <= 1'b0; //数据发送完成else if(tx_start) tx_en <= 1'b1; //进入发送数据状态中assign bps_start = tx_en;//tx_en脉冲上升沿检测,作为FIFO读使能信号reg tx_enr1,tx_enr2; //tx_en寄存器always @(posedge clk or negedge rst_n)if(!rst_n) begintx_enr1 <= 1'b1;tx_enr2 <= 1'b1;endelse begintx_enr1 <= tx_en;tx_enr2 <= tx_enr1;endassign fifo232_rdreq = tx_enr1 & ~tx_enr2; //tx_en上升沿置高一个时钟周期//---------------------------------------------------------reg rs232_tx_r; // RS232发送数据信号always @ (posedge clk or negedge rst_n)if(!rst_n) beginnum <= 4'd0;rs232_tx_r <= 1'b1;endelse if(tx_en) beginif(clk_bps) beginnum <= num+1'b1;case (num)4'd0: rs232_tx_r <= 1'b0; //发送起始位4'd1: rs232_tx_r <= tx_data[0]; //发送bit04'd2: rs232_tx_r <= tx_data[1]; //发送bit14'd3: rs232_tx_r <= tx_data[2]; //发送bit24'd4: rs232_tx_r <= tx_data[3]; //发送bit34'd5: rs232_tx_r <= tx_data[4]; //发送bit44'd6: rs232_tx_r <= tx_data[5]; //发送bit54'd7: rs232_tx_r <= tx_data[6]; //发送bit64'd8: rs232_tx_r <= tx_data[7]; //发送bit74'd9: rs232_tx_r <= 1'b1; //发送结束位default: rs232_tx_r <= 1'b1;endcaseendelse if(num==4'd11) num <= 4'd0; //复位,实际发送一个数据时间为10.5个波特率时钟周期endassign rs232_tx = rs232_tx_r;endmodule`timescale 1ns / 1psmodule uartfifo(clk,rst_n,rs232_tx);input clk; // 25MHz主时钟input rst_n; //低电平复位信号output rs232_tx; //RS232发送数据信号wire[7:0] wrf_din; //数据写入缓存FIFO输入数据总线wire wrf_wrreq; //数据写入缓存FIFO数据输入请求,高有效wire[7:0] tx_data; //串口待发送数据wire tx_start; //串口发送数据启动标志位,高有效wire fifo232_rdreq; //FIFO读请求信号,高有效wire fifo_empty; //FIFO空标志位,高有效assign tx_start = ~fifo_empty; //fifo有数据即启动串口模块发送数据//例化232发送数据产生模块datagene uut_datagene(.clk(clk),.rst_n(rst_n),.wrf_din(wrf_din),.wrf_wrreq(wrf_wrreq));//例化FIFOfifo232 fifo232_inst (.clock(clk),.data(wrf_din),.rdreq(fifo232_rdreq),.wrreq(wrf_wrreq),.empty(fifo_empty),.q(tx_data));//例化串口发送模块uart_ctrl uut_uartfifo(.clk(clk),.rst_n(rst_n),.tx_data(tx_data),.tx_start(tx_start),.fifo232_rdreq(fifo232_rdreq),.rs232_tx(rs232_tx));endmoduleEX5`timescale 1ns / 1psmodule vga_char(clk_25m,rst_n, //系统控制hsync,vsync,vga_r,vga_g,vga_b // VGA控制);input clk_25m; // 25MHzinput rst_n; //低电平复位// FPGA与VGA接口信号output hsync; //行同步信号output vsync; //场同步信号output[2:0] vga_r;output[2:0] vga_g;output[1:0] vga_b;//--------------------------------------------------// 坐标计数reg[9:0] x_cnt; //行坐标reg[9:0] y_cnt; //列坐标always @ (posedge clk_25m or negedge rst_n)if(!rst_n) x_cnt <= 10'd0;else if(x_cnt == 10'd799) x_cnt <= 10'd0;else x_cnt <= x_cnt+1'b1;always @ (posedge clk_25m or negedge rst_n)if(!rst_n) y_cnt <= 10'd0;else if(y_cnt == 10'd524) y_cnt <= 10'd0;else if(x_cnt == 10'd799) y_cnt <= y_cnt+1'b1;//--------------------------------------------------// VGA场同步,行同步信号reg hsync_r,vsync_r; //同步信号always @ (posedge clk_25m or negedge rst_n)if(!rst_n) hsync_r <= 1'b1;else if(x_cnt == 10'd0) hsync_r <= 1'b0; //产生hsync信号else if(x_cnt == 10'd96) hsync_r <= 1'b1;always @ (posedge clk_25m or negedge rst_n)if(!rst_n) vsync_r <= 1'b1;else if(y_cnt == 10'd0) vsync_r <= 1'b0; //产生vsync信号else if(y_cnt == 10'd2) vsync_r <= 1'b1;assign hsync = hsync_r;assign vsync = vsync_r;//--------------------------------------------------//有效显示标志位产生reg valid_yr; //行显示有效信号always @ (posedge clk_25m or negedge rst_n)if(!rst_n) valid_yr <= 1'b0;else if(y_cnt == 10'd32) valid_yr <= 1'b1;else if(y_cnt == 10'd512) valid_yr <= 1'b0;wire valid_y = valid_yr;reg valid_r; // VGA有效显示区标志位always @ (posedge clk_25m or negedge rst_n)if(!rst_n) valid_r <= 1'b0;else if((x_cnt == 10'd141) && valid_y) valid_r <= 1'b1;else if((x_cnt == 10'd781) && valid_y) valid_r <= 1'b0;wire valid = valid_r;//wire[9:0] x_dis; //横坐标显示有效区域相对坐标值0-639 wire[9:0] y_dis; //竖坐标显示有效区域相对坐标值0-479//assign x_dis = x_cnt - 10'd142;assign y_dis = y_cnt - 10'd33;//--------------------------------------------------//--------------------------------------------------// VGA色彩信号产生/*RGB = 000 黑色RGB = 100 红色= 001 蓝色= 101 紫色= 010 绿色= 110 黄色= 011 青色= 111 白色*//*EDN字模参数*/parameter char_line0 = 24'h000000,char_line1 = 24'h000000,char_line2 = 24'h000000,char_line3 = 24'hfcf8c7,char_line4 = 24'h424462,char_line5 = 24'h484262,char_line6 = 24'h484252,char_line7 = 24'h784252,char_line8 = 24'h48424a,char_line9 = 24'h48424a,char_linea = 24'h40424a,char_lineb = 24'h424246,char_linec = 24'h424446,char_lined = 24'hfcf8e2,char_linee = 24'h000000,char_linef = 24'h000000;reg[4:0] char_bit; //显示位计算always @(posedge clk_25m or negedge rst_n)if(!rst_n) char_bit <= 5'h1f;else if(x_cnt == 10'd442) char_bit <= 5'd23; //显示最高位数据else if(x_cnt > 10'd442 && x_cnt < 10'd466) char_bit <= char_bit-1'b1; //依次显示后面的数据reg[7:0] vga_rgb; // VGA色彩显示寄存器always @ (posedge clk_25m)if(!valid) vga_rgb <= 8'd0;else if(x_cnt > 10'd442 && x_cnt < 10'd467) begincase(y_dis)10'd231: if(char_line0[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_11100; //绿色10'd232: if(char_line1[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd233: if(char_line2[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd234: if(char_line3[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd235: if(char_line4[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd236: if(char_line5[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd237: if(char_line6[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd238: if(char_line7[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd239: if(char_line8[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd240: if(char_line9[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd241: if(char_linea[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd242: if(char_lineb[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd243: if(char_linec[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd244: if(char_lined[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd245: if(char_linee[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色10'd246: if(char_linef[char_bit]) vga_rgb <= 8'b111_000_00; //红色else vga_rgb <= 8'b000_111_00; //绿色default: vga_rgb <= 8'h00;endcaseendelse vga_rgb <= 8'h00;//r,g,b控制液晶屏颜色显示assign vga_r = vga_rgb[7:5];assign vga_g = vga_rgb[4:2];assign vga_b = vga_rgb[1:0];endmoduleEX6module sys_ram (address,clock,data,wren,q);input [11:0] address;input clock;input [7:0] data;input wren;output [7:0] q;endmodulemodule mem_cof(clk,rst_n,ram_wr,ram_addr,ram_din,ram_dout);input clk; //系统输入时钟,25Minput rst_n; //系统服务信号,低有效input ram_wr; //RAM写入使能信号,高表示写入input[11:0] ram_addr; //RAM地址总线input[7:0] ram_din; //RAM写入数据总线output[7:0] ram_dout; //RAM读出数据总线//例化M4K生成的RAMsys_ram uut_ram(.address(ram_addr),.clock(clk),.data(ram_din),.wren(ram_wr),.q(ram_dout));endmodulemodule sys_ram (address,clock,data,wren,q);input [11:0] address;input clock;input [7:0] data;input wren;output [7:0] q;wire [7:0] sub_wire0;wire [7:0] q = sub_wire0[7:0];altsyncram altsyncram_component (.wren_a (wren),.clock0 (clock),.address_a (address),.data_a (data),.q_a (sub_wire0),.aclr0 (1'b0),.aclr1 (1'b0),.address_b (1'b1),.addressstall_a (1'b0),.addressstall_b (1'b0),.byteena_a (1'b1),.byteena_b (1'b1),.clock1 (1'b1),.clocken0 (1'b1),.clocken1 (1'b1),.clocken2 (1'b1),.clocken3 (1'b1),.data_b (1'b1),.eccstatus (),.q_b (),.rden_a (1'b1),.rden_b (1'b1),.wren_b (1'b0));defparamaltsyncram_component.address_aclr_a = "NONE",altsyncram_component.indata_aclr_a = "NONE",altsyncram_component.intended_device_family = "Cyclone",altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",altsyncram_component.lpm_type = "altsyncram",altsyncram_component.numwords_a = 4096,altsyncram_component.operation_mode = "SINGLE_PORT",altsyncram_component.outdata_aclr_a = "NONE",altsyncram_component.outdata_reg_a = "CLOCK0",altsyncram_component.power_up_uninitialized = "FALSE",altsyncram_component.widthad_a = 12,altsyncram_component.width_a = 8,altsyncram_component.width_byteena_a = 1,altsyncram_component.wrcontrol_aclr_a = "NONE";endmoduleEX7module mem_cof(clk,rst_n,shift_din,shift_dout,//shift_all_datataps0x,taps1x,taps2x,taps3x,taps4x,taps5x,taps6x,taps7x );input clk; //系统输入时钟,25Minput rst_n; //系统服务信号,低有效input[3:0] shift_din; //移位RAM输入数据output[3:0] shift_dout; //移位RAM输出数据//output[31:0] shift_all_data; //移位RAM全部64bit数据output [3:0] taps0x;output [3:0] taps1x;output [3:0] taps2x;output [3:0] taps3x;output [3:0] taps4x;output [3:0] taps5x;output [3:0] taps6x;output [3:0] taps7x;//例化M4K生成的移位RAMshift_ram uut_shift(.clken(rst_n), //移位RAM使能信号,高有效.clock(clk),.shiftin(shift_din),.shiftout(shift_dout),//.taps(shift_all_data).taps0x(taps0x),.taps1x(taps1x),.taps2x(taps2x),.taps3x(taps3x),.taps4x(taps4x),.taps5x(taps5x),.taps6x(taps6x),.taps7x(taps7x));endmodule。
Quartus II如何输入和显示中文注释说明a) Quartus II 8.0以前的版本,可以输入中文也可以显示中文;b) Quartus II 8.0以后,Quartus II 9.1以前版本的版本可以显示中文,但是不能输入中文;c) Quartus II 9.1之后,Quartus II 11以前的版本不能输入中文,同时也不可以显示中文;d) Quartus II 11.0目前最新版本,可以显示中文字符,同时又能也能输入中文。
注意:由于ModelSim功能强大,Quartus II 11.0以后的软件很多功能都被剔除了,所以不见得版本越高越好,建议大家使用9.0或者9.5的版本。
Quartus II 软件可以到官网下载/?edition=web或者:/category-954833971.htm?spm=2013.1.w4010-542 0703609.9.I9BngM&search=y&parentCatId=914376443&parentCatName=%B5%E7%D7%D3%B5%E 7%C6%F8&catName=FPGA%2FVerilog#bd。
这里还有《verilog视频教程和源代码》和吴厚航(特权同学)的《深入浅出玩转FPGA 》等其他Verilog和FPGA学习视频。
Quartus II输入和显示中文注释的方法方法一:下载Quartus II 11.0以后的版本,11.0以后的版本都支持中英文显示和输入。
但Quartus II 11.0以后的版本功能被阉割了很多,不建议使用。
方法二:Quartus II 9.1以前的版本可以显示中文但不能输入中文注释,因此可以用复制粘贴的方法显示中文注释:即在Txt文档或者Word文档编辑好再复制再Quartus II的编辑窗口。
方法三:强烈推荐:(1)即在Quartus II的窗口调用其他编辑器,如调用Txt文本编辑、Notepad++或者UltraEdit 等编辑器。
EX1`timescale 1ns / 1psmodule clkdiv(clk,rst_n,clk_div);input clk; //50MHzinput rst_n; //低电平复位信号output clk_div; //分频信号,连接到蜂鸣器//---------------------------------------------------reg[19:0] cnt; //分频计数器always @ (posedge clk or negedge rst_n) //异步复位if(!rst_n) cnt <= 20'd0;else cnt <= cnt+1'b1; //寄存器cnt 20ms循环计数//----------------------------------------------------reg clk_div_r; //clk_div信号值寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) clk_div_r <= 1'b0;else if(cnt == 20'hfffff) clk_div_r <= ~clk_div_r; //每20ms让clk_div_r值翻转一次assign clk_div = clk_div_r;endmoduleEX2`timescale 1ns / 1ps//说明:当三个独立按键的某一个被按下后,相应的LED被点亮;// 再次按下后,LED熄灭,按键控制LED亮灭module sw_debounce(clk,rst_n,sw1_n,sw2_n,sw3_n,led_d1,led_d2,led_d3);input clk; //主时钟信号,50MHzinput rst_n; //复位信号,低有效input sw1_n,sw2_n,sw3_n; //三个独立按键,低表示按下output led_d1,led_d2,led_d3; //发光二极管,分别由按键控制//---------------------------------------------------------------------------reg[2:0] key_rst;always @(posedge clk or negedge rst_n)if (!rst_n) key_rst <= 3'b111;else key_rst <= {sw3_n,sw2_n,sw1_n};reg[2:0] key_rst_r; //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中always @ ( posedge clk or negedge rst_n )if (!rst_n) key_rst_r <= 3'b111;else key_rst_r <= key_rst;//当寄存器key_rst由1变为0时,led_an的值变为高,维持一个时钟周期wire[2:0] key_an = key_rst_r & ( ~key_rst);//---------------------------------------------------------------------------reg[19:0] cnt; //计数寄存器always @ (posedge clk or negedge rst_n)if (!rst_n) cnt <= 20'd0; //异步复位else if(key_an) cnt <=20'd0;else cnt <= cnt + 1'b1;reg[2:0] low_sw;always @(posedge clk or negedge rst_n)if (!rst_n) low_sw <= 3'b111;else if (cnt == 20'hfffff) //满20ms,将按键值锁存到寄存器low_sw中cnt == 20'hfffff low_sw <= {sw3_n,sw2_n,sw1_n};//---------------------------------------------------------------------------reg [2:0] low_sw_r; //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中always @ ( posedge clk or negedge rst_n )if (!rst_n) low_sw_r <= 3'b111;else low_sw_r <= low_sw;//当寄存器low_sw由1变为0时,led_ctrl的值变为高,维持一个时钟周期wire[2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]);reg d1;reg d2;reg d3;always @ (posedge clk or negedge rst_n)if (!rst_n) begind1 <= 1'b0;d2 <= 1'b0;d3 <= 1'b0;endelse begin //某个按键值变化时,LED将做亮灭翻转if ( led_ctrl[0] ) d1 <= ~d1;if ( led_ctrl[1] ) d2 <= ~d2;if ( led_ctrl[2] ) d3 <= ~d3;endassign led_d3 = d1 ? 1'b1 : 1'b0; //LED翻转输出assign led_d2 = d2 ? 1'b1 : 1'b0;assign led_d1 = d3 ? 1'b1 : 1'b0;endmoduleEX3`timescale 1ns / 1psmodule johnson(clk,rst_n,key1,key2,key3,led0,led1,led2,led3);input clk; //主时钟,50MHzinput rst_n; //低电平复位input key1,key2,key3; // 按键接口output led0,led1,led2,led3; // LED等接口//------------------------------------reg[23:0] delay; //延时计数器always @ (posedge clk or negedge rst_n)if(!rst_n) delay <= 0;else delay <= delay+1; //不断计数,周期为320msreg[2:0] key_value; //键值寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) key_value <= 3'b111;else if(delay == 24'hffffff) key_value <= {key3,key2,key1}; //delay 320ms,锁定键值//-------------------------------------reg[2:0] key_value_r;always @ (posedge clk or negedge rst_n)if(!rst_n) key_value_r <= 3'b111;else key_value_r <= key_value;wire[2:0] key_change; //判定前后20ms的键值是否发生了改变,若是,则key_change置高assign key_change = key_value_r & (~key_value); //check key_value negedge per clk//------------------------------------reg stop_start,left_right; //流水灯控制位always @ (posedge clk or negedge rst_n)if(!rst_n) beginstop_start <= 1;left_right <= 1;endelseif(key_change[2]) stop_start <= ~stop_start; //开始结束控制位else if(key_change[1]) left_right <= 1; //流水灯方向控制else if(key_change[0]) left_right <= 0; //流水灯方向控制//-------------------------------------reg[3:0] led_value_r; // LED值寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) led_value_r <= 4'b1110;else if(delay == 24'h3fffff && stop_start) //流水灯控制case (left_right) //方向控制1: led_value_r <= {led_value_r[2:0],led_value_r[3]}; //右移0: led_value_r <= {led_value_r[0],led_value_r[3:1]}; //左移default: ;endcaseassign {led3,led2,led1,led0} = ~led_value_r;endmoduleEX4`timescale 1ns / 1psmodule led_seg7(clk,rst_n,sm_cs1_n,sm_cs2_n,sm_db);input clk; // 50MHzinput rst_n; // 复位信号,低有效output sm_cs1_n,sm_cs2_n; //数码管片选信号,低有效output[6:0] sm_db; //7段数码管(不包括小数点)reg[24:0] cnt; //计数器,最大可以计数到2的25次方*20ns=640msalways @ (posedge clk or negedge rst_n)if(!rst_n) cnt <= 25'd0;else cnt <= cnt+1'b1; //循环计数reg[3:0] num; //显示数值always @ (posedge clk or negedge rst_n)if(!rst_n) num <= 4'd0;else if(cnt == 24'hffffff) num <= num+1'b1; //每640ms增一//-------------------------------------------------------------------------------/* 共阴极:不带小数点;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*/ parameter seg0 = 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段数码管(不包括小数点)always @ (num)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;assign sm_cs1_n = 1'b0; //数码管1常开assign sm_cs2_n = 1'b0; //数码管2常开endmoduleEX5`timescale 1ns / 1psmodule mux16(clk,rst_n,start,ain,bin,yout,done);input clk; //芯片的时钟信号。