文章目录

  • 1、 模10计数器的设计与仿真
  • 2、加入使能信号
  • 3、先递增后递减的计数器设计与仿真
  • 4、二分频(用D触发器实现)
  • 5、三分频
  • 6、任意分频(占空比为50%)
    • 6.1 任意偶数N分频方式
    • 6.2 任意奇数N分频方式
  • 产生iic的scl 250khz时钟频率

计数器的逻辑功能:记录时钟脉冲的个数

1、 模10计数器的设计与仿真

现要求设计模10计数器,0到9循环累加,计数满清0。

 module Count_1(input clk,input rst_n,output reg [3:0] cnt
);always@(posedge clk or negedge rst_n)if(!rst_n)cnt <= 4'd0; else if(cnt == 4'd9)cnt <= 4'd0;else cnt <= cnt + 1'b1;endmodule

综合出的RTL:

testbench仿真:

`timescale 1ns/1ps //时间精度
`define Clock 20 //时间周期
module Count_1_tb;reg clk;reg rst_n;wire [3:0] cnt;Count_1 u1(.clk(clk),.rst_n(rst_n),.cnt(cnt)
);
//产生时钟激励
initial  clk = 0;
always #(`Clock/2) clk= ~clk;//产生复位激励
initial beginrst_n=0; #(`Clock*5);rst_n=1;#500
$stop;
end
endmodule

波形如下:复位拉高,计数器实现从0-9的计数,每当计数到9后即可清零。

2、加入使能信号

设计带使能的模10计数器。当复位拉高且使能信号有效的时候开始0到9循环累加计数,计数满清0.

verilog代码:

 module Count_1(input clk,input rst_n,input en,output reg [3:0] cnt
);always@(posedge clk or negedge rst_n)if(!rst_n)cnt <= 4'd0; else if(en)beginif(cnt == 4'd9)cnt <= 4'd0;else cnt <= cnt + 1'b1;endelsecnt <= cnt;endmodule

生成的RTL图:

tb仿真文件:

`timescale 1ns/1ps //时间精度
`define Clock 20 //时间周期
module Count_1_tb;reg clk;reg rst_n;reg en;wire [3:0] cnt;Count_1 u1(.clk(clk),.rst_n(rst_n),.cnt(cnt),.en(en)
);
//产生时钟激励
initial  clk = 0;
always #(`Clock/2) clk= ~clk;//产生复位激励和输入
initial beginrst_n=0;en = 0;#(`Clock*5);rst_n=1;#(`Clock*2);en = 1;#500$stop;
end
endmodule

波形可看到,复位拉高后并没有直接开始计数,只有当en信号有效的时候,才能开始计数。

3、先递增后递减的计数器设计与仿真

设计一个计数器,先递增,递增到一定数后开始递减,递减到一定数后又递增,循环反复
.
复位拉高且使能信号有效,进行计数。
当递增标志信号有效且未增到9,则计数器+1
当递减标志信号有效且未减到0,则计数器-1
递增信号、递减信号

module Count_1(input         clk                 , input         rst_n               , input         en                  ,output reg    [3:0]cnt               ,output reg    flag_x   //递增递减的标志信号
);always @(posedge clk or negedge rst_n) beginif (!rst_n)cnt <= 0;else if(en)beginif(flag_x==0 && cnt<9) //递增有效且计数小于9cnt <= cnt + 1;else if(flag_x==1 && cnt>0)//递减有效且计数大于0cnt <= cnt - 1;endelse cnt <= 0;
end//生成递增递减的标志信号
always @(posedge clk or negedge rst_n) beginif (!rst_n)flag_x <= 0;else if(flag_x==0 && cnt==9)flag_x <= 1;else if(flag_x==1 && cnt==0)flag_x <= 0;
end
endmodule

tb仿真文件:

`timescale 1ns/1ps //时间精度
`define Clock 20 //时间周期
module Count_1_tb;reg clk;reg rst_n;reg en;wire [3:0] cnt;wire flag_x;Count_1 u1(.clk(clk),.rst_n(rst_n),.cnt(cnt),.en(en),.flag_x(flag_x)
);
//产生时钟激励
initial  clk = 0;
always #(`Clock/2) clk= ~clk;//产生复位激励和输入
initial beginrst_n=0;en = 0;#(`Clock*5);rst_n=1;#(`Clock*2);en = 1;#500$stop;
end
endmodule

波形如下:
当en信号有效且flag_x为低电平,计数器小于9的时候,开始了0-9递增计数;当计数到9且flag_x为高电平,表示开始递减计数,于是从9-0;

4、二分频(用D触发器实现)

Verilog代码:

module Count_1(input         clk   , input         rst_n , output reg    out
);always @(posedge clk or negedge rst_n) if (!rst_n)out <= 0;else out <= ~out;
endmodule

RTL图:

tb测试文件:

`timescale 1ns/1ps //时间精度
`define Clock 20 //时间周期
module Count_1_tb;reg clk;reg rst_n;wire out;Count_1 u1(.clk(clk),.rst_n(rst_n),.out(out)
);//产生时钟激励
initial  clk = 0;
always #(`Clock/2) clk= ~clk;//产生复位激励和输入
initial beginrst_n=0;#(`Clock*5);rst_n=1;#(`Clock*5);#500$stop;
end
endmodule

可看到输出的一个周期中,包含两个clk脉冲,因此实现了二分频。

5、三分频

由div3可看到,其为clk的三分频信号。pos_cnt为clk上升沿计数器,neg_cnt为下降沿计数器。由于是三分频,因此计数三个clk的上升和三个clk的下降沿即可,最后进行逻辑或运算得到div3.

verilog代码:

module Count_1(input rst_n,input clk,output reg [1:0] pos_cnt,  //上升沿计数器output reg [1:0] neg_cnt,  //下降沿计数器output reg neg_cnt_0,  //上升沿脉冲信号output reg pos_cnt_0, //下降沿脉冲信号output div3_o//输出三分频);//上升沿计数且每计数到2清零
always@(posedge clk or negedge rst_n) begin if(!rst_n)pos_cnt<=2'd0;else if(pos_cnt==2'd2) pos_cnt<=2'd0;elsepos_cnt<=pos_cnt+1'b1;
end//下降沿计数且每计数到2清零
always@(negedge clk or negedge rst_n)begin  if(!rst_n) neg_cnt<=2'd0;else if(neg_cnt==2'd2)neg_cnt<=2'd0;elseneg_cnt<=neg_cnt+1'b1;
end//产生两个时钟沿的脉冲信号
always@(posedge clk or negedge rst_n)
beginif(!rst_n) pos_cnt_0<=1'b0;else if (pos_cnt == 2'd1)pos_cnt_0<=1'b1;elsepos_cnt_0<=1'b0;
end     always@(negedge clk or negedge rst_n)
beginif(!rst_n) neg_cnt_0<=1'b0;else if (neg_cnt == 2'd1)neg_cnt_0<=1'b1;elseneg_cnt_0<=1'b0;
end
assign div3_o = pos_cnt_0 | neg_cnt_0; endmodule

tb测试文件:


`timescale 1ns/1ps //时间精度
`define Clock 20 //时间周期module Count_1_tb;reg rst_n;reg clk;wire  [1:0] pos_cnt;  //上升沿计数wire  [1:0] neg_cnt;  //下降沿计数wire pos_cnt_0;wire neg_cnt_0;wire div3_o;Count_1 u1(.clk(clk),.rst_n(rst_n),.pos_cnt(pos_cnt),.neg_cnt(neg_cnt),.neg_cnt_0(neg_cnt_0),.pos_cnt_0(pos_cnt_0),.div3_o(div3_o));initial clk = 0;always #(`Clock/2) clk= ~clk;initial beginrst_n=0 ;#(`Clock*20);rst_n=1;#(`Clock*100);$stop;
end endmodule 

波形仿真:

6、任意分频(占空比为50%)

任意分频通过计数器实现,但需要注意的是任意分频电路分为两种:奇数分频和偶数分频。偶数分频可直接采用计数器实现,而奇数分频还需要利用组合逻辑。
.
建议在设计过程中采用参数化设计,这样就可以随时改变参量以得到不同的分频需要。
.
在对时钟要求不是很严格的FPGA系统中,分频通常都是通过计数器的循环计数来实现的,否则将采用PLL来实现。

6.1 任意偶数N分频方式

方法1、先得到1Mhz的时钟,然后每(N/2-1 )和 N-1进行翻转
.
方法2、设计一个 N/2计数器,计数到(N/2-1)清零,然后每(N/2)-1 进行翻转。

例1:通过1Mhz时钟的方式进行偶数分频。

系统时钟为50Mhz,假如要产生1Mhz的时钟,则需要对系统时钟进行分频处理,50分频为偶数分频,可以采用计数的方式进行实现,50/1=50,则计数到49次的时候清零,否则进行+1计数,然后产生1Mhz的时钟频率

module Count_1(input rst_n,
input clk,
output reg [7:0]cnt,  //上升沿计数
output reg out);always@(posedge clk or negedge rst_n )
beginif(!rst_n)cnt<=1'b0;else if(cnt==8'd49)begincnt<=1'b0;endelsecnt<=cnt+1'b1;
endalways@(posedge clk or negedge rst_n )
beginif(!rst_n)out <= 0;else if(cnt ==8'd24 | cnt ==8'd49  )beginout <= ~out;endelseout <= out;
endendmodule
`timescale 1ns/1ps //时间精度
`define Clock 20 //时间周期module Count_1_tb;reg rst_n;reg clk;wire [7:0] cnt;  //上升沿计数wire out;Count_1 counter(.clk(clk),.rst_n(rst_n),.cnt(cnt),.out(out)
);
initial clk = 0;
always #(`Clock/2) clk= ~clk;initial beginrst_n=0 ;#(`Clock*20);rst_n=1;#(`Clock*150);$stop;
end
endmodule

波形如下 :
此时的计数器cnt为50计数器。我们让其在中间24和49的位置进行翻转,最终得到了周期为1000ns的输出,对应的时钟频率为1Mhz


例2:通过设计N/2计数器的方式进行偶数4分频。

module Count_1(input         clk   , input         rst_n , output reg    out
);
reg [2:0] cnt;always @(posedge clk or negedge rst_n) if (!rst_n)cnt <= 0;else if(cnt == 1)cnt <= 0;elsecnt <= cnt + 1;always @(posedge clk or negedge rst_n) if (!rst_n)out  <= 0;else if(cnt == 1)out  <= ~out;endmodule

tb测试文件:


`timescale 1ns/1ps //时间精度
`define Clock 20module Count_1_tb;reg clk;reg rst_n;wire out;  //上升沿计数Count_1 inst_Count_1 (.clk(clk), .rst_n(rst_n),.out(out));initial clk = 0;
always  #(`Clock/2) clk = ~clk;initial beginrst_n = 0;#20;rst_n = 1;#(`Clock*150);$stop;
end
endmodule

6.2 任意奇数N分频方式

方法:

第一步:设计N计数器(加到N-1清零)
.
第二步:产生上升沿分频信号和下降沿分频信号【都分别在(N-1)/2 和 N-1 处进行翻转 】
.
第三步:对第二步中的两个信号进行或运算。

例子:进行三分频设计:

如下为三分频的原理,设计模3计数器,分别进行时钟上升沿和下降沿的相应检测,输出的信号进行或运算。

verilog代码:

module Count_1(input         clk   , input         rst_n , output        out
);
reg [1:0] cnt;
reg pos_div;
reg neg_div;always @(posedge clk or negedge rst_n) if (!rst_n)cnt <= 0;else if(cnt == 2)cnt <= 0;elsecnt <= cnt + 1;//上升沿分频信号
always @(posedge clk or negedge rst_n) if (!rst_n)pos_div  <= 0;else if(cnt == 1)pos_div  <= ~pos_div;else if(cnt == 2)pos_div  <= ~pos_div;else pos_div  <= pos_div;//下降沿分频信号
always @(negedge clk or negedge rst_n) if (!rst_n)neg_div  <= 0;else if(cnt == 1)neg_div  <= ~neg_div;else if(cnt == 2)neg_div  <= ~neg_div;else neg_div  <= neg_div;
//或运算
assign out = pos_div | neg_div;endmodule

tb测试文件同上。
波形如下:直接看分频出来的out信号的周期是60ns,说明三分频成功。

产生iic的scl 250khz时钟频率

方法:先50分频产生1Mhz时钟,然后4分频产生250Khz

module Count_1(input clk,input rst_n,output i2c_scl,  //iic总线的串行时钟信号250Khzoutput i2c_clk  //1Mhz);reg [5:0] clk_1_cnt;
reg [1:0] clk_1_4_cnt;
reg clk_1; //1Mhz
reg clk_1_4;//250Khz//通过系统时钟50Mhz得到1Mhz时钟
//产生50计数器
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginclk_1_cnt <= 0;endelse if (clk_1_cnt == 6'd49) beginclk_1_cnt <= 0;endelse beginclk_1_cnt <= clk_1_cnt + 1;end
end
//每计数49和计数24的时候进行翻转,即可生成一个1Mhz的时钟
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginclk_1 <= 0;endelse if (clk_1_cnt == 6'd49 | clk_1_cnt == 6'd24) beginclk_1 <= ~ clk_1;endelse beginclk_1 <= clk_1;end
end//对1Mhz时钟进行四分频
//产生4计数器
always @(posedge clk_1 or negedge rst_n) beginif (!rst_n) beginclk_1_4_cnt <= 0;endelse if (clk_1_4_cnt == 2'd3) beginclk_1_4_cnt <= 0;endelse beginclk_1_4_cnt <= clk_1_4_cnt + 1;end
end
//每计数1和计数3的时候进行翻转,即可生成一个250khz的时钟
always @(posedge clk_1 or negedge rst_n) beginif (!rst_n) beginclk_1_4 <= 0;endelse if (clk_1_4_cnt == 2'd3 | clk_1_4_cnt == 2'd1  ) beginclk_1_4 <= ~clk_1_4;endelse beginclk_1_4 <= clk_1_4;end
end
assign i2c_clk = clk_1;
assign i2c_scl = clk_1_4;
endmodule

tb仿真:


`timescale 1ns/1ps //时间精度
`define Clock 20module Count_1_tb;reg clk;reg rst_n;wire i2c_scl;wire i2c_clk;Count_1 inst_Count_1(.clk     (clk),.rst_n   (rst_n),.i2c_scl (i2c_scl),.i2c_clk (i2c_clk));initial clk = 0;
always  #(`Clock/2) clk = ~clk;initial beginrst_n = 0;#20;rst_n = 1;#(`Clock*300);$stop;
end endmodule

直接利用200分频,生成250khz时钟

module Count_1(input clk,input rst_n,output i2c_clk  //250Khz);reg [7:0] clk_1_cnt;reg clk_1; //通过系统时钟50Mhz得到250khz时钟
//产生200计数器
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginclk_1_cnt <= 0;endelse if (clk_1_cnt == 8'd199) beginclk_1_cnt <= 0;endelse beginclk_1_cnt <= clk_1_cnt + 1;end
end
//每计数199和计数99的时候进行翻转,即可生成一个1Mhz的时钟
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginclk_1 <= 0;endelse if (clk_1_cnt == 8'd199 | clk_1_cnt == 8'd99) beginclk_1 <= ~ clk_1;endelse beginclk_1 <= clk_1;end
endassign i2c_clk = clk_1;
endmodule

更多计数器的学习

Verilog基础知识-——计数器设计以及任意分频设计与modelsim仿真相关推荐

  1. Verilog基础知识总结02

    Verilog基础知识总结02 1.简述Verilog如何建模 数字电路有两种基本要素:线(器件管脚之间的物理连线:wire)和器件(模块:module). Verilog建模就是用HDL语言把数字电 ...

  2. Verilog基础知识(数值表示总结,signed,原码,反码,补码)

    以前虽然是用过verilog,但是只使用了其中最常见wire,reg类型数据,并且是无符号的,因为是及处理过程很多数据就是无符号的.但是想进一步拓展无符号数,或者其底层的补码形式存储与运算方式,就需要 ...

  3. 数字电路基础知识——组合逻辑电路之乘法器的设计(一)—— 并行、移位相加、加法树、查找表乘法器

    数字电路基础知识--乘法器的设计(一)-- 并行.移位相加.加法树.查找表 乘法器的设计主要应用在数字信号处理和数字通信,本节主要介绍乘法器的四种实现方法.使用并行乘法器.移位相加乘法器.查找表乘法器 ...

  4. Verilog基础知识3(门控时钟及FPGA时钟使能处理)

    需求说明:Verilog设计 内容       :第一部分  门控时钟                   第二部分  门控时钟和时钟使能的理解(附代码) 来自       :时间的诗 第一部分  门 ...

  5. Verilog基础知识

    I/O端口类型: input             wire型 output           wire/reg型 verilog可综合语句 assign,always,其中initial 语句不 ...

  6. Verilog笔记——数据检测/独热码检测——Quartus与Modelsim仿真

    MATLAB 与 FPGA无线通信.图像处理.数字信号处理系列 1.题目要求 输入32-bit数据,若是2的N次方(如1=20,2=21),输出1,否则输出0,复位时输出高阻态.(实际上,这是对32位 ...

  7. Verilog基础知识(异步FIFO)

    本文主要内容来自Clifford E. Cummings的 Simulation and Synthesis Techniques for Asynchronous FIFO Design 这篇文章的 ...

  8. Verilog 基础知识

    Verilog 的逻辑值 逻辑 0:表示低电平,也就是对应我们电路的 GND: 逻辑 1:表示高电平,也就是对应我们电路的 VCC: 逻辑 X:表示未知,有可能是高电平,也有可能是低电平: 逻辑 Z: ...

  9. 有效地使用计算机操作系统的教学设计与反思,《操作系统的基础知识(1)》教学设计及反思...

    教学目标 一.学习者分析 学生通过第一章的学习,对计算机的软.硬件知识有了初步的了解,同时对操作系统的作用也有了简单的认识.但由于学生普遍对计算机理论部分的知识不够重视,所以大部分学生对本节内容了解得 ...

  10. FPGA基础知识----第三章 第2节 综合和仿真

    第2节 综合和仿真 2.1 综合 Verilog 是硬件描述语言,顾名思义,就是用代码的形式描述硬件的功能,最终在硬件电路上实现该功能. 在 Verilog 描述出硬件功能后需要使用综合器对 Veri ...

最新文章

  1. 为什么你看了那么多面经,面试还是挂了?
  2. jar打包混淆上传全自动日志
  3. viper4android哪个版本好,VIPER4Android最新版本
  4. 一种常见的关于率指标的错误分析思路
  5. .net core 使用RSA获取私钥证书并签名
  6. 抽走超大桌布之后保持桌面物体不掉,需要多快的速度?
  7. 利用Hexo搭建个人博客-博客发布篇
  8. LeetCode: Single Number I II
  9. 死磕java_死磕 java同步系列之AQS起篇
  10. python dataset用法_dataset 用法(2)
  11. 支持向量机(Support Vector Machine,SVM)
  12. Android Studio中Spinner控件的使用方法2-2
  13. CentOS7部署YApi
  14. GIS空间分析 栅格数据分析2 成本距离分析
  15. python distribute包管理工具安装AttributeError错误
  16. 百度地图如何在html中显示图片,在网页中插入百度地图(实例)
  17. SyntaxHighlighter使用方法
  18. 2021下半年软考成绩什么时候出?
  19. Python SMTP 发送带附件电子邮件
  20. 《C++语言入门经典》一第1章 初识C++——“Hello World!” 1.1 C++的历史背景

热门文章

  1. PeopleSoft 登录页面更换
  2. 夜神模拟器 Nox Player 雷电模拟器 掉线 连不上 运行不显示的解决方案
  3. 初步探索C++深浅拷贝
  4. MOCTF-WRITE-UP(二)
  5. 2019-01-21-mqtt-mosquitto-启动Unable to load CA certificates
  6. 路径导航与启发式搜索
  7. 学会写作:自我进阶的高效方法
  8. mysql rman_利用RMAN把ORACLE10G64位降级为32位_MySQL
  9. python 卡方分布值_数据分析|抽样分布
  10. 1m照片的宽和高是多少_jpg图片容量1M是多少KB