HDLBits练习——Counters

1.Count15(16进制同步复位计数器)

module top_module (
    input clk,
    input reset,      // Synchronous active-high reset
    output [3:0] q);

    always @ (posedge clk) begin
        if(reset)
            q <= 0;
        else
            q <= q + 1'b1;
    end
    
endmodule

2.Decade counter(十进制计数器)

module top_module (
    input clk,
    input reset,        // 同步 active-high reset
    output [3:0] q);

    always @ (posedge clk) begin
        if(reset)
            q <= 0;
        else if(q < 4'd9)
            q <= q + 1'b1;
        else
            q <= 0;   
    end
    
endmodule

3.Decade counter again

module top_module (
    input clk,
    input reset,
    output [3:0] q);

    always @ (posedge clk) begin
        if(reset)
            q <= 1;
        else if(q < 4'd10)
            q <= q + 1'b1;
        else
            q <= 1;
    end
    
endmodule

4.slow decade counter

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);

    reg [3:0] cnt;
    always @ (posedge clk) begin
        if(reset)
            cnt <= 0;
        else if(slowena) begin
            if(cnt == 4'd9)
                cnt <= 0;     //从0-9计数,周期为10,则9过后应该为0 
            else
                cnt <= cnt + 1'b1;
        end
    end
    assign q = cnt;
    
endmodule

5.counter 1-12


提供了模块count4,可以直接例化,但是本题主要考虑对于四位计数器的理解,时钟和使能信号都很好理解,但是对于load信号,其代表的是重新加载,即回到初始值,那么就存在两种情况,一是有效置位reset==1’b1,二是计数循环结束并可以开始下一循环,即Q值达到4’d12并且使能信号enable为1’b1,两种情况为或关系;对于d信号而言,其在load信号有效时值为4‘d1,其余情况为任意值即可。来源博客

module top_module (
    input clk,
    input reset,
    input enable,
    output [3:0] Q,
    output c_enable,
    output c_load,
    output [3:0] c_d
); 

    assign c_enable=enable;
    assign c_load=(reset|(Q==4'd12&enable))?1'b1:1'b0;
    assign c_d=c_load?4'b1:Q;
    count4 instance1(clk,c_enable,c_load,c_d,Q);

endmodule

6.counter1000(分频)


从 1000 Hz 时钟中,导出一个1 Hz 信号,称为 OneHertz,可用于驱动一组小时/分钟/秒计数器的使能信号以创建数字挂钟。由于我们希望时钟每秒计数一次,因此必须每秒正好对OneHertz信号进行一个周期的置位。使用模10(BCD)计数器和尽可能少的其他门构建分频器。同时从您使用的每个 BCD 计数器输出使能信号(最快的计数器c_enable[0],最慢的计数器c_enable[2])

题目使用3个0-9的计数器来实现时钟分频功能。若仅使用一个bcdcount分频,每计数10次,OneHertz输出为高,那么可以实现10分频,即100Hz。如果counter0每计数10次,counter1计数1次,那么counter1计数10次时OneHertz为高,则可以实现100分频,即10Hz。同理,三个bcdcount可以实现1000分频,即1Hz。
采用组合逻辑电路使能三个bcdcount,容易理解,reset不为1时,counter0始终在计数,c_enable[0]=1’b1;
仅当counter0计数10次(q0=4’d9)时,counter1计数1次,也就是counter0计数10个时钟周期后,下一时钟周期counter1计数,c_enable[1]=1’b1;
当counter1计数10次时(q1=4’d9),counter1会保存q1=4’d9十个时钟周期才会变回0,即需要counter0=4’d9才会再次变化。所以counter2有效的时钟周期为counter1=4’d9的情况下,counted0=4’d9的下一时钟周期。所以q1=4’d9 && q0=4’d9时c_enable[2]=1’b1。
根据最终得到的波形图可以看到,要求的OneHertz输出并不是频率为1Hz、占空比为50%的时钟,而是频率为1Hz、宽度为一个clk时钟周期的的脉冲。所以,OneHertz为高的条件为q2=4’d9 && q1=4’d9 && q0=4’d9。原文分析链接

module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); 
    reg [3:0] q0,q1,q2;
    always @(*) begin
        if(reset) begin
            c_enable <= 3'b000;
        end
        else begin
            c_enable[0] = 1'b1;
            if(q0==4'd9) 
                c_enable[1] = 1'b1;
            else 
                c_enable[1] = 1'b0;
            if(q1==4'd9 && q0==4'd9)
                c_enable[2] = 1'b1;
            else 
                c_enable[2] = 1'b0;       
        end
    end
    assign OneHertz = (q2==4'd9 && q1==4'd9 && q0==4'd9);   
    bcdcount counter0 (clk, reset, c_enable[0],q0);
    bcdcount counter1 (clk, reset, c_enable[1],q1);
    bcdcount counter2 (clk, reset, c_enable[2],q2);
   
endmodule

7.4-digit decimal counter(多位bcd十进制计数器)


16个bit的变量分为四段,从低到高每段分别计数,其中对于每段信号的状态而言,有三个可能,一是无进位信号保持计数值不变,二是有进位信号且计数值小于4’h9,因此计数值+1’b1,三是有进位信号但计数值达到4’h9,循环结束回到初始值4’h0;对于进位信号ena而言,需要注意两点,一是进位信号的判断值在循环结束的前一个状态即4’h8、8’h98和12’h998,因为这样才能在时钟触发的时候正常计数,二是进位需要在无效置位情况下发生,因此每一项都要与上~reset。

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);

    always @ (posedge clk) begin
        ena<={~reset&q[11:0]==12'h998,~reset&q[7:0]==8'h98,~reset&q[3:0]==4'h8};
        if(reset) begin 
            q<=16'd0;        
        end
        else begin            
            q[3:0]<=(q[3:0]<4'h9)?q[3:0]+1'b1:4'h0;
            q[7:4]<=(!ena[1])?q[7:4]:(q[7:4]<4'h9)?q[7:4]+1'b1:4'h0;
            q[11:8]<=(!ena[2])?q[11:8]:(q[11:8]<4'h9)?q[11:8]+1'b1:4'h0;
            q[15:12]<=(!ena[3])?q[15:12]:(q[15:12]<4'h9)?q[15:12]+1'b1:4'h0;
        end
    end
    
endmodule

8.12 hours clock


总共需要用到6个BCD counter,表示时、分、秒各两个,时从01计到12,分从00计到59,秒从00计到59;复位时显示AM 12:00:00;复位的优先级高于enable,也就是说,即使enable为0,只要复位,也要显示AM 12:00:00。

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 

    reg [3:0] ss0,ss1,mm0,mm1,hh1,hh0;
    reg [3:0] state;
    
    always @ (posedge clk) begin
        if(reset)
            ss0 <= 4'd0;
        else if(ena) begin
            if(ss0 == 4'd9)
                ss0 <= 4'd0;
            else
                ss0 <= ss0 + 4'd1;
        end
        else
            ss0 <= ss0;
    end
    
    always @ (posedge clk) begin
        if(reset)
            ss1 <= 4'd0;
        else if(ss1 == 4'd5) begin
            if(ss0 == 4'd9 && ena)
                ss1 <= 4'd0;
            else
                ss1 <= ss1;
        end
        else begin
            if(ss0 == 4'd9 && ena)
                ss1 <= ss1 + 4'd1;
            else
                ss1 <= ss1;
        end
    end
    
    always @ (posedge clk) begin
        if(reset)
            mm0 <= 4'd0;
        else if(mm0 == 4'd9) begin
            if(ss1 == 4'd5 && ss0 == 4'd9)
                mm0 <= 4'd0;
            else
                mm0 <= mm0;
        end
        else begin
            if(ss1 == 4'd5 && ss0 == 4'd9)
                mm0 <= mm0 + 4'd1;
            else
                mm0 <= mm0;
        end
    end
    
    always @ (posedge clk) begin
        if(reset)
            mm1 <= 4'd0;
        else if(mm1 == 4'd5) begin
            if(mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd9)
                mm1 <= 4'd0;
            else
                mm1 <= mm1;
        end
        else begin
            if(mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd9)
                mm1 <= mm1 + 4'd1;
            else
                mm1 <= mm1;
        end
    end
    
    always @ (posedge clk) begin
        if(reset) begin
            state <= 4'd0;
            hh1 <= 4'd1;
            hh0 <= 4'd2;
        end
        else begin
            case(state)
                4'd0:begin
                    hh1 <= 4'd1;
                    hh0 <= 4'd2;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd1;
                end
                4'd1:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd1;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd2;
                end
                4'd2:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd2;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd3;
                end
                4'd3:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd3;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd4;
                end
                4'd4:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd4;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd5;
                end
                4'd5:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd5;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd6;
                end
                4'd6:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd6;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd7;
                end
                4'd7:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd7;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd8;
                end
                4'd8:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd8;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd9;
                end
                4'd9:begin
                    hh1 <= 4'd0;
                    hh0 <= 4'd9;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd10;
                end
                4'd10:begin
                    hh1 <= 4'd1;
                    hh0 <= 4'd0;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd11;
                end
                4'd11:begin
                    hh1 <= 4'd1;
                    hh0 <= 4'd1;
                    if(mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd8)
                        state <= 4'd0;
                end
                default:begin
                    state <= 4'd0;
                    hh1 <= 4'd1;
                    hh0 <= 4'd2;
                end
            endcase
        end
    end
    
    assign hh = {hh1,hh0};
    assign mm = {mm1,mm0};
    assign ss = {ss1,ss0};
    
    always @ (posedge clk) begin
        if(reset)
            pm <= 1'b0;
        else if(hh1 == 4'd1 && hh0 == 4'd1 && mm1 == 4'd5 && mm0 == 4'd9 && ss1 == 4'd5 && ss0 == 4'd9)
            pm <= ~pm;
        else
            pm <= pm;
    end
    
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值