野火FPGA学习--计数器

一、计数器

 

 计数器波形图:

verilog代码:

//2023/4/11 lzp 计数器实现
`timescale 1ns/1ns
module counter(
    input   wire        sys_clk,
    input   wire        sys_rst_n,//_n表示低电平
    output  reg[1:0]    led_out //用always赋值,所以要用reg
);

parameter   CNT_MAX = 25_000_000 - 1;

reg[24:0]   cnt;
reg         flag;

//异步复位,使用异步复位更好
//cnt计数
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n) begin
    cnt <= 1'b0;
end
else begin
    if(cnt == CNT_MAX) begin
        cnt <= 0;
    end
    else begin
        cnt <= cnt + 1;
    end
end

always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n) begin
    led_out <= 2'b01;
    flag <= 1'b0;
end
else begin
    if(cnt == CNT_MAX) begin
        flag <= flag + 1;
        case(flag) 
            0: led_out <= 2'b01;
            1: led_out <= 2'b10;
            default: led_out <= 2'b00;
        endcase
    end
end

endmodule

/* module counter_tb();

reg        sys_clk;
reg        sys_rst_n;//_n表示低电平
wire[1:0]    led_out; //用always赋值,所以要用reg\
    
counter counter(
    sys_clk,
    sys_rst_n,
    led_out
);
    
initial begin
    sys_clk = 0;
    sys_rst_n <= 0;
    #20
    sys_rst_n <= 1;
end    

always#10 sys_clk = ~sys_clk;

endmodule */

管脚绑定:

 上板调试:

 烧录后即可看到D6和D7led分别闪烁:

二、分频器

1.  偶分频

分配器基于计数器的实现。

 六分频波形图:

verilog代码:

//2023/4/11 lzp 六分频
`timescale 1ns/1ns
module counter(
    input   wire        sys_clk,
    input   wire        sys_rst_n,
    output  reg         six_clk
);

parameter   CNT_MAX = 3 - 1;

reg[1:0]    cnt;

//异步复位,使用异步复位更好
//cnt计数
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n) begin
    cnt <= 1'b0;
end
else begin
    if(cnt == CNT_MAX) begin
        cnt <= 0;
    end
    else begin
        cnt <= cnt + 1;
    end
end

always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n) begin
    six_clk <= 1'b0;
end
else begin
    if(cnt == CNT_MAX) begin
        six_clk <= ~six_clk;
    end
end

endmodule

module counter_tb();

reg        sys_clk;
reg        sys_rst_n;//_n表示低电平
wire       six_clk;

counter counter(
    sys_clk,
    sys_rst_n,
    six_clk
);
    
initial begin
    sys_clk = 0;
    sys_rst_n <= 0;
    #20
    sys_rst_n <= 1;
end    

always#10 sys_clk = ~sys_clk;

endmodule

 仿真波形图:

但这样设计出来的分频是有问题的,在高速系统中不能保证时钟到达每个寄存器的时间是相同的,所以需要进行改进:

 改进版verilog:

//2023/4/11 lzp 六分频
`timescale 1ns/1ns
module counter(
    input   wire        sys_clk,
    input   wire        sys_rst_n,
    output  reg         six_clk
);

parameter   CNT_MAX = 6 - 1;

reg[2:0]    cnt;

//异步复位,使用异步复位更好
//cnt计数
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n) begin
    cnt <= 1'b0;
end
else begin
    if(cnt == CNT_MAX) begin
        cnt <= 0;
    end
    else begin
        cnt <= cnt + 1;
    end
end

always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n) begin
    six_clk <= 1'b0;
end
else begin
    if(cnt == CNT_MAX) begin
        six_clk <= 1;
    end
    else begin
        six_clk <= 0;
    end
end

endmodule

module counter_tb();

reg        sys_clk;
reg        sys_rst_n;//_n表示低电平
wire       six_clk;

counter counter(
    sys_clk,
    sys_rst_n,
    six_clk
);
    
initial begin
    sys_clk = 0;
    sys_rst_n <= 0;
    #20
    sys_rst_n <= 1;
end    

always#10 sys_clk = ~sys_clk;

endmodule

 波形图:

两者方法的对比如下,一个使用输出的时钟作为触发,一个还是使用系统时钟clk作为触发:

 

 2. 奇分频

如果使用奇分频的话,实现要稍微比偶分频复杂一点(因为要保持50%的占空比),下面是五分频的占空比:

实现方法是将上升沿触发得到的clk_out和下降沿得到的clk_out进行或操作,即可得到最后的百分之50的占空比的输出信号。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值