赞
踩
特权同学《Verilog边码边学》,B站教学视频链接:101 组合逻辑与时序逻辑_哔哩哔哩_bilibili
目录
1、对FPGA系统时钟(频率较高)进行分频,产生分频时钟(频率较低)
2、分频时钟可以作为FPGA低速外设的同步时钟
IIC总线的时钟(≤400KHz)
低速SPI总线的时钟(≤1MHz)
3、对于频率较高的分频时钟,不能直接作为外设时钟或FPGA内部时钟使用,这类时钟应该由FPGA内部的PLL邓时钟管理单元产生
功能需求:输入时钟100MHz,产生一个1MHz的低频时钟
分析:
① 100MHz / 1MHz = 100,翻译一下就是每100个输入时钟周期是1个输出时钟周期
② 需要对100MHz时钟做100分频
③ 计数器循环计数周期为0-99,那么前50个输入时钟就是输出时钟的高电平,后50个时钟是输出时钟的低电平
代码实现:当计数器为0-49时输出高电平,计数器为50-99时输出低电平
-
- `timescale 1ns/1ps
-
- module vlg_design(
- input clk,
- input rst_n,
- output reg clk_1mhz
- );
-
- //`define CNT_MAX 100
- //`define CNT_MAX_DIV2 `CNT_MAX/2
-
- localparam CNT_MAX = 8'd100; //时钟为高电平
- localparam CNT_MAX_DIV2 = 8'd50; //时钟为高电平的一半
-
- reg[7:0] cnt; // 8bit计数器
-
- always @(posedge clk)
- //同步复位,当rst_n为低电平时复位
- if(!rst_n) cnt <= 8'd0;
- else if(cnt < (CNT_MAX-1)) cnt <= cnt+1'b1;
- else cnt <= 8'd0;
-
- always @(posedge clk)
- if(!rst_n) clk_1mhz <= 8'd0;
- else if(cnt < CNT_MAX_DIV2) clk_1mhz <= 1'b1;
- else clk_1mhz <= 1'b0;
-
- endmodule

结果展示
功能需求:输入时钟25MHz,产生一个400KHz的低频时钟
由于25MHz/400KHz=62.5,是小数分频,由于只能在上升沿或下降沿触发,所以只能等效为输入时钟的625个周期是输出时钟的10个周期,需要满足以下公式:
先做5次62分频,再做5次63分频,得到625个输入时钟周期,之后令分频时钟在625个分频时钟内跳变20次共10个周期。
可以取公约数,最终就是先做1次62分频(前31个输入时钟周期为高电平,后31个输入时钟周期为低电平),再做1次63分频(前31个输入时钟周期为高电平,后32个输入时钟周期为低电平),得到125个输入时钟周期,之后令分频时钟在125个分频时钟内跳变4次共2个周期。
这个方法被称作”双模前置小数分频“,其最重要的核心是M分频(62)和M+1分频(63)这个相近频率。
代码实现
-
- `timescale 1ns/1ps
-
- module vlg_design(
- input clk,
- input rst_n,
- output reg clk_400khz
- );
-
- //`define CNT_MAX 100
- //`define CNT_MAX_DIV2 `CNT_MAX/2
-
- localparam div_e = 8'd62; //62分频周期数,1个输出周期
- localparam div_o = 8'd63; //63分频周期数,1个输出周期
- localparam change = 8'd62; //电平转换
-
- reg[8:0] cnt; // 8bit计数器
- reg[8:0] cnt62; // 8bit计数器
- reg[8:0] cnt63; // 8bit计数器
-
- always @(posedge clk) begin
- //同步复位,当rst_n为低电平时复位
- if(!rst_n) begin
- cnt <= 8'd0;
- cnt62 <= 8'd0;
- cnt63 <= 8'd0;
- end
- else begin
- if(cnt < change) begin
- cnt62 <= cnt62 + 1'b1; //当cnt<62时,cnt62从0增加至61
- cnt <= cnt + 1'b1;
- end
- else begin
- if(cnt63 == div_o - 1) cnt63 <= 8'd0;
- else cnt63 <= cnt63 + 1'b1; //当cnt≥62时,cnt63从0增加至62
- end
- end
- end
-
- always @(posedge clk) begin
- if(!rst_n) begin
- clk_400khz <= 1'b0;
- end
- else begin
- if(cnt < change) begin
- if(cnt62 < 8'd31)
- clk_400khz <= 1'b1;
- else
- clk_400khz <= 1'b0;
- end
- else begin
- if(cnt63 < 8'd31)
- clk_400khz <= 1'b1;
- else
- clk_400khz <= 1'b0;
- end
- end
- end
-
- endmodule

结果展示
这里取了两个周期,2T=5us,400KHz的分频时钟周期为2.5us,可以得到仿真结果是正确的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。