赞
踩
Timer是数字电路的基础,所有器件都是在时钟节拍下工作,由于时钟节拍速率高,FPGA内部可以达到100M,有些低速的设备就需要进行分频处理,这就产生了计数的需求。不同的功能模块速率不同,自然也就需要不同的计数器。
分频器的关键是计算出源时钟频率与分频后的时钟频率的倍数关系,倍数除以2 就是计数最大值cnt。
module counter(Clk,Rst_n,Low_clock); input Clk; //系统时钟 input Rst_n; //全局复位,低电平复位 output reg Low_clock; //Low_clock输出 reg [14:0]cnt; //定义计数器寄存器 //计数器计数进程 always@(posedge Clk or negedge Rst_n) if(Rst_n == 1'b0) cnt <= 15'd0; else if(cnt == 15'd24_999) cnt <= 15'd0; else cnt <= cnt + 1'b1; //Low_clock输出控制进程 always@(posedge Clk or negedge Rst_n) if(Rst_n == 1'b0) Low_clock<= 1'b1; else if(cnt == 15'd24_999) Low_clock<= ~Low_clock; else Low_clock<= Low_clock; endmodule
在CPU系统中,有多个电压轨,主电源供电后,需要控制不同电压轨的上电时序,已确保系统正常启动。有时候为了保证供电的稳定,需要控制启动时CPU的复位时间。
设计目标就是在主电源上电后的多少ms内输出一个低电平,此后信号保持为高电平状态。
module rst_delay125ms( cpld_16MHz, rst_pld_n_delay ); input cpld_16MHz; output rst_pld_n_delay ; reg [24:0]delay_125ms_cunt = 25'b0; //计数器上电赋初始值 reg delay_125ms = 1'b0; //power_on 10ms delay generator always@(posedge cpld_16MHz) begin if (delay_10ms_cunt == 25'd2_000_000) //改变cunt的值即可实现任意时间长度控制 begin delay_125ms_cunt <= delay_125ms_cunt; delay_125ms <= 1'b1; end else begin delay_125ms_cunt <= delay_125ms_cunt +1; delay_125ms <= 1'b0; end end assign rst_pld_n_delay = delay_125ms? 1'b1: 1'b0; endmodule
该功能实现把单个时钟周期信号展宽为需要的时钟宽度信号,一般应用在片选、使能等信号上。
此例用到了参数定义语句,方便修改需要展宽的时间宽度,
仿真中为了便于观察,把此参数设为了16.
parameter CNT_MAX = 25’d8_000; //0.5ms
module rst_delay(Clk,Rst_n,Dog_rst_i,Dog_rst_delay_o); input Clk; //系统时钟,50M input Rst_n; //全局复位,低电平复位 input Dog_rst_i; output Dog_rst_delay_o; reg [24:0]cnt; //定义计数器寄存器 reg EN; parameter CNT_MAX = 25'd8_000; //0.5ms always@(posedge Clk or negedge Rst_n) if(!Rst_n) EN <= 1'b0; else if(Dog_rst_i) EN <= 1'b1; else if(cnt == CNT_MAX) EN <= 1'b0; else EN <= EN; assign Dog_rst_delay_o = EN; //计数器计数进程 always@(posedge Clk or negedge Rst_n ) if(Rst_n == 1'b0 ) cnt <= 25'd0; else if(cnt == CNT_MAX) cnt <= 25'd0; else if(EN) cnt <= cnt + 1'b1; else cnt <= cnt; endmodule
仿真图
脉宽展宽仅限于输入脉冲的宽度较窄的情况,如果输入信号是一个跳变,比如从低电平变到高电平,我们想通过此事件触发一个特定宽度的脉冲,那么只要把上面的程序稍作修改即可,计数器计数开始的条件改为输入脉冲,计到需要的脉宽后即停止,输出脉冲的起始时刻可以通过判断计数器的某一位来实现。
module rst_delay(Clk,Rst_n,Dog_rst_i,Dog_rst_delay_o); input Clk; //系统时钟,50M input Rst_n; //全局复位,低电平复位 input Dog_rst_i; output Dog_rst_delay_o; reg [24:0]cnt; //定义计数器寄存器 reg EN; parameter CNT_MAX = 25'd16; //0.5ms always@(posedge Clk or negedge Rst_n) if(!Rst_n) EN <= 1'b0; else if(cnt[1:0]==2'b11) //计数器的某位作为条件触发输出跳变 EN <= 1'b1; else if(cnt == CNT_MAX) //CNT_MAX 决定输出脉冲的宽度 EN <= 1'b0; else EN <= EN; assign Dog_rst_delay_o = EN; //计数器计数进程 always@(posedge Clk or negedge Rst_n ) if(Rst_n == 1'b0 ) cnt <= 25'd0; else if(cnt == CNT_MAX) // cnt <= 25'd0; cnt <= cnt; // else if(EN) else if(Dog_rst_i) //输入跳变触发计数 cnt <= cnt + 1'b1; // else // cnt <= cnt; endmodule
仿真图如下:
该功能主要实现两个信号控制另外一个信号,比如看门狗的打开、关闭,set/reset功能。
module rst_delay( Clk, Rst_n, SFTDog_open, SFTDog_close, SFTDog_en ); input Clk; input Rst_n; //全局复位,低电平复位 input SFTDog_open; // 打开 input SFTDog_close; //关闭 output reg SFTDog_en;//功能输出 always@(posedge Clk ) begin if(!Rst_n ) SFTDog_en<= 1'b0; else if(SFTDog_open) SFTDog_en<= 1'b1; else if(!SFTDog_close) SFTDog_en<= 1'b0; end endmodule
仿真图
PWM波形在很多领域都可以用得到,比如屏幕背光亮度控制、运动控制、开关电源设计等等领域。在下面的代码中首先对输入时钟进行分频,产生所需要的pwm频率;其次对分频后的时钟进行上升沿采样,采样的原理就是利用两个寄存器,分别缓冲分频信号,通过
assign pos_ege = tmp0_div_clk & !tmp1_div_clk;
可以实现上升沿的判断。
上升沿抓到后,启动pwm脉宽计数,一直计到所需要的脉宽。
module PWM(Clk,Rst_n,pwm); input Clk; //系统时钟 50MHz 20ns input Rst_n; //全局复位,低电平复位 output reg pwm; //led输出 reg div_clk; reg [24:0]cnt; //定义计数器寄存器 reg [24:0]pwm_cnt; //定义计数器寄存器 reg tmp0_div_clk,tmp1_div_clk; wire pos_ege; parameter CNT_MAX = 25'd2_499_999; // 0.05s 通过修改pwm_MAX,实现不同频率。 parameter pwm_MAX = 25'd100; // 0 < pwm_MAX < 2* CNT_MAX , 通过修改pwm_MAX,实现不同占空比。 //分频计数器计数进程 always@(posedge Clk or negedge Rst_n) if(Rst_n == 1'b0) cnt <= 25'd0; else if(cnt == CNT_MAX) cnt <= 25'd0; else cnt <= cnt + 1'b1; //div clock 输出控制进程 always@(posedge Clk or negedge Rst_n) if(Rst_n == 1'b0) div_clk <= 1'b0; else if(cnt == CNT_MAX) div_clk <= ~div_clk; //========================================================= // posedge detect always@(posedge Clk or negedge Rst_n) if(!Rst_n)begin tmp0_div_clk <= 1'b0; tmp1_div_clk <= 1'b0; end else begin tmp0_div_clk <= div_clk; tmp1_div_clk <= tmp0_div_clk; end assign pos_ege = tmp0_div_clk & !tmp1_div_clk; always@(posedge Clk or negedge Rst_n) if(!Rst_n) pwm <= 1'b0; else if(pos_ege) pwm <= 1'b1; else if(pwm_cnt == pwm_MAX) pwm <= 1'b0; //脉宽计数器计数进程 always@(posedge Clk or negedge Rst_n ) if(Rst_n == 1'b0 ) pwm_cnt <= 25'd0; else if(pwm_cnt == pwm_MAX) pwm_cnt <= 25'd0; else if(pwm) pwm_cnt <= pwm_cnt + 1'b1; endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。