分频的verilog语言实现

分频的verilog语言实现
分频的verilog语言实现

分频的Verilog实现

1.分频:在实际应用中,自己设计的开发板上不会去装多个晶振来产生不

同频率的时钟信号,这就要我们在已有的基础上自己来创造设计电路

中所需要的时钟信号来,有时候所需要的频率并不是在已有的频率上

直接进行简单的整数分频就可以得到的,有时需要进行小数的分频。

2.在分频的过程中,偶数分频并不困难,若要进行2N次分频的话,只需

要计数到N的时候,波形进行翻转就行了,或者在最后一级加一个2

分频也可以实现。

下面是我写的一个偶数分频的代码:

module div2n(rst,clk,cnt,clk_2n);//偶数次分频

input rst,clk;

output clk_2n,cnt;

reg [3:0] cnt;//刚开始没有定义计数的位宽仿真的时候老是出现输出为0的现象,看似很简单的程序搞的有些纠结啊

reg clk_2n;

always @(posedge clk )

begin

if(rst) //若复位信号为高电平则计数清零和输出清零

begin

cnt<=0;

clk_2n<=0;

end

else

if(cnt==3)//进行8分频,这里的cnt取不同的值进行其他的分频,若计数到达4时从0开始的输出电平翻转

begin

clk_2n<=~clk_2n;

cnt<=0;

end

else cnt<=cnt+1;

end

endmodule

功能仿真波形以及后仿真波形如下:

从后仿真中可以明显的看出输出时钟信号和输入的标准信号有延迟时间,在计数寄存器中出现了相邻两个数之间的竞争,但是没有出现在时钟的上升沿,不会引起最后实现的错误!

奇数分频:若奇数分频中不考虑占空比的话,分频代码可以按照偶数分频的思路来写,但是大多数情况下需要考虑的是使占空比设计为50%。若要进行奇数次的分频而且要求占空比为50%可以采用:用两个计数器,一个由输入时钟下降沿触发,一个由输入时钟的上升沿触发,最后将两个计数器的输出进行相或,就可得到。

程序代码:

module div7(rst,clk,cout1,cout2,cout);

input clk,rst;

output cout1,cout2,cout;

reg [2:0] m,n;//定义两个中间的计数变量

wire cout;

reg cout1,cout2;

assign cout=cout1|cout2;//将上升沿和下降沿的输出相或得到占空比为50%的波形

always @(posedge clk)//上升沿触发

begin

if(rst) begin cout1<=0;m<=0;end//当rst为1时复位

else if(!rst)

begin if(m==6) begin m<=0;end//计数到达7时计数复位

else m<=m+1;//其他情况计数器正常计数

if(m==2) cout1=~cout1;//计数到达3时翻转

else if(m==5) cout1=~cout1;//计数器达到6时再翻转

end

end

always @(negedge clk)//下降沿触发,情况同上

begin

if(rst) begin cout2<=0;n<=0;end

else if(!rst)

begin if(n==6) begin n<=0;end

else n<=n+1;

if(n==2) cout2=~cout2;

else if(n==5) cout2=~cout2;

end

end

endmodule

最后仿真波形:

时序仿真波形为:

半整数分频:半整数分频N.5的分频。设计的思想是:比如说要实现2.5分频可以先设计一个模3计数器,再设计一个脉冲扣除电路,加在模3计数器之后,每来3个脉冲就扣除半个脉冲,即可实现分频系数为2.5的半整数分频,采用类似的方法,可以实现任意半整数分配器。脉冲扣除是输入频率与2分频输出异或的结果。

大致的思路可用下图来分析:

5.5分频代码为

module xfp(clkin,clr,clkout);

input clkin,clr;

output clkout;

reg clkout,clk1;

wire clk2;

integer count;

xor xor1(clk2,clkin,clk1);//将输出2分频时钟与clk2/6分频时钟相异或得到5.5分频

always @(posedge clkout or negedge clr)//输出时钟2分频

begin if(~clr)

begin clk1<=1'b0; end

else clk1<=~clk1;

end

always @(posedge clk2 or negedge clr)//将时钟clk2 6分频

begin if(~clr)

begin count<=0;clkout<=1'b0; end

else if(count==5)//改变count的值可实现不同模的分频

begin count<=0;clkout<=1'b1; e nd

else begin count<=count+1;clkout<=1'b0;end

end

endmodule

当然仿真波形比较的简单,只给出功能仿真波形,从波形图中很容易的可以看出是5.5分频,若要改成其他的N.5分频只需将代码中count的赋值就可以了。

小数分频:在实际应用中,还会遇到小数分频。总结实现小数分频可以采用两种方法,方法一是:用数字锁相环实现,先利用锁相环电路将输入时钟倍频,然后再利用分频器对新产生的高频信号进行分频得到需要的时钟频率。比如要实现5.7分频,可以先将输入的时钟10倍频,然后再将倍频后的时钟57分频,这样就可以得到精确的5.7的小数分频。方法二是先设计两个不同分频比的整数分频器,然后通过控制两种分频比出现不同次数来获得所需要的小数分频值来实现小数分频。分频比可以表示为N=M/P,其中N表示分频比,M表示分频器输入脉冲数,P表示分频器输出脉冲数。当N为小数分频比时,又可以表示为N=K+10-n X,式中K,n和X都为正整数,n表示为小数的位数。由以上两式可得M=( K+10-n X)P,令P=10n,有M=10n k+X,即在进行10n K分频时多输入X个脉冲。下面给出8.1分频电路的代码

module rxs(clk_in,rst,clk_out);//8.1小数分频(8×9+9×1)/(9+1)input clk_in,rst;

output clk_out;

reg clk_out;

reg [3:0] cnt1,cnt2;

always @(posedge clk_in or posedge rst)

begin if(rst) begin cnt1<=0;cnt2<=0;clk_out<=0;end//复位清零

else if(cnt1<9) //9次8分频

begin if(cnt2<7) begin cnt2<=cnt2+1;clk_out<=0;end

else begin cnt2<=0;cnt1<=cnt1+1;clk_out<=1;end

end

else begin //1次9分频

if(cnt2<8) begin cnt2<=cnt2+1;clk_out<=0;end

else begin cnt2<=0;cnt1<=0;clk_out<=1;end

end

end

仿真波形和上面的分频波形差不多,到此为止所有的分频电路都可以实现了,上面的代码只给出了简单的几个分频,如果要进行其他的分频的话改变代码中的计数变量的值即可。

Verilog各种倍分频器设计

module odd_division(clk,rst,count,clk_odd); /*count没必要放在端口中,这里只是为了仿真时观察*/ input clk,rst; output clk_odd; output[3:0] count; reg clk_odd; reg[3:0] count; parameter N = 6; /*6分频* / always @ (posedge clk) if(! rst) begin count <= 1'b0; clk_odd <= 1'b0; end else if ( count < N/2-1) begin count <= count + 1'b1; end else begin count <= 1'b0; clk_odd <= ~clk_odd; end endmodule 奇数倍分频:归类为一般的方法为:对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发进行模N计数,计数从零开始,到N-1)/2进行输出时钟翻转,然后经过(N+1)/2再次进行翻转得到一个占空比非50%奇数n分频时钟。再者同时进行下降沿触发的模N计数,到和上升沿过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数n分频时钟。两个占空比非50%的n分频时钟相或运算,得到占空比为50%的奇数n分频时钟。 module even_division(clk,rst,count1,count2,clk_even); /*count1,count2没必要放在端口中,这

里只是为了仿真时观察*/ input clk,rst; output[3:0] count1,count2; output clk_even; reg[3:0] count1,count2; reg clkA,clkB; wire clk_even,clk_re; parameter N = 5; /*5分频*/ assign clk_re = ~clk; assign clk_even = clkA | clkB; always @(posedge clk) if(! rst) begin count1 <= 1'b0; clkA <= 1'b0; end else if(count1 < (N - 1)) begin count1 <= count1 + 1'b1; /*这里是非阻塞赋值是先执行了下面的IF判断,最后才赋的值。最初看这程序时没注意,想了好半天*/ if(count1 == (N - 1)/2) begin clkA <= ~clkA; end end else begin clkA <= ~clkA;

Verilog编码风格

Verilog编码风格 嵌入式开发2010-05-03 15:28:13 阅读14 评论0 字号:大中小订阅 这是以前公司的对fpga代码编写的要求 良好代码编写风格的通则概括如下: (1)对所有的信号名、变量名和端口名都用小写,这样做是为了和业界的习惯保持一致;对常量名和用户定义的类型用大写; (2)使用有意义的信号名、端口名、函数名和参数名; (3)信号名长度不要太长; (4)对于时钟信号使用clk 作为信号名,如果设计中存在多个时钟,使用clk 作为时钟信号的前缀; (5)对来自同一驱动源的信号在不同的子模块中采用相同的名字,这要求在芯片总体设计时就定义好顶层子模块间连线的名字,端口和连接端口的信号尽可能采用相同的名字; (6)对于低电平有效的信号,应该以一个下划线跟一个小写字母b 或n 表示。注意在同一个设计中要使用同一个小写字母表示低电平有效; (7)对于复位信号使用rst 作为信号名,如果复位信号是低电平有效,建议使用rst_n; (8)当描述多比特总线时,使用一致的定义顺序,对于verilog 建议采用bus_signal[x:0]的表示; (9)尽量遵循业界已经习惯的一些约定。如*_r 表示寄存器输出,*_a 表示异步信号,*_pn 表示多周期路径第n 个周期使用的信号,*_nxt 表示锁存前的信号,*_z 表示三态信号等; (10)在源文件、批处理文件的开始应该包含一个文件头、文件头一般包含的内容如下例所示:文件名,作者,模块的实现功能概述和关键特性描述,文件创建和修改的记录,包括修改时间,修改的内容等; (11)使用适当的注释来解释所有的always 进程、函数、端口定义、信号含义、变量含义或信号组、变量组的意义等。注释应该放在它所注释的代码附近,要求简明扼要,只要足够说明设计意图即可,避免过于复杂; (12)每一行语句独立成行。尽管VHDL 和Verilog 都允许一行可以写多个语句,当时每个语句独立成行可以增加可读性和可维护性。同时保持每行小于或等于72 个字符,这样做都是为了提高代码得可读性; (13)建议采用缩进提高续行和嵌套语句得可读性。缩进一般采用两个空格,如西安交通大学SOC 设计中心 2 如果空格太多则在深层嵌套时限制行长。同时缩进避免使用TAB 键,这样可以避免不同机器TAB 键得设置不同限制代码得可移植能力; (14)在RTL 源码的设计中任何元素包括端口、信号、变量、函数、任务、模块等的命名都不能取Verilog 和VHDL 语言的关键字; (15)在进行模块的端口申明时,每行只申明一个端口,并建议采用以下顺序:

用Verilog语言实现任意整数分频器

用Verilog语言实现任意整数分频器 分频器是FPGA设计中使用频率非常高的基本设计之一,尽管在目前大部分设计中,广泛使用芯片厂家集成的锁相环资源,如赛灵思(Xilinx)的DLL.来进行时钟的分频,倍频以及相移。但是对于时钟要求不高的基本设计,通过语言进行时钟的分频相移仍然非常流行,首先这种方法可以节省芯片内部的锁相环资源,再者,消耗不多的逻辑单元就可以达到对时钟操作的目的。另一方面,通过语言设计进行时钟分频,可以看出设计者对设计语言的理解程度。因此很多招聘单位在招聘时往往要求应聘者写一个分频器(比如奇数分频)以考核应聘人员的设计水平和理解程度。下面讲讲对各种分频系数进行分频的方法:第一,偶数倍分频:偶数倍分频应该是大家都比较熟悉的分频,通过计数器计数是完全可以实现的。如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。电路上只需一个D触发器和一个非门即可实现,Q(n+1)=D,D=~Q(n),clk_out=Q(n+1) . 第二,奇数倍分频:奇数倍分频常常在论坛上有人问起,实际上,奇数倍分频有两种实现方法: 占空比为非50%的三分频时钟,完全可以通过计数器来实现,如进行三分频,通过待分频时钟上升沿触发计数器进行模三计数,当计数器计数到邻近值进行两次翻转,比如可以在计数器计数到1时,输出时钟进行翻转,计数到2时再次进行翻转。即是在计数值在邻近的1和2进行了两次翻转。这样实现的三分频占空比为1/3或者2/3。 module three(clk_in,rst,clk_out); // 三倍频 inputclk_in,rst; output clk_out; reg clk_out; reg [1:0] count; always @(negedgerst or posedgeclk_in) begin if(rst==0) begin count<=0; clk_out<=0; end else begin count<=count+1; if(count==1) clk_out<=~clk_out; else if(count==2) begin clk_out=~clk_out; count<=0; end end end endmodule 仿真图 另一种实现: module div3(CLKIN,CLKOUT,RESETn); //依然是三倍频 inputCLKIN,RESETn;

VerilogHDL经典程序非常适合新手

一、2线-4线译码器 module counter4(q1,q0,ncr,cp); input cp,ncr; output q1,q0; reg q1,q0; always@(posedge cp or negedge ncr) begin if(~ncr){q1,q0}<=2'b00; else{q1,q0}<={q1,q0}+1'b1; end endmodule 二、4选1数据选择器 module selector4_1(i0,i1,i2,i3,a1,a0,y); input i0,i1,i2,i3,a1,a0; output y; reg y; always@(a1or a0) begin case({a1,a0}) 2'b00:y=i0; 2'b01:y=i1; 2'b10:y=i2; 2'b11:y=i3; default:y=0; 一、2线-4线译码器 module counter4(q1,q0,ncr,cp); input cp,ncr; output q1,q0; reg q1,q0; always@(posedge cp or negedge ncr) begin if(~ncr){q1,q0}<=2'b00; else{q1,q0}<={q1,q0}+1'b1; end endmodule 二、4选1数据选择器 module selector4_1(i0,i1,i2,i3,a1,a0,y); input i0,i1,i2,i3,a1,a0; output y; reg y; always@(a1or a0) begin case({a1,a0}) 2'b00:y=i0;

实验六--Verilog设计分频器计数器电路答案

实验六 Verilog设计分频器/计数器电路 一、实验目的 1、进一步掌握最基本时序电路的实现方法; 2、学习分频器/计数器时序电路程序的编写方法; 3、进一步学习同步和异步时序电路程序的编写方法。 二、实验内容 1、用Verilog设计一个10分频的分频器,要求输入为clock(上升沿有效),reset(低电平复位),输出clockout为4个clock周期的低电平,4个clock周期的高电平),文件命名为fenpinqi10.v。 2、用Verilog设计一异步清零的十进制加法计数器,要求输入为时钟端CLK(上升沿)和异步清除端CLR(高电平复位),输出为进位端C和4位计数输出端Q,文件命名为couter10.v。 3、用Verilog设计8位同步二进制加减法计数器,输入为时钟端CLK(上升沿有效)和异步清除端CLR(低电平有效),加减控制端UPDOWN,当UPDOWN为1时执行加法计数,为0时执行减法计数;输出为进位端C和8位计数输出端Q,文件命名为couter8.v。 4、用VERILOG设计一可变模数计数器,设计要求:令输入信号M1和M0控制计数模,当M1M0=00时为模18加法计数器;M1M0=01时为模4加法计数器;当M1M0=10时为模12加法计数器;M1M0=11时为模6加法计数器,输入clk上升沿有效,文件命名为mcout5.v。 5、VerilogHDL设计有时钟时能的两位十进制计数器,有时钟使能的两位十进制计数器的元件符号如图所示,CLK是时钟输入端,上升沿有效;ENA是时钟使能控制输入端,高电平有效,当ENA=1时,时钟CLK才能输入;CLR是复位输入端,高电平有效,异步清零;Q[3..0]是计数器低4位状态输出端,Q[7..0]是高4位状态输出端;COUT是进位输出端。 三、实验步骤 实验一:分频器 1、建立工程

Verilog语言基础知识

Verilog HDL语言基础知识 先来看两个Verilog HDL程序。 例一个8位全加器的Verilog HDL源代码 module adder8(cout,sum,ina,inb,cin); output[7:0] sum; output cout; input[7:0] ina,inb; input cin; @ assign {cout,sum}=ina+inb+cin; 模块的端口声明了模块的输人和输出口。其格式如下: module 模块名(口1,口2,口3,口4,……); 2.模块内容 模块内容包括I/O说明,信号类型声明和功能定义。 (1) I/O说明的格式如下: ; 输人口: input端口名1,端口名2,……端口名N; 输出口: output端口名l,端口名2,……端口名N; I/O说明也可以写在端口声明语句里。其格式如下: module module_name(input portl,input port2,…output portl,output port2,…); (2)信号类型声明: 它是说明逻辑描述中所用信号的数据类型及函数声明。如 ( reg[7:0] out; 数字 (1)整数

在Verilog HDL中,整数型常量(即整常数)有以下4种进制表示形式: ◇二进制整数(b或B); ◇十进制整数(d或D); ◇十六进制整数(h或H); ◇八进制整数(o或O)。 ) 完整的数字表达式为: <位宽>'<进制> <数字>, 位宽为对应二迸制数的宽度,如: 8'b nets型变量wire nets型变量指输出始终根据输入的变化而更新其值的变量,它一般指的是硬件电路中的各种物理连接。Verilog HDL中提供了多种nets型变量,具体见表。 这里着重介绍wire型变量。wire是一种常用的nets型变量,wire型数据常用来表示assign语句赋值的组合逻辑信号。Verilog HDL模块中的输入/输出信号类型缺省时自动定义为wire型。Wire型信号可以用作任何方程式的输入,也可以用作assign语句和实例元件的输出,其取值为0,1,x,z。 wire型变量格式如下: & ⑴.定义宽度为1位的变量: wire 数据名1,数据名2,……数据名n; 例如:wire a,b; register型变量reg register型变量对应的是具有状态保持作用的电路元件,如触发器、寄存器等。register

verilogHDL分频器(奇数分频和偶数分频)

module clk_div( //-----------input----------- iCLK, div, //-----------output---------- oCLK ); //-----------input----------- parameter WIDE=14; input iCLK; input[WIDE-1:0]div; //-----------output----------- output oCLK; wire oCLK_odd; wire oCLK_even; assign oCLK=div[0]?oCLK_odd:oCLK_even; div_odd DUTo (.iCLK(iCLK),.oCLK(oCLK_odd),.div(div)); div_even DUTe (.iCLK(iCLK),.oCLK(oCLK_even),.div(div)); endmodule // odd module div_odd( //--------input-------- iCLK, div, //--------output-------- oCLK ); //--------input-------- parameter WIDE=14; input iCLK; input[WIDE-1:0]div; //--------output-------- output oCLK; reg outCLK;

/* =========================== solve 1 =========================== reg cout; reg[WIDE-1:0] cnt; initial cnt=0; wire inCLK; reg cc; initial cc=0; always @(posedge cout) cc<=~cc; assign inCLK = iCLK^cc; always @(posedge inCLK) begin if(cnt<(div[WIDE-1:1])) begin cnt<=cnt+1; cout<=1'b0; end else begin cnt<=0; cout<=1'b1; end end always @(negedge iCLK) outCLK <= cout; assign oCLK=cc; */ //======================== //solve 2 //======================== reg[WIDE-1:0] cnt_a; initial cnt_a=0; reg[WIDE-1:0] cnt_b; initial cnt_b=0; reg cout_a;

verilog语言的综合与不可综合

Verilog的综合与不可综合 综合说明编的代码可以对应出具体的电路,不可综合说明没有对应的电路结构。不可综合的代码编译通过,只能看到输出,不能实现电路,就是不能用来制作具体的芯片。 一、基本 Verilog中的变量有线网类型和寄存器类型。线网型变量综合成wire,而寄存器可能综合成WIRE,锁存器和触发器。 二:verilog语句结构到门级的映射 1、连续性赋值:assign 连续性赋值语句逻辑结构上就是将等式右边的驱动左边的结点。因些连续性赋值的目标结点总是综合成由组合逻辑驱动的结点。Assign语句中的延时综合时都将忽视。 2、过程性赋值: 过程性赋值只出现在always语句中。 阻塞赋值和非阻塞赋值就该赋值本身是没有区别的,只是对后面的语句有不同的影响。 建议设计组合逻辑电路时用阻塞赋值,设计时序电路时用非阻塞赋值。 过程性赋值的赋值对象有可能综合成wire,latch,和flip-flop,取决于具体状况。如,时钟控制下的非阻塞赋值综合成flip-flop。 过程性赋值语句中的任何延时在综合时都将忽略。 建议同一个变量单一地使用阻塞或者非阻塞赋值。 3、逻辑操作符: 逻辑操作符对应于硬件中已有的逻辑门 4、算术操作符: Verilog中将reg视为无符号数,而integer视为有符号数。因此,进行有符号操作时使用integer,使用无符号操作时使用reg。 5、进位: 通常会将进行运算操作的结果比原操作数扩展一位,用来存放进位或者借位。如: Wire [3:0] A,B; Wire [4:0] C; Assign C=A+B; C的最高位用来存放进位。 6、关系运算符: 关系运算符:<,>,<=,>= 和算术操作符一样,可以进行有符号和无符号运算,取决于数据类型是reg,net还是integer。

Verilog的135个经典设计实例

【例3.1】4位全加器 module adder4(cout,sum,ina,inb,cin); output[3:0] sum; output cout; input[3:0] ina,inb; input cin; assign {cout,sum}=ina+inb+cin; endmodule 【例3.2】4位计数器 module count4(out,reset,clk); output[3:0] out; input reset,clk; reg[3:0] out; always @(posedge clk) begin if (reset) out<=0; //同步复位 else out<=out+1; //计数 end endmodule 【例3.3】4位全加器的仿真程序 `timescale 1ns/1ns `include "adder4.v" module adder_tp; //测试模块的名字 reg[3:0] a,b; //测试输入信号定义为reg型 reg cin; wire[3:0] sum; //测试输出信号定义为wire型 wire cout; integer i,j; adder4 adder(sum,cout,a,b,cin); //调用测试对象 always #5 cin=~cin; //设定cin的取值 initial begin a=0;b=0;cin=0; for(i=1;i<16;i=i+1) #10 a=i; //设定a的取值 end - 1 -

initial begin for(j=1;j<16;j=j+1) #10 b=j; //设定b的取值 end initial//定义结果显示格式 begin $monitor($time,,,"%d + %d + %b={%b,%d}",a,b,cin,cout,sum); #160 $finish; end endmodule 【例3.4】4位计数器的仿真程序 `timescale 1ns/1ns `include "count4.v" module coun4_tp; reg clk,reset; //测试输入信号定义为reg型 wire[3:0] out; //测试输出信号定义为wire型 parameter DELY=100; count4 mycount(out,reset,clk); //调用测试对象 always #(DELY/2) clk = ~clk; //产生时钟波形 initial begin//激励信号定义 clk =0; reset=0; #DELY reset=1; #DELY reset=0; #(DELY*20) $finish; end //定义结果显示格式 initial $monitor($time,,,"clk=%d reset=%d out=%d", clk, reset,out); endmodule 【例3.5】“与-或-非”门电路 module AOI(A,B,C,D,F); //模块名为AOI(端口列表A,B,C,D,F) input A,B,C,D; //模块的输入端口为A,B,C,D output F; //模块的输出端口为F - 2 -

分频器的verilog hdl语言

分频器的verilog HDL描述(转) 分频器,在许多涉及时序的电路设计中都会用到,在这里,我转载某位高人的文章,关于分频器的设计 偶数倍分频:偶数倍分频应该是大家都比较熟悉的分频,通过计数器计数是完全可以实现的。如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。 module odd_division(clk,rst,count,clk_odd); input clk,rst; output clk_odd; output[3:0] count; reg clk_odd; reg[3:0] count; parameter N = 6; always @ (posedge clk) if(! rst) begin count <= 1'b0; clk_odd <= 1'b0; end else if ( count < N/2-1) begin count <= count + 1'b1; end else begin

clk_odd <= ~clk_odd; end endmodule 奇数倍分频:归类为一般的方法为:对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发进行模N计数,计数从零开始,到(N-1)/2进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%奇数n分频时钟。再者同时进行下降沿触发的模N 计数,到和上升沿过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数n分频时钟。两个占空比非50%的n分频时钟相或运算,得到占空比为50%的奇数n分频时钟。 module even_division(clk,rst,count1,count2,clk_even); input clk,rst; output[3:0] count1,count2; output clk_even; reg[3:0] count1,count2; reg clkA,clkB; wire clk_even; parameter N = 5; assign clk_re = ~clk; assign clk_even = clkA | clkB; always @(posedge clk) if(! rst) begin count1 <= 1'b0; clkA <= 1'b0; end else

任意分频Verilog实现

1. 偶数倍(2N)分频 使用一模N计数器模块即可实现,即每当模N计数器上升沿从0开始计数至N-1时,输出时钟进行翻转, 同时给计数器一复位信号使之从0开始重新计数,以此循环即可。偶数倍分频原理示意图见图1。 2. 奇数倍(2N+1)分频 (1)占空比为X/(2N+1)或(2N+1-X)/(2N+1)分频,用模(2N+1)计数器模块可以实现。取0至2N-1之间一数值X(0,当计数器时钟上升沿从0开始计数到X值时输出时钟翻转一次,在计数器继续计数达到2N 时,输出时钟再次翻转并对计数器置一复位信号,使之从0开始重新计数,即可实现。 (2)占空比为50%的分频,设计思想如下:基于(1)中占空比为非50%的输出时钟在输入时钟的上升沿 触发翻转;若在同一个输入时钟周期内,此计数器的两次输出时钟翻转分别在与(1)中对应的下降沿触发翻转,输出的时钟与(1)中输出的时钟进行逻辑或,即可得到占空比为50%的奇数倍分频时钟。当然其 输出端再与偶数倍分频器串接则可以实现偶数倍分频。奇数倍分频原理示意图见图2。(这也是许多公司常出的面试题,^_^,是不是很简单?) 3. N-0.5倍分频 采用模N计数器可以实现。具体如下:计数器从0开始上升沿计数,计数达到N-1上升沿时,输出时钟需翻转,由于分频值为N-0.5,所以在时钟翻转后经历0.5个周期时,计数器输出时钟必须进行再次翻转,即当 CLK为下降沿时计数器的输入端应为上升沿脉冲,使计数器计数达到N而复位为0重新开始计数同时输出时钟翻转。这个过程所要做的就是对CLK进行适当的变换,使之送给计数器的触发时钟每经历N-0.5个周期就翻转一次。N-0.5倍:取N=3,分频原理示意图见图3。 对于任意的N+A/B倍分频(N、A、B∈Z,A≦B) 分别设计一个分频值为N和分频值N+1的整数分频器,采用脉冲计数来控制单位时间内两个分频器出现 的次数,从而获得所需要的小数分频值。可以采取如下方法来计算个子出现的频率: 设N出现的频率为a,则N×a+(N+1)×(B-a)=N×B+A 求解a=B-A; 所以N+1出现的频率为 A.例如实现7+2/5分频,取a为3,即7×3+8×2就可以实现。但是由于这种小数分频输出的时钟脉冲抖动很大, 现实中很少使用。 通常实现偶数的分频比较容易,以十分频为例: always @( posedge clk or posedge reset) if(reset) begin k<=0; clk_10<=0; end else if(k==4) begin k<=0;

Verilog语言的特点

一、第一章 1.几个英文缩写: PLA(Programmable Logic Array)可编程逻辑阵列 FPGA(Field Programmable Gate Array)现场可编程逻辑门阵列 CPLD(Complex Programmable Logic Device)复杂可编程逻辑器件 CAD(Computer Aided Design) 计算机辅助设计 CAE(computer aided engineering) EDA(electronic design automation) 电子设计自动化 2.EDA定义:以计算机为工作平台,以EDA软件为开发环境,以PLD器件或者ASIC专用 集成电路为目标器件设计实现电路系统的一种技术。 3.现代EDA技术的特征【简答】 (1)采用硬件描述语言(HDL)进行设计 HDL语言更适合于描述规模大、功能复杂的数字系统,使设计者在比较抽象的层次上对所设计系统的结构和逻辑功能进行描述。 (2)逻辑综合与优化 目前EDA工具最高只能接受行为级和RTL级描述的HDL文件进行逻辑综合 (3)开放性和标准化 普遍采用标准化和开放性的框架结构,可以与其他的EDA工具一起进行设计工作,实现各种工具的优化组合,集成在一个易于管理的统一环境下,实现资源共享提高工作效率,利于大规模设计。 (4)更完备的库(Library) 在电路设计的各个阶段,EDA系统需要不同层次、不同种类的元器件模型库的支持。EDA 工具要具有更强大的设计能力和更高的设计效率,必须配有丰富的库。各种模型库的功能和规模是衡量EDA工具优劣的一个标志 4.基于EDA技术的设计思路(P4~P5) (1)Top-down设计,即自顶向下的设计 将设计分成几个不同的层次:系统级、功能级、门级、开关级, 按照自上而下的顺序,在不同的层次上对系统进行设计和仿真。 首先从系统设计入手,在顶层进行功能框图的划分和机构设计。 在功能级进行仿真纠错,并用HDL对高层次的系统行为进行描 述,然后用综合工具将设计转化为具体门电路网表。 Top-down的设计须经过“设计—验证—修改设计—再验证”的 过程,不断反复,直到结果能够实现所要求的功能,并在速度、 功耗、价格和可靠性方面实现较为合理的平衡。 (2)Bottom-up设计,即自底向上的设计 设计者选择标准集成电路,或者将各种基本单元做成基本单元库,调用这些基本单元,直到设计出满足需要的系统。缺点:效率低、易出错 5.IP核的一些概念(intellectual property) IP核(IP模块):指功能完整,性能指标可靠,已验证的、可重用的电路功能模块。分为硬核、固核、软核。 (1)软核:如ARM。是指在寄存器级或门级对电路功能用HDL描述,表现为用VHDL 等硬件描述语言描述的功能块,但是并不涉及用什么具体电路元件实现这些功能。 (2)硬核:以版图形式实现的设计模块,基于一定的设计工艺。供设计的最终阶段产品: 掩膜。

实验六Verilog设计分频器计数器电路答案

实验六V e r i l o g设计分频器/计数器电路 一、实验目的 1、进一步掌握最基本时序电路的实现方法; 2、学习分频器/计数器时序电路程序的编写方法; 3、进一步学习同步和异步时序电路程序的编写方法。 二、实验内容 1、用Verilog设计一个10分频的分频器,要求输入为clock(上升沿有效),reset(低电平复位),输出clockout为4个clock周期的低电平,4个clock 周期的高电平),文件命名为。 2、用Verilog设计一异步清零的十进制加法计数器,要求输入为时钟端CLK (上升沿)和异步清除端CLR(高电平复位),输出为进位端C和4位计数输出端Q,文件命名为。 3、用Verilog设计8位同步二进制加减法计数器,输入为时钟端CLK(上升沿有效)和异步清除端CLR(低电平有效),加减控制端UPDOWN,当UPDOWN 为1时执行加法计数,为0时执行减法计数;输出为进位端C和8位计数输出端Q,文件命名为。 4、用VERILOG设计一可变模数计数器,设计要求:令输入信号M1和M0控制计数模,当M1M0=00时为模18加法计数器;M1M0=01时为模4加法计数器;当M1M0=10时为模12加法计数器;M1M0=11时为模6加法计数器,输入clk 上升沿有效,文件命名为。 5、VerilogHDL设计有时钟时能的两位十进制计数器,有时钟使能的两位十进制计数器的元件符号如图所示,CLK是时钟输入端,上升沿有效;ENA是

时钟使能控制输入端,高电平有效,当ENA=1时,时钟CLK才能输入;CLR 是复位输入端,高电平有效,异步清零;Q[3..0]是计数器低4位状态输出端,Q[7..0]是高4位状态输出端;COUT是进位输出端。 三、实验步骤 实验一:分频器 1、建立工程 2、创建Verilog HDL文件 3、输入10分频器程序代码并保存 4、进行综合编译 5、新建波形文件 6、导入引脚 7、设置信号源并保存 8、生成网表 9、功能仿真 10、仿真结果分析 由仿真结果可以看出clockout输出5个clock周期的低电平和5个clock 的高电平达到10分频的效果,设计正确。 实验二:十进制加法计数器(异步清零) 1、建立工程 2、创建Verilog HDL文件 3、输入加法计数器代码并保存 4、进行综合编译 5、新建波形文件 6、导入引脚 7、设置信号源并保存 8、生成网表 9、功能仿真 10、仿真结果分析

VHDL语言的主要描述语句

VHDL语言的主要描述语句 按照语句的执行顺序对VHDL语言进行分类,包含两类语句: 并行描述语句该语句的执行与书写顺序无关,总是同时被执行 顺序描述语句从仿真的角度,该语句是顺序执行的 进程语句(PROCESS)是最典型的并行语句,一个构造体内可以有几个进程语句同时存在,而且并发执行。但是进程内部的所有语句都是顺序语句。 一、顺序描述语句 顺序描述语句只能用在进程和子程序中,它和其他高级语言一样,其语句是按照语句的出现的顺序加以执行的。如下分别介绍有关的顺序描述语句. 1.WAIT语句 进程在执行过程中总是处于两种状态:执行或挂起,进程的状态变化受等待语句的控制,当进程执行到等待语句,就被挂起,并等待再次执行进程. 等待语句的格式: *WAIT 无限等待 *WAIT ON 敏感信号变化 *WAIT UNTIL 条件满足 *WAIT FOR 时间到 (1)WAIT ON 格式:WAIT ON 信号[,信号] 例5-1 PROCESS(a,b) BEGIN y<=a AND b;

END PROCESS; 该例中的进程与下例中进程相同: 例5-1 PROCESS BEGIN y<=a AND b; WAIT ON a,b; END PROCESS; 例5-2 PROCESS(a,b) BEGIN y<=a AND b; WAIT ON a,b; END PROCESS; (2)WAIT UNTIL 直到条件满足 格式: WAIT UNTIL 布尔表达式 当进程执行到该语句时,被挂起;若布尔表达式为真时,进程将被启动.例: WAIT UNTIL ((x*10)<100) (3)WAIT FOR等到时间到 格式: WAIT FOR 时间表达式 当进程执行到该语句时,被挂起;等待一定的时间后,进程将被启动.例: WAIT FOR 20 ns; WAIT FOR (a*(b+c);

Verilog分频器设计

Verilog分频器设计 module adder(clk,z); output z; reg q; reg z; always@(posedge clk) begin if(q%9==0) z<=q; else q=q+1; end endmodule module counter9(clk,datein,z); output z; input clk; input datein; reg z; reg[3:0] q; always@(posedge clk) begin q<=q+1; if (q==4'b1001) begin q<=4'b0000; z<=datein; end end endmodule

2008-11-04 19:58 分频器是FPGA设计中使用频率非常高的基本单元之一。尽管目前在大部分设计中还广泛使用集成锁相环(如altera的PLL,Xilinx的DLL)来进行时钟的分频、倍频以及相移设计,但是,对于时钟要求不太严格的设计,通过自主设计进行时钟分频的实现方法仍然非常流行。首先这种方法可以节省锁相环资源,再者,这种方式只消耗不多的逻辑单元就可以达到对时钟操作的目的。偶数倍分频:偶数倍分频应该是大家都比较熟悉的分频,通过计数器计数是完全可以实现的。如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。 module odd_division(clk,rst,count,clk_odd); /*count没必要放在端口中,这里只是为了仿真时观察*/ input clk,rst; output clk_odd; output[3:0] count; reg clk_odd; reg[3:0] count; parameter N = 6; /*6分频* / always @ (posedge clk) if(! rst) begin count <= 1'b0; clk_odd <= 1'b0; end else if ( count < N/2-1) begin count <= count + 1'b1; end else begin count <= 1'b0; clk_odd <= ~clk_odd;

Verilog程序例子

modul e and1(a, b, c); input a; input b; output c; assign c = a & b; endmodul e `timescale 1ns/1ns modul e t; reg a; reg b; wire c; and1 t(a,b,c); initial begin a=0; b=0; #100 a = 1; b = 0; #100 a = 0; b = 1; #100 a = 0; b = 0; #100 a = 1; b = 1; #100 $stop;

end initial $monitor("a = %d, ", a, " b = %d, ", b, "c = %d\n", c); endmodul e modul e add(a, b, in, c, out); input a; input b; input in; output c; output out; assign {out, c} = a + b + in; endmodul e `timescal e 1ns/1ns modul e count_t; reg clk; reg a; reg b; reg in; wire c; wire out; ad d process(a, b, in, c, out);

initial clk = 0; always forever #5 clk = ~clk; initial begin a = 0; b = 0; in = 0; #10 a = 0; b = 0; in = 1; #10 a = 0; b = 1; in = 0; #10 a = 0; b = 1; in = 1; #10 a = 1; b = 0; in = 0; #10 a = 1; b = 0; in = 1; #10 a = 1; b = 1; in = 0; #10 a = 1; b = 1; in = 1; end initial begin #200 $finish; end initial $monitor(" out = %d, c = %d\n", out, c); endmodul e modul e compare (equal, a, b); input a,b; output equal; assign equal= (a==b)?1:0; endmodul e `timescal e 1ns/1ns modul e t; reg a, b; wire equal; initial begin a=0; b=0; #100 a = 1; b = 0;

Verilog语言基础教程

Verilog HDL Verilog HDL是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象 设计层次的数字系统建模。被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统之间。数字系统能够按层次描述,并可在相同描述中显式地进行时序建模。 Verilog HDL 语言具有下述描述能力:设计的行为特性、设计的数据流特性、设计的结构组成以及包含响应监控和设计验证方面的时延和波形产生机制。所有这些都使用同一种建模语言。此外,Verilog HDL语言提供了编程语言接口,通过该接口可以在模拟、验证期间从设计外部访问设计,包括模拟的具体控制和运行。 Verilog HDL语言不仅定义了语法,而且对每个语法结构都定义了清晰的模拟、仿真语义。因此,用这种语言编写的模型能够使用Verilog仿真器进行验证。语言从C编程语言中继承了多种操作符和结构。Verilog HDL提供了扩展的建模能力,其中许多扩展最初很难理解。但是,Verilog HDL语言的核心子集非常易于学习和使用,这对大多数建模应用来说已经足够。当然,完整的硬件描述语言足以对从最复杂的芯片到完整的电子系统进行描述。 =============================== 中文版Verilog HDL简明教程:第1章简介 Verilog HDL是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统之间。数字系统能够按层次描述,并可在相同描述中显式地进行时序建模。 Verilog HDL 语言具有下述描述能力:设计的行为特性、设计的数据流特性、设计的结构组成以及包含响应监控和设计验证方面的时延和波形产生机制。所有这些都使用同一种建模语言。此外,Verilog HDL语言提供了编程语言接口,通过该接口可以在模拟、验证期间从设计外部访问设计,包括模拟的具体控制和运行。 Verilog HDL语言不仅定义了语法,而且对每个语法结构都定义了清晰的模拟、仿真语义。因此,用这种语言编写的模型能够使用Verilog仿真器进行验证。语言从C编程语言中继承了多种操作符和结构。Verilog HDL提供了扩展的建模能力,其中许多扩展最初很难理解。但是,Verilog HDL语言的核心子集非常易于学习和使用,这对大多数建模应用来说已经足够。当然,完整的硬件描述语言足以对从最复杂的芯片到完整的电子系统进行描述。 历史 Verilog HDL语言最初是于1983年由Gateway Design Automation公司为其模

用verilog实现任意倍分频器的方法

用verilog语言写的任意整数的分频器 占空比:对于一串理想的脉冲序列中(如方波),正脉冲的持续时间与脉冲总周期的比值,叫做这个方波的占空比。 分频分为奇分频和偶分频 第一,偶数倍分频:偶数倍分频应该是大家都比较熟悉的分频,通过计数器计数是完全可以实现的。如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。 第二:奇数倍分频:奇数倍分频常常在论坛上有人问起,实际上,奇数倍分频有两种实现方法:首先,完全可以通过计数器来实现,如进行三分频,通过待分频时钟上升沿触发计数器进行模三计数,当计数器计数到邻近值进行两次翻转,比如可以在计数器计数到1时,输出时钟进行翻转,计数到2时再次进行翻转。即是在计数值在邻近的1和2进行了两次翻转。这样实现的三分频占空比为1/3或者2/3。如果要实现占空比为50%的三分频时钟,可以通过待分频时钟下降沿触发计数,和上升沿同样的方法计数进行三分频,然后下降沿产生的三分频时钟和上升沿产生的时钟进行相或运算,即可得到占空比为50%的三分频时钟。这种方法可以实现任意的奇数分频。归类为一般的方法为:对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%奇数n分频时钟。再者同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟时钟翻转,同样经过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数n分频时钟。两个占空比非50%的n分频时钟相或运算,得到占空比为50%的奇数n分频时钟。另外一种方法:对进行奇数倍n分频时钟,首先进行n/2分频(带小数,即等于(n-1)/2+0.5),然后再进行二分频得到。得到占空比为50%的奇数倍分频。 下面讲讲进行小数分频的设计方法: 第三,小数分频:首先讲讲如何进行n+0.5分频,这种分频需要对输入时钟进行操作。基本的设计思想:对于进行n+0.5分频,首先进行模n的计数,在计数到n-1时,输出时钟赋为‘1’,回到计数0时,又赋为0,因此,可以知道,当计数值为n-1时,输出时钟才为1,因此,只要保持计数值n-1为半个输入时钟周期,即实现了n+0.5分频时钟,因此保持n-1为半个时钟周期即是一个难点。从中可以发现,因为计数器是通过时钟上升沿计数,因此可以在计数为n- 1时对计数触发时钟进行翻转,那么时钟的下降沿变成了上升沿。即在计数值为n-1期间的时钟下降沿变成了上升沿,则计数值n-1只保持了半个时钟周期,由于时钟翻转下降沿变成上升沿,因此计数值变为0。因此,每产生一个n+0.5分频时钟的周期,触发时钟都是要翻转一次。设计思路如下:

相关文档
最新文档